Common subdirectories: kicker/ui/.deps and kicker/ui/.deps
Common subdirectories: kicker/ui/CVS and kicker/ui/CVS
diff -Nup kicker/ui/Makefile.am kicker/ui/Makefile.am
--- kicker/ui/Makefile.am	2005-04-15 01:16:06.000000000 +0200
+++ kicker/ui/Makefile.am	2005-05-03 09:58:16.000000000 +0200
@@ -10,7 +10,7 @@ libkicker_ui_la_SOURCES = addbutton_mnu.
         addcontainer_mnu.cpp recentapps.cpp browser_dlg.cpp \
         removeapplet_mnu.cpp removeextension_mnu.cpp removecontainer_mnu.cpp \
         addspecialbutton_mnu.cpp removespecialbutton_mnu.cpp \
-        removebutton_mnu.cpp popupmenutitle.cpp hidebutton.cpp
+        removebutton_mnu.cpp popupmenutitle.cpp hidebutton.cpp clicklineedit.cpp
 
 libkicker_ui_la_LIBADD = $(top_builddir)/libkonq/libkonq.la $(top_builddir)/kdmlib/libdmctl.la
 
@@ -23,7 +23,7 @@ noinst_HEADERS = addbutton_mnu.h addappl
 		addcontainer_mnu.h recentapps.h browser_dlg.h \
 		removeapplet_mnu.h removeextension_mnu.h removecontainer_mnu.h \
 		addspecialbutton_mnu.h removespecialbutton_mnu.h \
-		removebutton_mnu.h popupmenutitle.h hidebutton.h
+		removebutton_mnu.h popupmenutitle.h hidebutton.h clicklineedit.h
 
 removecontainer_mnu.lo: ../share/kickerSettings.h
 removeextension_mnu.lo: ../share/kickerSettings.h
@@ -34,6 +34,4 @@ k_mnu.lo: ../share/kickerSettings.h
 removecontainer_mnu.lo: ../core/extensionSettings.h
 removeextension_mnu.lo: ../core/extensionSettings.h
 service_mnu.lo: ../share/kickerSettings.h
-browser_mnu.lo: ../share/kickerSettings.h
-recentapps.lo: ../share/kickerSettings.h
 
diff -Nup kicker/ui/clicklineedit.cpp kicker/ui/clicklineedit.cpp
--- kicker/ui/clicklineedit.cpp	1970-01-01 01:00:00.000000000 +0100
+++ kicker/ui/clicklineedit.cpp	2005-05-03 09:58:16.000000000 +0200
@@ -0,0 +1,85 @@
+/*
+    This file is part of libkdepim.
+    Copyright (c) 2004 Daniel Molkentin <molkentin@kde.org>
+    based on code by Cornelius Schumacher <schumacher@kde.org> 
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+    Boston, MA 02111-1307, USA.
+*/
+
+
+#include "clicklineedit.h"
+
+#include "qpainter.h"
+
+using namespace KPIM;
+
+ClickLineEdit::ClickLineEdit(QWidget *parent, const QString &msg, const char* name) :
+  KLineEdit(parent, name) 
+{
+  mDrawClickMsg = true;
+  setClickMessage( msg ); 
+}
+
+ClickLineEdit::~ClickLineEdit() {}
+
+
+void ClickLineEdit::setClickMessage( const QString &msg )
+{
+  mClickMessage = msg;
+  repaint();
+}
+
+void ClickLineEdit::setText( const QString &txt )
+{
+  mDrawClickMsg = txt.isEmpty();
+  repaint();
+  KLineEdit::setText( txt );
+}
+
+void ClickLineEdit::drawContents( QPainter *p )
+{
+  KLineEdit::drawContents( p );
+
+  if ( mDrawClickMsg == true && !hasFocus() ) {
+    QPen tmp = p->pen();
+    p->setPen( gray );
+    QRect cr = contentsRect();
+    p->drawText( cr, AlignAuto|AlignVCenter, mClickMessage );
+    p->setPen( tmp );
+  }
+}
+
+void ClickLineEdit::focusInEvent( QFocusEvent *ev )
+{
+  if ( mDrawClickMsg == true ) 
+  { 
+    mDrawClickMsg = false;
+    repaint();
+  }
+  QLineEdit::focusInEvent( ev );
+}
+
+void ClickLineEdit::focusOutEvent( QFocusEvent *ev )
+{
+  if ( text().isEmpty() )
+  {
+    mDrawClickMsg = true;
+    repaint();
+  }
+  QLineEdit::focusOutEvent( ev );
+}
+
+#include "clicklineedit.moc"
diff -Nup kicker/ui/clicklineedit.h kicker/ui/clicklineedit.h
--- kicker/ui/clicklineedit.h	1970-01-01 01:00:00.000000000 +0100
+++ kicker/ui/clicklineedit.h	2005-05-03 09:58:16.000000000 +0200
@@ -0,0 +1,63 @@
+/*
+    This file is part of libkdepim.
+    Copyright (c) 2004 Daniel Molkentin <molkentin@kde.org> 
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+    Boston, MA 02111-1307, USA.
+*/
+
+#ifndef CLICKLINEEDIT_H
+#define CLICKLINEEDIT_H
+
+#include <klineedit.h>
+#include <kdepimmacros.h>
+
+namespace KPIM {
+
+/** 
+  This class provides a KLineEdit which contains a greyed-out hinting
+  text as long as the user didn't enter any text
+
+  @short LineEdit with customizable "Click here" text
+  @author Daniel Molkentin
+*/
+class KDE_EXPORT ClickLineEdit : public KLineEdit
+{
+  Q_OBJECT
+  public:
+    ClickLineEdit( QWidget *parent, const QString &msg = QString::null, const char* name = 0 );
+    ~ClickLineEdit();
+
+    void setClickMessage( const QString &msg );
+    QString clickMessage() const { return mClickMessage; } 
+  
+    virtual void setText( const QString& txt );
+
+  protected:
+    virtual void drawContents( QPainter *p );
+    virtual void focusInEvent( QFocusEvent *ev );
+    virtual void focusOutEvent( QFocusEvent *ev );
+
+  private:
+    QString mClickMessage;
+    bool mDrawClickMsg;
+
+};
+
+}
+
+#endif // CLICKLINEEDIT_H
+
+
diff -Nup kicker/ui/k_mnu.cpp kicker/ui/k_mnu.cpp
--- kicker/ui/k_mnu.cpp	2005-04-28 00:48:39.000000000 +0200
+++ kicker/ui/k_mnu.cpp	2005-05-03 09:58:16.000000000 +0200
@@ -26,9 +26,13 @@ CONNECTION WITH THE SOFTWARE OR THE USE 
 #include <unistd.h>
 #include <dmctl.h>
 
