/*************************************************************************** * Copyright (C) 2005 by Joe Ferris * * jferris@optimistictech.com * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program 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 General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "katapult.h" #include "actionregistry.h" #include "katapultcatalog.h" #include "katapultdisplay.h" #include "katapultsettings.h" #include "status.h" Katapult::Katapult() : DCOPObject("Katapult"), KSystemTray(0, "katapultSysTray") { // Register with DCOP kapp->dcopClient()->registerAs("katapult", false); kapp->dcopClient()->setDefaultObject(objId()); setPixmap(TDEGlobal::iconLoader()->loadIcon("katapult", TDEIcon::Small)); display = 0; globalAccel = 0; actions = 0; action = 0; executing = FALSE; _query = ""; settings = new KatapultSettings(); helpmenu = new KHelpMenu(this,TQString(),false); connect(helpmenu, TQ_SIGNAL(showAboutApplication()),this, TQ_SLOT(showAboutDialog())); hideTimer = new TQTimer(this); connect(hideTimer, TQ_SIGNAL(timeout()), this, TQ_SLOT(hideLauncher())); clearTimer = new TQTimer(this); connect(clearTimer, TQ_SIGNAL(timeout()), this, TQ_SLOT(clearQuery())); connect(settings, TQ_SIGNAL(catalogsChanged()), this, TQ_SLOT(loadCatalogPlugins())); connect(settings, TQ_SIGNAL(displayChanged()), this, TQ_SLOT(initDisplay())); connect(settings, TQ_SIGNAL(systrayChanged()), this, TQ_SLOT(updateSystray())); loadCatalogPlugins(); initDisplay(); if(settings->systrayIcon()) { show(); } //show popup (unless we're session restored) if (!settings->hideNotification()) { TQString msg = i18n("Application successfully started !\nPress %1 to use it...") .arg(globalAccel->shortcut("show_katapult").toString()); KPassivePopup::message(i18n("Katapult Notification"), msg, kapp->miniIcon(), this, 0, settings->notificationTimeout()); } } Katapult::~Katapult() { if(globalAccel != 0) delete globalAccel; if(actions != 0) delete actions; delete settings; } void Katapult::loadCatalogPlugins() { catalogs = settings->activeCatalogs(); } void Katapult::initDisplay() { display = settings->display(); if(display == 0) { initAccel(this); } else { initAccel(display); setQuery(""); connect(display, TQ_SIGNAL(keyReleased(TQKeyEvent *)), this, TQ_SLOT(keyReleased(TQKeyEvent *))); connect(display, TQ_SIGNAL(focusOut()), this, TQ_SLOT(hideLauncher())); } } void Katapult::initAccel(TQWidget *parent) { globalAccel = new TDEGlobalAccel(parent); globalAccel->insert("show_katapult", i18n("Show Launcher"), i18n("Shows the Katapult launcher"), ALT+Key_Space, ALT+Key_Space, this, TQ_SLOT(showLauncher())); globalAccel->readSettings(); globalAccel->updateConnections(); actions = new TDEActionCollection(parent); actionCollection()->clear(); contextMenu()->clear(); new TDEAction(i18n("Execute"), "application-x-executable", Key_Return, this, TQ_SLOT(execute()), actions, "execute"); new TDEAction(i18n("Clear"), "edit-clear", Key_Left, this, TQ_SLOT(clearQuery()), actions, "clear"); new TDEAction(i18n("Close"), "window-close", Key_Escape, this, TQ_SLOT(hideLauncher()), actions, "close"); new TDEAction(i18n("Complete Query"), "next", Key_Right, this, TQ_SLOT(completeQuery()), actions, "complete_query"); new TDEAction(i18n("Show Context Menu"), "menu", CTRL+Key_C, this, TQ_SLOT(showContextMenu()), actions, "show_menu"); TDEAction *actGlobAccel = KStdAction::keyBindings(this, TQ_SLOT(showGlobalShortcutsDialog()), actions); actGlobAccel->setText(i18n("Configure &Global Shortcuts...")); actGlobAccel->plug((TQWidget *) contextMenu()); KStdAction::keyBindings(this, TQ_SLOT(showShortcutsDialog()), actions)->plug((TQWidget *) contextMenu()); KStdAction::preferences(settings, TQ_SLOT(configure()), actions)->plug((TQWidget *) contextMenu()); contextMenu()->insertItem(SmallIconSet("help"), KStdGuiItem::help().text(), helpmenu->menu()); contextMenu()->insertSeparator(); KStdAction::quit(this, TQ_SLOT(close()), actions)->plug((TQWidget *) contextMenu()); actions->readShortcutSettings(); } void Katapult::completeQuery() { if(!bestMatch.isNull()) { TQString newQuery = bestMatch.item()->text(); setQuery(""); setQuery(newQuery); } } void Katapult::clearQuery() { setQuery(""); } void Katapult::setQuery(TQString _query) { allStatus=0; bestMatch = Match(); this->_query = _query; if(display != 0) display->setQuery(_query); if(_query == "") { TQDictIterator it(catalogs); KatapultCatalog *catalog; while((catalog = it.current()) != 0) { ++it; catalog->setQuery(""); } display->setItem(0); display->setAction(0); display->setStatus(0); display->setSelected(0); action = 0; } else if(catalogs.count() == 0) { allStatus = S_Active | S_NoResults; display->setStatus(allStatus); } else { TQDictIterator it(catalogs); KatapultCatalog *catalog; int status; while((catalog = it.current()) != 0) { ++it; catalog->setQuery(_query); status = catalog->status(); if(status & S_HasResults) { if(allStatus & S_HasResults) allStatus |= S_Multiple; Match match = catalog->bestMatch(); if(!match.isNull()) { if(bestMatch.isNull() || bestMatch.rank() < match.rank()) bestMatch = match; } } allStatus |= status; } if(bestMatch.isNull() || bestMatch.rank() == 0) bestMatch = Match(); if(!bestMatch.isNull()) { TQPtrList itemActions = ActionRegistry::self()->actionsForItem(bestMatch.item()); action = itemActions.at(0); connect(bestMatch.item(), TQ_SIGNAL(itemChanged()), this, TQ_SLOT(updateDisplay())); } } if(!(allStatus & S_HasResults) && allStatus & S_Active) { // no results switch(settings->noResultsAction()) { case KatapultSettings::NR_HideDisplay: hideTimer->start(settings->noResultsDelay(), TRUE); break; case KatapultSettings::NR_ClearQuery: clearTimer->start(settings->noResultsDelay(), TRUE); break; default: break; } } else { //stop timers if a catalog has suddenly realized it //does accept the input after all. if (hideTimer->isActive()) hideTimer->stop(); if (clearTimer->isActive()) clearTimer->stop(); } if(!executing && settings->isAutoExecute() && allStatus & S_HasResults && !(allStatus & S_Multiple)) { execute(); } updateDisplay(); } void Katapult::showAboutDialog() { TDEAboutApplication *aboutDialog = new TDEAboutApplication(this); aboutDialog->exec(); delete aboutDialog; } void Katapult::updateDisplay() { if(display != 0 && executing == FALSE) { display->setItem(bestMatch.item()); if(bestMatch.isNull()) { display->setAction(0); display->setSelected(0); } else { display->setAction(action); display->setSelected(bestMatch.matched()); } display->setStatus(allStatus); display->update(); } } void Katapult::showLauncher() { if(!settings->isConfiguring() && display != 0) { setQuery(""); display->setStatus(0); display->setQuery(""); display->show(); display->update(); KWin::forceActiveWindow(display->winId()); } } void Katapult::hideLauncher() { if(display != 0) display->hide(); setQuery(""); } void Katapult::showShortcutsDialog() { KKeyDialog::configure(actions); } void Katapult::showGlobalShortcutsDialog() { KKeyDialog::configure(globalAccel); } void Katapult::execute() { executing = TRUE; if(action == 0) { display->setStatus(S_Active | S_NoResults); display->update(); hideTimer->start(settings->hideDelay(), TRUE); } else { completeQuery(); if(!bestMatch.isNull()) action->execute(bestMatch.item()); hideTimer->start(settings->hideDelay(), TRUE); } executing = FALSE; } void Katapult::updateSystray() { if(settings->systrayIcon()) show(); else hide(); } void Katapult::showContextMenu() { contextMenu()->popup(TQCursor::pos()); } void Katapult::keyReleased(TQKeyEvent *e) { if(e->key() == Key_BackSpace) { if(hideTimer->isActive()) hideTimer->stop(); if(clearTimer->isActive()) clearTimer->stop(); TQString newQuery = _query.left(_query.length()-1); setQuery(""); setQuery(newQuery); } else { TQString t = e->text(); if ( !t.isEmpty() && (!e->ascii() || e->ascii()>=32) && e->key() != Key_Delete) setQuery(_query + t); } } void Katapult::mousePressEvent(TQMouseEvent *e) { if(e->button() == TQt::LeftButton) showLauncher(); else KSystemTray::mousePressEvent(e); } #include "katapult.moc"