You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
343 lines
11 KiB
343 lines
11 KiB
Index: kicker/kicker/ui/k_mnu.cpp
|
|
===================================================================
|
|
--- kicker/kicker/ui/k_mnu.cpp.orig
|
|
+++ kicker/kicker/ui/k_mnu.cpp
|
|
@@ -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"
|
|
@@ -58,9 +64,12 @@ CONNECTION WITH THE SOFTWARE OR THE USE
|
|
#include "quickbrowser_mnu.h"
|
|
#include "recentapps.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)
|
|
@@ -165,6 +174,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;
|
|
@@ -191,13 +220,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 KLineEdit(hbox); searchEdit->setClickMessage(" "+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
|
|
@@ -737,3 +782,43 @@ void PanelKMenu::clearRecentMenuItems()
|
|
}
|
|
|
|
|
|
+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);
|
|
+ }
|
|
+}
|
|
Index: kicker/kicker/ui/k_mnu.h
|
|
===================================================================
|
|
--- kicker/kicker/ui/k_mnu.h.orig
|
|
+++ kicker/kicker/ui/k_mnu.h
|
|
@@ -73,6 +73,8 @@ protected slots:
|
|
void slotSaveSession();
|
|
void slotRunCommand();
|
|
void slotEditUserContact();
|
|
+ void slotUpdateSearch(const QString &searchtext);
|
|
+ void slotClearSearch();
|
|
void paletteChanged();
|
|
virtual void configChanged();
|
|
void updateRecent();
|
|
@@ -89,6 +91,8 @@ protected:
|
|
void doNewSession(bool lock);
|
|
void createRecentMenuItems();
|
|
virtual void clearSubmenus();
|
|
+ void filterMenu(PanelServiceMenu* menu, const QString &searchString);
|
|
+ void keyPressEvent(QKeyEvent* e);
|
|
|
|
private:
|
|
QPopupMenu *sessionsMenu;
|
|
@@ -101,6 +105,8 @@ private:
|
|
KActionCollection *actionCollection;
|
|
KBookmarkOwner *bookmarkOwner;
|
|
PopupMenuList dynamicSubMenus;
|
|
+ KLineEdit *searchEdit;
|
|
+ static const int searchLineID;
|
|
};
|
|
|
|
#endif
|
|
Index: kicker/kicker/ui/service_mnu.cpp
|
|
===================================================================
|
|
--- kicker/kicker/ui/service_mnu.cpp.orig
|
|
+++ kicker/kicker/ui/service_mnu.cpp
|
|
@@ -26,6 +26,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE
|
|
#include <qbitmap.h>
|
|
#include <qpixmap.h>
|
|
#include <qimage.h>
|
|
+#include <qmap.h>
|
|
|
|
#include <dcopclient.h>
|
|
#include <kapplication.h>
|
|
@@ -100,6 +101,8 @@ void PanelServiceMenu::initialize()
|
|
clear();
|
|
|
|
clearSubmenus();
|
|
+ searchSubMenuIDs.clear();
|
|
+ searchMenuItems.clear();
|
|
doInitialize();
|
|
}
|
|
|
|
@@ -296,6 +299,10 @@ void PanelServiceMenu::fillMenu(KService
|
|
|
|
int newId = insertItem(iconset, groupCaption, m, id++);
|
|
entryMap_.insert(newId, static_cast<KSycocaEntry*>(g));
|
|
+ // This submenu will be searched when applying a search string
|
|
+ searchSubMenuIDs[m] = newId;
|
|
+ // Also search the submenu name itself
|
|
+ searchMenuItems.insert(newId);
|
|
// We have to delete the sub menu our selves! (See Qt docs.)
|
|
subMenus.append(m);
|
|
}
|
|
@@ -308,6 +315,7 @@ void PanelServiceMenu::fillMenu(KService
|
|
}
|
|
|
|
KService::Ptr s(static_cast<KService *>(e));
|
|
+ searchMenuItems.insert(id);
|
|
insertMenuItem(s, id++, -1, &suppressGenericNames, QString::null, specialTitle[s->name()], categoryIcon[s->name()] );
|
|
}
|
|
else if (e->isType(KST_KServiceSeparator))
|
|
@@ -900,6 +908,8 @@ void PanelServiceMenu::slotClear()
|
|
delete *it;
|
|
}
|
|
subMenus.clear();
|
|
+ searchSubMenuIDs.clear();
|
|
+ searchMenuItems.clear();
|
|
}
|
|
|
|
void PanelServiceMenu::selectFirstItem()
|
|
@@ -924,3 +934,72 @@ void PanelServiceMenu::updateRecentlyUse
|
|
RecentlyLaunchedApps::the().m_bNeedToUpdate = true;
|
|
}
|
|
|
|
+void PanelServiceMenu::setSearchString(const QString &searchString)
|
|
+{
|
|
+ // We must initialize the menu, because it might have not been opened before
|
|
+ initialize();
|
|
+
|
|
+ bool foundSomething = false;
|
|
+ std::set<int> nonemptyMenus;
|
|
+ std::set<int>::const_iterator menuItemIt(searchMenuItems.begin());
|
|
+ // Apply the filter on this menu
|
|
+ for (; menuItemIt != searchMenuItems.end(); ++menuItemIt) {
|
|
+ int id = *menuItemIt;
|
|
+ KService* s = dynamic_cast< KService* >( static_cast< KSycocaEntry* >( entryMap_[ id ]));
|
|
+ QString menuText = text(id);
|
|
+ if (menuText.contains(searchString, false) > 0
|
|
+ || ( s != NULL && ( s->name().contains(searchString, false) > 0
|
|
+ || s->exec().contains(searchString, false) > 0
|
|
+ || s->comment().contains(searchString, false) > 0
|
|
+ || s->genericName().contains(searchString, false) > 0
|
|
+ || s->exec().contains(searchString, false) > 0 )
|
|
+ )) {
|
|
+ setItemEnabled(id, true);
|
|
+ foundSomething = true;
|
|
+ nonemptyMenus.insert(id);
|
|
+ }
|
|
+ else {
|
|
+ setItemEnabled(id, false);
|
|
+ }
|
|
+ }
|
|
+ // Apply the filter on this menu
|
|
+ /*for (int i=count()-1; i>=0; --i) {
|
|
+ int id = idAt(i);
|
|
+ QString menuText = text(id);
|
|
+ if (menuText.contains(searchString, false) > 0) {
|
|
+ setItemEnabled(id, true);
|
|
+ foundSomething = true;
|
|
+ nonemptyMenus.insert(id);
|
|
+ }
|
|
+ else {
|
|
+ setItemEnabled(id, false);
|
|
+ }
|
|
+ }*/
|
|
+
|
|
+ PanelServiceMenuMap::iterator it(searchSubMenuIDs.begin());
|
|
+ // Apply the search filter on submenus
|
|
+ for (; it != searchSubMenuIDs.end(); ++it) {
|
|
+ it.key()->setSearchString(searchString);
|
|
+ if (nonemptyMenus.find(it.data()) != nonemptyMenus.end()) {
|
|
+ // if the current menu is a match already, we don't
|
|
+ // block access to the contained items
|
|
+ setItemEnabled(it.data(), true);
|
|
+ it.key()->setSearchString(QString());
|
|
+ foundSomething = true;
|
|
+ }
|
|
+ else if (it.key()->hasSearchResults()) {
|
|
+ setItemEnabled(it.data(), true);
|
|
+ foundSomething = true;
|
|
+ }
|
|
+ else {
|
|
+ setItemEnabled(it.data(), false);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ hasSearchResults_ = foundSomething;
|
|
+}
|
|
+
|
|
+bool PanelServiceMenu::hasSearchResults()
|
|
+{
|
|
+ return hasSearchResults_;
|
|
+}
|
|
Index: kicker/kicker/ui/service_mnu.h
|
|
===================================================================
|
|
--- kicker/kicker/ui/service_mnu.h.orig
|
|
+++ kicker/kicker/ui/service_mnu.h
|
|
@@ -26,6 +26,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE
|
|
|
|
#include <qmap.h>
|
|
#include <qvaluevector.h>
|
|
+#include <set>
|
|
|
|
#include <ksycocaentry.h>
|
|
#include <kservice.h>
|
|
@@ -41,8 +42,11 @@ CONNECTION WITH THE SOFTWARE OR THE USE
|
|
* @author Rik Hemsley <rik@kde.org>
|
|
*/
|
|
|
|
+class KLineEdit;
|
|
typedef QMap<int, KSycocaEntry::Ptr> EntryMap;
|
|
typedef QValueVector<QPopupMenu*> PopupMenuList;
|
|
+class PanelServiceMenu;
|
|
+typedef QMap<PanelServiceMenu*,int> PanelServiceMenuMap;
|
|
|
|
class KDE_EXPORT PanelServiceMenu : public KPanelMenu
|
|
{
|
|
@@ -63,6 +67,8 @@ public:
|
|
virtual void showMenu();
|
|
bool highlightMenuItem( const QString &menuId );
|
|
void selectFirstItem();
|
|
+ void setSearchString(const QString& searchString);
|
|
+ bool hasSearchResults();
|
|
|
|
private:
|
|
void fillMenu( KServiceGroup::Ptr &_root, KServiceGroup::List &_list,
|
|
@@ -115,6 +121,9 @@ protected:
|
|
bool addmenumode_;
|
|
QPoint startPos_;
|
|
PopupMenuList subMenus;
|
|
+ PanelServiceMenuMap searchSubMenuIDs;
|
|
+ bool hasSearchResults_;
|
|
+ std::set<int> searchMenuItems;
|
|
|
|
private slots:
|
|
void slotContextMenu(int);
|