+#include <qhbox.h>
 #include <qimage.h>
+#include <qlabel.h>
 #include <qpainter.h>
 #include <qstyle.h>
+#include <qtimer.h>
+#include <qtooltip.h>
 
 #include <dcopclient.h>
 #include <kapplication.h>
@@ -40,9 +44,11 @@ CONNECTION WITH THE SOFTWARE OR THE USE 
 #include <kglobal.h>
 #include <kglobalsettings.h>
 #include <kiconloader.h>
+#include <klineedit.h>
 #include <klocale.h>
 #include <kmessagebox.h>
 #include <kstandarddirs.h>
+#include <ktoolbarbutton.h>
 #include <kwin.h>
 
 #include "client_mnu.h"
@@ -55,9 +61,12 @@ CONNECTION WITH THE SOFTWARE OR THE USE 
 #include "popupmenutitle.h"
 #include "quickbrowser_mnu.h"
 
+#include "clicklineedit.h"
 #include "k_mnu.h"
 #include "k_mnu.moc"
 
+const int PanelKMenu::searchLineID(23140 /*whatever*/);
+
 PanelKMenu::PanelKMenu()
   : PanelServiceMenu(QString::null, QString::null, 0, "KMenu")
   , bookmarkMenu(0)
@@ -140,6 +149,26 @@ void PanelKMenu::paletteChanged()
     }
 }
 
