From caaa91a08cb11ff7ce6c410280dbcd1023b935d1 Mon Sep 17 00:00:00 2001 From: Jekyll Wu Date: Tue, 17 Apr 2012 23:56:49 +0800 Subject: [PATCH] Add support for KDE Web Shortcus There is a submenu in the context menu for searching selected text using any of the enabled search provider and opening the result in the default web browser. This could be useful for searching compilation failure messages, warning messages in logfile, etc. DIGEST: FEATURE: FIXED-IN: 4.9.0 REVIEW: 104493 --- desktop/partui.rc | 1 + desktop/sessionui.rc | 3 +- src/SessionController.cpp | 101 +++++++++++++++++++++++++++++++++++--- src/SessionController.h | 18 +++++-- src/ViewManager.cpp | 2 +- 5 files changed, 112 insertions(+), 13 deletions(-) diff --git a/desktop/partui.rc b/desktop/partui.rc index bc5c15a59..3e000d9bc 100644 --- a/desktop/partui.rc +++ b/desktop/partui.rc @@ -4,6 +4,7 @@ + S&crollback diff --git a/desktop/sessionui.rc b/desktop/sessionui.rc index 2a05e4e11..587570aae 100644 --- a/desktop/sessionui.rc +++ b/desktop/sessionui.rc @@ -1,6 +1,6 @@ - + @@ -41,6 +41,7 @@ + diff --git a/src/SessionController.cpp b/src/SessionController.cpp index fd23e0b49..c4cd0d229 100644 --- a/src/SessionController.cpp +++ b/src/SessionController.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -44,6 +45,8 @@ #include #include #include +#include +#include #include // Konsole @@ -97,6 +100,7 @@ SessionController::SessionController(Session* session , TerminalDisplay* view, Q , _searchBar(0) , _codecAction(0) , _switchProfileMenu(0) + , _webSearchMenu(0) , _listenForScreenWindowUpdates(false) , _preventClose(false) , _keepIconUntilInteraction(false) @@ -332,13 +336,87 @@ void SessionController::setupPrimaryScreenSpecificActions(bool use) selectAllAction->setEnabled(use); } -void SessionController::updateCopyAction(const QString& text) +void SessionController::selectionChanged(const QString& selectedText) { - KActionCollection* collection = actionCollection(); - QAction* copyAction = collection->action("edit_copy"); + _selectedText = selectedText; + updateCopyAction(selectedText); + updateWebSearchMenu(); +} - // copy action is meaningful only when some text is selcted. - copyAction->setEnabled(!text.isEmpty()); +void SessionController::updateCopyAction(const QString& selectedText) +{ + QAction* copyAction = actionCollection()->action("edit_copy"); + + // copy action is meaningful only when some text is selected. + copyAction->setEnabled(!selectedText.isEmpty()); +} + +void SessionController::updateWebSearchMenu() +{ + // reset + _webSearchMenu->setVisible(false); + _webSearchMenu->menu()->clear(); + + if ( _selectedText.isEmpty() ) + return ; + + QString searchText = _selectedText; + searchText = searchText.replace('\n', ' ').replace('\r', ' ').simplified(); + + if (searchText.isEmpty()) + return; + + KUriFilterData filterData(searchText); + filterData.setSearchFilteringOptions(KUriFilterData::RetrievePreferredSearchProvidersOnly); + + if (KUriFilter::self()->filterSearchUri(filterData, KUriFilter::NormalTextFilter)) { + const QStringList searchProviders = filterData.preferredSearchProviders(); + if (!searchProviders.isEmpty()) { + + _webSearchMenu->setText(i18n("Search for '%1' with", KStringHandler::rsqueeze(searchText, 16))); + + KAction* action = 0; + + foreach(const QString& searchProvider, searchProviders) + { + action = new KAction(searchProvider, _webSearchMenu); + action->setIcon(KIcon(filterData.iconNameForPreferredSearchProvider(searchProvider))); + action->setData(filterData.queryForPreferredSearchProvider(searchProvider)); + connect(action, SIGNAL(triggered()), this, SLOT(handleWebShortcutAction())); + _webSearchMenu->addAction(action); + } + + _webSearchMenu->addSeparator(); + + action = new KAction(i18n("Configure Web Shortcuts..."), _webSearchMenu); + action->setIcon(KIcon("configure")); + connect(action, SIGNAL(triggered()), this, SLOT(configureWebShortcuts())); + _webSearchMenu->addAction(action); + + _webSearchMenu->setVisible(true); + } + + } + +} + +void SessionController::handleWebShortcutAction() +{ + KAction* action = qobject_cast(sender()); + if (!action) + return; + + KUriFilterData filterData(action->data().toString()); + + if (KUriFilter::self()->filterUri(filterData, QStringList() << "kurisearchfilter")) { + const KUrl& url = filterData.uri(); + new KRun(url, QApplication::activeWindow(), 0, true, true); + } +} + +void SessionController::configureWebShortcuts() +{ + KToolInvocation::kdeinitExec("kcmshell4", QStringList() << "ebrowsing"); } bool SessionController::eventFilter(QObject* watched , QEvent* event) @@ -469,6 +547,12 @@ void SessionController::setupCommonActions() action->setText(i18n("Paste Selection")); action->setShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_Insert)); + _webSearchMenu = new KActionMenu(i18n("Web Search"), _view); + _webSearchMenu->setIcon(KIcon("preferences-web-browser-shortcuts")); + _webSearchMenu->setVisible(false); + collection->addAction("web-search", _webSearchMenu); + + action = collection->addAction("select-all", this, SLOT(selectAll())); action->setText(i18n("&Select All")); action->setIcon(KIcon("edit-select-all")); @@ -1189,10 +1273,15 @@ void SessionController::showDisplayContextMenu(const QPoint& position) QAction* contentSeparator = new QAction(popup); contentSeparator->setSeparator(true); contentActions << contentSeparator; + popup->insertActions(popup->actions().value(0, 0), contentActions); + + // always update this submenu before showing the context menu, + // because the available search services might have changed + // since the context menu is shown last time + updateWebSearchMenu(); _preventClose = true; - popup->insertActions(popup->actions().value(0, 0), contentActions); QAction* chosen = popup->exec(_view->mapToGlobal(position)); // check for validity of the pointer to the popup menu diff --git a/src/SessionController.h b/src/SessionController.h index 160c95f17..85dbdbbeb 100644 --- a/src/SessionController.h +++ b/src/SessionController.h @@ -195,17 +195,17 @@ public slots: */ void setupPrimaryScreenSpecificActions(bool use); + /** + * update actions which are closely related with the selected text. + */ + void selectionChanged(const QString& selectedText); + /** * close the associated session. This might involve user interaction for * confirmation. */ void closeSession(); - /** - * enable or disable the copy action - */ - void updateCopyAction(const QString & text); - /** Increase font size */ void increaseTextSize(); @@ -237,6 +237,8 @@ private slots: void monitorSilence(bool monitor); void renameSession(); void switchProfile(Profile::Ptr profile); + void handleWebShortcutAction(); + void configureWebShortcuts(); // other void prepareSwitchProfileMenu(); @@ -270,6 +272,9 @@ private slots: /* Returns true if called within a KPart; false if called within Konsole. */ bool isKonsolePart() const; + // update actions related with selected text + void updateCopyAction(const QString& selectedText); + void updateWebSearchMenu(); private: // begins the search @@ -314,12 +319,15 @@ private: KCodecAction* _codecAction; KActionMenu* _switchProfileMenu; + KActionMenu* _webSearchMenu; bool _listenForScreenWindowUpdates; bool _preventClose; bool _keepIconUntilInteraction; + QString _selectedText; + static QSet _allControllers; static int _lastControllerId; static const KIcon _activityIcon; diff --git a/src/ViewManager.cpp b/src/ViewManager.cpp index 6434a662b..82fa3205b 100644 --- a/src/ViewManager.cpp +++ b/src/ViewManager.cpp @@ -516,7 +516,7 @@ SessionController* ViewManager::createController(Session* session , TerminalDisp connect(session , SIGNAL(primaryScreenInUse(bool)) , controller , SLOT(setupPrimaryScreenSpecificActions(bool))); connect(session , SIGNAL(selectedText(QString)) , - controller , SLOT(updateCopyAction(QString))); + controller , SLOT(selectionChanged(QString))); connect(view , SIGNAL(destroyed()) , controller , SLOT(deleteLater())); // if this is the first controller created then set it as the active controller