+
+/* A MenuHBox is supposed to be inserted into a menu.
+ * You can set a special widget in the hbox which will
+ * get the focus if the user moves up or down with the 
+ * cursor keys
+ */ 
+class MenuHBox : public QHBox {
+public:
+    MenuHBox(PanelKMenu* parent) : QHBox(parent)
+    {
+    }
+    
+    virtual void keyPressEvent(QKeyEvent *e)
+    {
+        
+    }
+private:
+    PanelKMenu *parent;
+};
+
 void PanelKMenu::initialize()
 {
 //    kdDebug(1210) << "PanelKMenu::initialize()" << endl;
@@ -166,13 +195,29 @@ void PanelKMenu::initialize()
     // add services
     PanelServiceMenu::initialize();
 
+    // Insert search field
+    QHBox* hbox = new QHBox( this );
+    KToolBarButton *clearButton = new KToolBarButton( "locationbar_erase", 0, hbox );
+    searchEdit = new KPIM::ClickLineEdit(hbox, " "+i18n("Press '/' to search..."));
+    hbox->setFocusPolicy(QWidget::StrongFocus);
+    hbox->setFocusProxy(searchEdit);
+    hbox->setSpacing( 3 );
+    connect(clearButton, SIGNAL(clicked()), searchEdit, SLOT(clear()));
+    connect(this, SIGNAL(aboutToHide()), this, SLOT(slotClearSearch())); 
+    connect(searchEdit, SIGNAL(textChanged(const QString&)),
+        this, SLOT( slotUpdateSearch( const QString&)));
+    insertItem(hbox, searchLineID, 0);
+
+    //QToolTip::add(clearButton, i18n("Clear search"));
+    //QToolTip::add(searchEdit, i18n("Enter the name of an application"));
+
     if (KickerSettings::showMenuTitles())
     {
         int id;
         id = insertItem(new PopupMenuTitle(i18n("All Applications"), font()), -1 /* id */, 0);
-        setItemEnabled( id, false );
+        setItemEnabled(id, false);
         id = insertItem(new PopupMenuTitle(i18n("Actions"), font()), -1 /* id */, -1);
-        setItemEnabled( id, false );
+        setItemEnabled(id, false);
     }
 
     // create recent menu section
@@ -303,7 +348,7 @@ void PanelKMenu::initialize()
 
         if (KickerSettings::menuEntryHeight() > -1)
         {
-            insertItem(SmallIconSet("switchuser", KickerSettings::menuEntryHeight()),
+            insertItem(/*SmallIconSet("", KickerSettings::menuEntryHeight())),*/
                        i18n("Switch User"),
                        sessionsMenu);
         }
@@ -442,8 +487,8 @@ void PanelKMenu::slotSessionActivated( i
         doNewSession( true );
     else if (ent == 101)
         doNewSession( false );
-    else if (!sessionsMenu->isItemChecked( ent ))
-        DM().lockSwitchVT( ent );
+    else
+        DM().switchVT( ent );
 }
 
 void PanelKMenu::doNewSession( bool lock )
@@ -621,3 +666,44 @@ void PanelKMenu::mouseMoveEvent(QMouseEv
     QMouseEvent newEvent = translateMouseEvent(e);
     PanelServiceMenu::mouseMoveEvent( &newEvent );
 }
+
+void PanelKMenu::slotUpdateSearch(const QString& searchString)
+{
+    kdDebug() << "Searching for " << searchString << endl;
+    setSearchString(searchString);
+}
+
+void PanelKMenu::slotClearSearch()
+{
+    if (searchEdit && searchEdit->text().isEmpty() == false) {
+        QTimer::singleShot(0, searchEdit, SLOT(clear()));
+    }
+}
+
+void PanelKMenu::keyPressEvent(QKeyEvent* e)
+{
+    // We move the focus to the search field if the
+    // user presses '/'. This is the same shortcut as
+    // konqueror is using, and afaik it's hardcoded both
+    // here and there. This sucks badly for many non-us
+    // keyboard layouts, but for the sake of consistency
+    // we follow konqueror.
+    if (!searchEdit) return KPanelMenu::keyPressEvent(e);
+
+    if (e->key() == Qt::Key_Slash && !searchEdit->hasFocus()) {
+        if (indexOf(searchLineID) >=0 ) {
+            setActiveItem(indexOf(searchLineID));
+        }
+    }
+    else if (e->key() == Qt::Key_Escape && searchEdit->text().isEmpty() == false) {
+        searchEdit->clear();
+    }
+    else if (e->key() == Qt::Key_Delete && !searchEdit->hasFocus() && 
+        searchEdit->text().isEmpty() == false)
+    {
+        searchEdit->clear();
+    }
+    else {
+        KPanelMenu::keyPressEvent(e);
+    }
+}
diff -Nup kicker/ui/k_mnu.h kicker/ui/k_mnu.h
--- kicker/ui/k_mnu.h	2005-02-23 00:41:46.000000000 +0100
+++ kicker/ui/k_mnu.h	2005-05-03 09:58:16.000000000 +0200
@@ -29,6 +29,11 @@ CONNECTION WITH THE SOFTWARE OR THE USE 
 
 #include "service_mnu.h"
 
+namespace KPIM {
+    // Yes, ClickLineEdit was copied from libkdepim.
+    // Can we have it in kdelibs please?
+    class ClickLineEdit;
+}
 class KickerClientMenu;
 class KBookmarkMenu;
 class KActionCollection;
@@ -66,6 +71,8 @@ protected slots:
     void slotSaveSession();
     void slotRunCommand();
     void slotEditUserContact();
+    void slotUpdateSearch(const QString &searchtext);
+    void slotClearSearch();
     void paletteChanged();
 
 protected:
@@ -78,6 +85,8 @@ protected:
     void mouseMoveEvent(QMouseEvent *);
     bool loadSidePixmap();
     void doNewSession( bool lock );
+    void filterMenu(PanelServiceMenu* menu, const QString &searchString);
+    void keyPressEvent(QKeyEvent* e);
 
 private:
     QPopupMenu                 *sessionsMenu;
@@ -89,6 +98,8 @@ private:
     KBookmarkMenu              *bookmarkMenu;
     KActionCollection          *actionCollection;
     KBookmarkOwner             *bookmarkOwner;
+    KPIM::ClickLineEdit        *searchEdit;
+    static const int            searchLineID;
 };
 
 #endif
diff -Nup kicker/ui/service_mnu.cpp kicker/ui/service_mnu.cpp
--- kicker/ui/service_mnu.cpp	2005-04-06 00:49:25.000000000 +0200
+++ kicker/ui/service_mnu.cpp	2005-05-03 11:55:44.000000000 +0200
@@ -25,6 +25,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE 
 #include <qcursor.h>
 #include <qpixmap.h>
 #include <qimage.h>
+#include <qmap.h>
 
 #include <dcopclient.h>
 #include <kapplication.h>
@@ -60,11 +61,12 @@ const int kRecentMenusOffset = 1001;
 // static object that stores "recent" history
 static RecentlyLaunchedApps s_RecentApps;
 
+#define __min( x, y ) ( x > y ? y : x )
+
 PanelServiceMenu::PanelServiceMenu(const QString & label, const QString & relPath, QWidget * parent,
-                                   const char * name, bool addmenumode, const QString & insertInlineHeader)
+                                   const char * name, bool addmenumode)
     : KPanelMenu(label, parent, name),
       relPath_(relPath),
-      insertInlineHeader_( insertInlineHeader ),
       clearOnClose_(false),
       addmenumode_(addmenumode),
       popupMenu_(0)
@@ -232,15 +234,45 @@ void PanelServiceMenu::initialize()
     doInitialize();
 }
 
-void PanelServiceMenu::fillMenu(KServiceGroup::Ptr& _root,
-                                KServiceGroup::List& _list,
-                                const QString& /* _relPath */,
-                                int& id)
+void PanelServiceMenu::doInitialize(int index)
 {
-    QStringList suppressGenericNames = _root->suppressGenericNames();
+    // Set the startposition outside the panel, so there is no drag initiated
+    // when we use drag and click to select items. A drag is only initiated when
+    // you click to open the menu, and then press and drag an item.
+    startPos_ = QPoint(-1,-1);
 
-    KServiceGroup::List::ConstIterator it = _list.begin();
-    for (; it != _list.end(); ++it) {
+    // We ask KSycoca to give us all services (sorted).
+    KServiceGroup::Ptr root = KServiceGroup::group(relPath_);
+
+    if (!root || !root->isValid())
+        return;
+
+    KServiceGroup::List list = root->entries(true,
+                                   excludeNoDisplay_,
+                                   true,
+                                   KickerSettings::detailedMenuEntries() &&
+                                   !KickerSettings::detailedEntriesNamesFirst());
+
+    if (list.isEmpty()) {
+        setItemEnabled(insertItem(i18n("No Entries")), false);
+        return;
+    }
+
+    int id = idStart;
+    if (addmenumode_) {
+        int mid = insertItem(SmallIconSet("ok"), i18n("Add This Menu"), id++);
+        entryMap_.insert(mid, static_cast<KSycocaEntry*>(root));
+
+        if (list.count() > 0) {
+            insertSeparator();
+            id++;
+        }
+    }
+
+    QStringList suppressGenericNames = root->suppressGenericNames();
+
+    KServiceGroup::List::ConstIterator it = list.begin();
+    for (; it != list.end(); ++it) {
 
         KSycocaEntry * e = *it;
 
@@ -249,72 +281,35 @@ void PanelServiceMenu::fillMenu(KService
             KServiceGroup::Ptr g(static_cast<KServiceGroup *>(e));
             QString groupCaption = g->caption();
 
-           // Avoid adding empty groups.
+            // Avoid adding empty groups.
             KServiceGroup::Ptr subMenuRoot = KServiceGroup::group(g->relPath());
+            if (subMenuRoot->childCount() == 0)
+                continue;
 
-            int nbChildCount = subMenuRoot->childCount();
-            if ( nbChildCount == 0 && !g->showEmptyMenu())
+            // Ignore dotfiles.
+            if ((g->name().at(0) == '.'))
                 continue;
 
-	    QString inlineHeaderName = g->showInlineHeader() ? groupCaption : "";
             // Item names may contain ampersands. To avoid them being converted
             // to accelerators, replace them with two ampersands.
             groupCaption.replace("&", "&&");
 
-            if ( nbChildCount == 1 && g->allowInline() && g->inlineAlias())
-            {
-                KServiceGroup::Ptr element = KServiceGroup::group(g->relPath());
-                if ( element )
-                {
-                    //just one element
-                    KServiceGroup::List listElement = element->entries(true, excludeNoDisplay_, true, KickerSettings::menuEntryFormat() == KickerSettings::DescriptionAndName || KickerSettings::menuEntryFormat() == KickerSettings::DescriptionOnly);
-                    KSycocaEntry * e1 = *( listElement.begin() );
-                    if ( e1->isType( KST_KService ) )
-                    {
-                        KService::Ptr s(static_cast<KService *>(e1));
-                        insertMenuItem(s, id++, -1, &suppressGenericNames,g->caption());
-                        continue;
-                    }
-                }
-            }
-            if ( g->allowInline() && ( ( nbChildCount <= g->inlineValue() ) ||   ( g->inlineValue()==0 ) ))
-            {
-                //inline all entries
-                KServiceGroup::Ptr rootElement = KServiceGroup::group(g->relPath());
-
-                if (!rootElement || !rootElement->isValid())
-                    break;
-
-                KServiceGroup::List listElement = rootElement->entries(true, excludeNoDisplay_, true, KickerSettings::menuEntryFormat() == KickerSettings::DescriptionAndName || KickerSettings::menuEntryFormat() == KickerSettings::DescriptionOnly);
-
-                if ( !g->inlineAlias() && !inlineHeaderName.isEmpty() )
-                {
-                    int mid = insertItem(new PopupMenuTitle(inlineHeaderName, font()), id + 1, id++);
-                    setItemEnabled( mid, false );
-                }
-
-                fillMenu( rootElement, listElement,  g->relPath(), id );
-                continue;
-            }
-            // Ignore dotfiles.
-            if ((g->name().at(0) == '.'))
-                continue;
             PanelServiceMenu * m =
-                newSubMenu(g->name(), g->relPath(), this, g->name().utf8(), inlineHeaderName);
+                newSubMenu(g->name(), g->relPath(), this, g->name().utf8());
             m->setCaption( groupCaption );
 
             QIconSet iconset;
 
             if (KickerSettings::menuEntryHeight() > 0)
             {
-                iconset = KGlobal::iconLoader()->loadIconSet(
+                iconset = KGlobal::instance()->iconLoader()->loadIconSet(
                                                             g->icon(),
                                                             KIcon::NoGroup,
                                          KickerSettings::menuEntryHeight());
             }
             else if (KickerSettings::menuEntryHeight() == 0)
             {
-                QPixmap normal = KGlobal::iconLoader()->loadIcon(
+                QPixmap normal = KGlobal::instance()->iconLoader()->loadIcon(
                                                             g->icon(),
                                                             KIcon::Small,
                                                             0,
@@ -322,7 +317,7 @@ void PanelServiceMenu::fillMenu(KService
                                                             0L,
                                                             true);
 
-                QPixmap active = KGlobal::iconLoader()->loadIcon(
+                QPixmap active = KGlobal::instance()->iconLoader()->loadIcon(
                                                             g->icon(),
                                                             KIcon::Small,
                                                             0,
@@ -345,14 +340,16 @@ void PanelServiceMenu::fillMenu(KService
                 iconset.setPixmap(active, QIconSet::Small, QIconSet::Active);
             }
 
-            int newId = insertItem(iconset, groupCaption, m, id++);
+            int newId = insertItem(iconset, groupCaption, m, id++, index++);
             entryMap_.insert(newId, static_cast<KSycocaEntry*>(g));
+            m_ids.append(newId);
             // We have to delete the sub menu our selves! (See Qt docs.)
             subMenus.append(m);
         }
         else if (e->isType(KST_KService)) {
             KService::Ptr s(static_cast<KService *>(e));
-            insertMenuItem(s, id++, -1, &suppressGenericNames);
+            m_ids.append( id );
+            insertMenuItem(s, id++, index++, &suppressGenericNames);
         }
         else if (e->isType(KST_KServiceSeparator)) {
             insertSeparator();
@@ -366,51 +363,8 @@ void PanelServiceMenu::fillMenu(KService
       if (KGlobalSettings::insertTearOffHandle())
         insertTearOffHandle();
 #endif
-
-}
-
-void PanelServiceMenu::doInitialize()
-{
-
-    // Set the startposition outside the panel, so there is no drag initiated
-    // when we use drag and click to select items. A drag is only initiated when
-    // you click to open the menu, and then press and drag an item.
-    startPos_ = QPoint(-1,-1);
-
-    // We ask KSycoca to give us all services (sorted).
-    KServiceGroup::Ptr root = KServiceGroup::group(relPath_);
-
-    if (!root || !root->isValid())
-        return;
-
-    KServiceGroup::List list = root->entries(true, excludeNoDisplay_, true, KickerSettings::menuEntryFormat() == KickerSettings::DescriptionAndName || KickerSettings::menuEntryFormat() == KickerSettings::DescriptionOnly);
-
-    if (list.isEmpty()) {
-        setItemEnabled(insertItem(i18n("No Entries")), false);
-        return;
-    }
-
-    int id = idStart;
-
-    if (addmenumode_) {
-        int mid = insertItem(SmallIconSet("ok"), i18n("Add This Menu"), id++);
-        entryMap_.insert(mid, static_cast<KSycocaEntry*>(root));
-
-        if (list.count() > 0) {
-            insertSeparator();
-            id++;
-        }
-    }
-    if ( !insertInlineHeader_.isEmpty() )
-    {
-        int mid = insertItem(new PopupMenuTitle(insertInlineHeader_, font()), -1, 0);
-        setItemEnabled( mid, false );
-    }
-    fillMenu( root, list, relPath_, id );
 }
 
-
-
 void PanelServiceMenu::configChanged()
 {
     s_RecentApps.m_bNeedToUpdate = false;
@@ -418,32 +372,21 @@ void PanelServiceMenu::configChanged()
     deinitialize();
 }
 
-void PanelServiceMenu::insertMenuItem(KService::Ptr & s, int nId,
-                                      int nIndex/*= -1*/,
-                                      const QStringList *suppressGenericNames /* = 0 */,
-                                      const QString & aliasname)
+void PanelServiceMenu::insertMenuItem(KService::Ptr & s, int nId, int nIndex/*= -1*/, const QStringList *suppressGenericNames /* = 0 */)
 {
-    QString serviceName = aliasname.isEmpty() ? s->name():aliasname;
+    QString serviceName = s->name();
     // add comment
-    QString comment = s->genericName();
-    if (!comment.isEmpty())
-    {
-        if (KickerSettings::menuEntryFormat() == KickerSettings::NameAndDescription)
-        {
-            if (!suppressGenericNames ||
-                !suppressGenericNames->contains(s->untranslatedGenericName()))
-            {
-                serviceName = QString("%1 (%2)").arg(serviceName).arg(comment);
-            }
-        }
-        else if (KickerSettings::menuEntryFormat() == KickerSettings::DescriptionAndName)
-        {
-            serviceName = QString("%1 (%2)").arg(comment).arg(serviceName);
-        }
-        else if (KickerSettings::menuEntryFormat() == KickerSettings::DescriptionOnly)
-        {
-            serviceName = comment;
-        }
+    if (KickerSettings::detailedMenuEntries()) {
+      QString comment = s->genericName();
+      if ( !comment.isEmpty() ) {
+        if (KickerSettings::detailedEntriesNamesFirst())
+        {
+          if (!suppressGenericNames || !suppressGenericNames->contains(s->untranslatedGenericName()))
+            serviceName = QString( "%1 (%2)" ).arg( serviceName ).arg( comment );
+        }
+        else
+          serviceName = QString( "%1 (%2)" ).arg( comment ).arg( serviceName );
+      }
     }
 
     // restrict menu entries to a sane length
@@ -468,14 +411,14 @@ void PanelServiceMenu::insertMenuItem(KS
 
     if (KickerSettings::menuEntryHeight() > 0)
     {
-        iconset = KGlobal::iconLoader()->loadIconSet(
+        iconset = KGlobal::instance()->iconLoader()->loadIconSet(
                                                             s->icon(),
                                                             KIcon::NoGroup,
                                           KickerSettings::menuEntryHeight());
     }
     else if (KickerSettings::menuEntryHeight() == 0)
     {
-        QPixmap normal = KGlobal::iconLoader()->loadIcon(
+        QPixmap normal = KGlobal::instance()->iconLoader()->loadIcon(
                                                             s->icon(),
                                                             KIcon::Small,
                                                             0,
@@ -483,7 +426,7 @@ void PanelServiceMenu::insertMenuItem(KS
                                                             0L,
                                                             true);
 
-        QPixmap active = KGlobal::iconLoader()->loadIcon(
+        QPixmap active = KGlobal::instance()->iconLoader()->loadIcon(
                                                             s->icon(),
                                                             KIcon::Small,
                                                             0,
@@ -838,9 +781,9 @@ void PanelServiceMenu::slotDragObjectDes
 }
 
 PanelServiceMenu *PanelServiceMenu::newSubMenu(const QString & label, const QString & relPath,
-                                               QWidget * parent, const char * name, const QString& _inlineHeader)
+                                               QWidget * parent, const char * name)
 {
-    return new PanelServiceMenu(label, relPath, parent, name, false,_inlineHeader);
+    return new PanelServiceMenu(label, relPath, parent, name);
 }
 
 void PanelServiceMenu::slotClearOnClose()
@@ -861,7 +804,7 @@ void PanelServiceMenu::slotClose()
         clearOnClose_ = false;
         slotClear();
     }
-
+    
     delete popupMenu_;
     popupMenu_ = 0;
 }
@@ -878,9 +821,122 @@ void PanelServiceMenu::slotClear()
     entryMap_.clear();
     KPanelMenu::slotClear();
     subMenus.clear();
+    m_ids.clear();
 }
 
 void PanelServiceMenu::selectFirstItem()
 {
     setActiveItem(indexOf(idStart));
 }
+
+void PanelServiceMenu::setSearchString(const QString &searchString)
+{
+    int idsize = m_ids.count();
+    int i, id = idStart;   
+    int index = 0;
+    QValueList<int>::ConstIterator it;
+
+    if ( m_ids.count() )
+        index = indexOf( m_ids.first() );
+
+    // first step is to clear the old search results
+    for ( it=m_ids.begin(); it!=m_ids.end(); ++it )
+    {
+        removeItem( *it );
+    }
+    m_ids.clear();
+
+    // We must initialize the menu, because it might have not been opened before
+    if ( searchString.isEmpty() ) 
+    {
+        doInitialize( index );
+        return;
+    }
+
+    KService::List list = findMatchingServices( searchString, QString::null );
+    KService::Ptr s;
+
+    for( i=0;i<__min((int)list.count(),idsize);i++ )
+    {
+        s = list[i];
+        m_ids.append( id );
+        insertMenuItem( s, id++, index++ );
+    }
+
+    for( ;i<idsize;i++ )
+    {
+        m_ids.append( id );
+        insertItem( QString::null, id++, index++ );
+        setItemEnabled( m_ids.last(), false );
+    }
+}
+
+bool PanelServiceMenu::hasSearchResults()
+{
+    return hasSearchResults_;
+}
+
+KService::List PanelServiceMenu::findMatchingServices( const QString & pattern, const QString & relPath ) 
+{
+    KServiceGroup::List::ConstIterator it;
+    KService::List results;
+
+    // Do not allow empty search strings
+    if ( pattern.isEmpty() )
+        return results;
+
+    // We ask KSycoca to give us all services (sorted).
+    KServiceGroup::Ptr root = KServiceGroup::group( relPath );
+
+    if (!root || !root->isValid())
+        return results;
+
+    KServiceGroup::List list = root->entries(true, true, true,
+                                               KickerSettings::detailedMenuEntries() &&
+                                               !KickerSettings::detailedEntriesNamesFirst());
+
+    QStringList suppressGenericNames = root->suppressGenericNames();
+
+    if (list.isEmpty())
+        return results;
+
+    for (it = list.begin(); it != list.end(); ++it) 
+    {
+        KSycocaEntry* e = *it;
+        if (e->isType(KST_KServiceGroup)) 
+        {
+
+            KServiceGroup::Ptr g(static_cast<KServiceGroup *>(e));
+
+            // Ignore dotfiles.
+            if ((g->name().at(0) == '.'))
+                continue;
+
+            // Avoid adding empty groups.
+            KServiceGroup::Ptr subMenuRoot = KServiceGroup::group(g->relPath());
+            if (subMenuRoot->childCount() == 0)
+                continue;
+
+            results += findMatchingServices( pattern, g->relPath() );
+        }
+        else if (e->isType(KST_KService)) 
+        {
+            KService::Ptr s(static_cast<KService *>(e));
+
+            // check wether this KService matches the users
+            // search string. We search case insensitive in:
+            // - Name 
+            // - Generic Name (e.g. "Mail Client")
+            // - Comment
+            // - Executable (e.g. "kmail")
+            if ( s->name().contains( pattern, false ) ||
+                 s->genericName().contains( pattern, false ) ||
+                 s->comment().contains( pattern, false ) ||
+                 s->exec().contains( pattern, false ) )
+                results.append( s );
+        }
+    }
+
+    return results;
+}
+
diff -Nup kicker/ui/service_mnu.h kicker/ui/service_mnu.h
--- kicker/ui/service_mnu.h	2005-03-17 00:39:55.000000000 +0100
+++ kicker/ui/service_mnu.h	2005-05-03 11:53:11.000000000 +0200
@@ -25,11 +25,12 @@ CONNECTION WITH THE SOFTWARE OR THE USE 
 #define SERVICE_MENU_H
 
 #include <qmap.h>
+#include <set>
 
 #include <ksycocaentry.h>
 #include <kservice.h>
 #include <kpanelmenu.h>
-#include <kservicegroup.h>
+
 /**
  * PanelServiceMenu is filled with KDE services and service groups. The sycoca
  * database is queried and the hierarchical structure built by creating child
@@ -40,8 +41,11 @@ CONNECTION WITH THE SOFTWARE OR THE USE 
  * @author Rik Hemsley <rik@kde.org>
  */
 
+class KLineEdit;
 typedef QMap<int, KSycocaEntry::Ptr> EntryMap;
 typedef QPtrList<QPopupMenu> PopupMenuList;
+class PanelServiceMenu;
+typedef QMap<PanelServiceMenu*,int> PanelServiceMenuMap;
 
 class KDE_EXPORT PanelServiceMenu : public KPanelMenu
 {
@@ -49,7 +53,7 @@ class KDE_EXPORT PanelServiceMenu : publ
 
 public:
     PanelServiceMenu(const QString & label, const QString & relPath,
-		     QWidget* parent  = 0, const char* name = 0, bool addmenumode = false,const QString &insertInlineHeader = QString::null);
+		     QWidget* parent  = 0, const char* name = 0, bool addmenumode = false);
 
     virtual ~PanelServiceMenu();
 
@@ -63,10 +67,19 @@ public:
     void showMenu() { activateParent(QString::null); }
     bool highlightMenuItem( const QString &menuId );
     void selectFirstItem();
+    void setSearchString(const QString& searchString);
+    bool hasSearchResults();
 
 private:
-    void insertMenuItem(KService::Ptr & s, int nId, int nIndex = -1, const QStringList *suppressGenericNames=0, const QString &aliasname = QString::null);
-    void fillMenu( KServiceGroup::Ptr &_root, KServiceGroup::List &_list, const QString &_relPath, int & id );
+    void insertMenuItem(KService::Ptr & s, int nId, int nIndex = -1, const QStringList *suppressGenericNames=0);
+    /**
+     * Get a list of KServices which match to the giveb pattern @p pattern.
+     * @p relPath is the path in which we start searching. This is mostly needed
+     * for internal recursion.
+     *
+     * @returns KService::List of matching services
+     */
+    KService::List findMatchingServices( const QString & pattern, const QString & relPath = QString::null );
 
 protected slots:
     virtual void initialize();
@@ -80,7 +93,7 @@ protected slots:
 
 protected:
     virtual PanelServiceMenu * newSubMenu(const QString & label, const QString & relPath,
-					  QWidget * parent, const char * name, const QString & _inlineHeader=QString::null);
+					  QWidget * parent, const char * name);
 
     virtual void mousePressEvent(QMouseEvent *);
     virtual void mouseReleaseEvent(QMouseEvent *);
@@ -90,7 +103,7 @@ protected:
 
     void activateParent(const QString &child);
 
-    void doInitialize();
+    void doInitialize( int index = 0 );
 
     QString relPath_;
 
@@ -98,12 +111,15 @@ protected:
 
     bool loaded_;
     bool excludeNoDisplay_;
-    QString insertInlineHeader_;
+
     QPopupMenu * opPopup_;
     bool clearOnClose_;
     bool addmenumode_;
     QPoint startPos_;
     PopupMenuList subMenus;
+    bool hasSearchResults_;
+
+    QValueList<int> m_ids;
 
 private slots:
     void slotContextMenu(int);
