/* ============================================================  *  * This file is a part of the reKonq project  * * Copyright (C) 2008 by Andrea Diamantini  * *  * 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, 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.  *  * ============================================================ */ #include "searchbar.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include SearchBar::SearchBar() : m_searchCombo(0), m_searchMode(UseSearchProvider), m_urlEnterLock(false), m_process(0) { m_searchCombo = new SearchBarCombo(0); m_searchCombo->lineEdit()->installEventFilter(this); connect(m_searchCombo, SIGNAL(activated(const QString &)), SLOT(startSearch(const QString &))); connect(m_searchCombo, SIGNAL(iconClicked()), SLOT(showSelectionMenu())); m_searchCombo->setWhatsThis(i18n("Search Bar

" "Enter a search term. Click on the icon to change search mode or provider.

")); m_popupMenu = 0; m_searchComboAction = actionCollection()->addAction("toolbar_search_bar"); m_searchComboAction->setText(i18n("Search Bar")); m_searchComboAction->setDefaultWidget(m_searchCombo); m_searchComboAction->setShortcutConfigurable(false); KAction *a = actionCollection()->addAction("focus_search_bar"); a->setText(i18n("Focus Searchbar")); a->setShortcut(Qt::CTRL+Qt::Key_S); connect(a, SIGNAL(triggered()), this, SLOT(focusSearchbar())); configurationChanged(); // parent is the KonqMainWindow and we want to listen to PartActivateEvent events. parent->installEventFilter(this); } SearchBar::~SearchBar() { KConfigGroup config(KGlobal::config(), "SearchBar"); config.writeEntry("Mode", (int) m_searchMode); config.writeEntry("CurrentEngine", m_currentEngine); delete m_searchCombo; m_searchCombo = 0L; delete m_process; m_process=0L; } static QChar delimiter() { static QChar s_delimiter = 0; if (s_delimiter == 0) { KConfig _config("kuriikwsfilterrc", KConfig::NoGlobals); KConfigGroup config(&_config, "General"); s_delimiter = config.readEntry("KeywordDelimiter", int(':')); } return s_delimiter; } void SearchBar::nextSearchEntry() { if (m_searchMode == FindInThisPage) { m_searchMode = UseSearchProvider; if (!m_searchEngines.isEmpty()) { m_currentEngine = m_searchEngines.first(); } else { m_currentEngine = "google"; } } else { int index = m_searchEngines.indexOf(m_currentEngine); ++index; if (index >= m_searchEngines.count()) { m_searchMode = FindInThisPage; } else { m_currentEngine = m_searchEngines.at(index); } } setIcon(); } void SearchBar::previousSearchEntry() { if (m_searchMode == FindInThisPage) { m_searchMode = UseSearchProvider; if (!m_searchEngines.isEmpty()) { m_currentEngine = m_searchEngines.last(); } else { m_currentEngine = "google"; } } else { int index = m_searchEngines.indexOf(m_currentEngine); if (index == 0) { m_searchMode = FindInThisPage; } else { --index; m_currentEngine = m_searchEngines.at(index); } } setIcon(); } void SearchBar::startSearch(const QString &search) { if ( m_urlEnterLock || search.isEmpty() ) return; if (m_searchMode == UseSearchProvider) { m_urlEnterLock = true; KService::Ptr service; KUriFilterData data; QStringList list; list << "kurisearchfilter" << "kuriikwsfilter"; service = KService::serviceByDesktopPath(QString("searchproviders/%1.desktop").arg(m_currentEngine)); if (service) { const QString searchProviderPrefix = service->property("Keys").toStringList().first() + delimiter(); data.setData(searchProviderPrefix + search); } if (!service || !KUriFilter::self()->filterUri(data, list)) { data.setData(QLatin1String("google") + delimiter() + search); KUriFilter::self()->filterUri(data, list); } if (QApplication::keyboardModifiers() & Qt::ControlModifier) { KParts::OpenUrlArguments arguments; KParts::BrowserArguments browserArguments; browserArguments.setNewTab(true); if (ext) emit ext->createNewWindow(data.uri(), arguments, browserArguments); } else { if (ext) { emit ext->openUrlRequest(data.uri()); m_part->widget()->setFocus(); // #152923 } } } m_searchCombo->addToHistory(search); m_searchCombo->setItemIcon(0, m_searchIcon); m_urlEnterLock = false; } void SearchBarPlugin::setIcon() { if (m_searchMode == FindInThisPage) { m_searchIcon = SmallIcon("edit-find"); } else { KService::Ptr service; KUriFilterData data; QStringList list; list << "kurisearchfilter" << "kuriikwsfilter"; service = KService::serviceByDesktopPath(QString("searchproviders/%1.desktop").arg(m_currentEngine)); if (service) { const QString searchProviderPrefix = service->property("Keys").toStringList().first() + delimiter(); data.setData(searchProviderPrefix + "some keyword"); } if (service && KUriFilter::self()->filterUri(data, list)) { QString iconPath = KStandardDirs::locate("cache", KMimeType::favIconForUrl(data.uri()) + ".png"); if (iconPath.isEmpty()) { m_searchIcon = SmallIcon("unknown"); } else { m_searchIcon = QPixmap(iconPath); } } else { m_searchIcon = SmallIcon("google"); } } // Create a bit wider icon with arrow QPixmap arrowmap = QPixmap(m_searchIcon.width()+5,m_searchIcon.height()+5); arrowmap.fill(m_searchCombo->lineEdit()->palette().color(m_searchCombo->lineEdit()->backgroundRole())); QPainter p(&arrowmap); p.drawPixmap(0, 2, m_searchIcon); QStyleOption opt; opt.state = QStyle::State_None; opt.rect = QRect(arrowmap.width()-6, arrowmap.height()-5, 6, 5); m_searchCombo->style()->drawPrimitive(QStyle::PE_IndicatorArrowDown, &opt, &p, m_searchCombo); p.end(); m_searchIcon = arrowmap; m_searchCombo->setIcon(m_searchIcon); } void SearchBar::showSelectionMenu() { if (!m_popupMenu) { KUriFilterData data; QStringList list; list << "kurisearchfilter" << "kuriikwsfilter"; m_popupMenu = new QMenu(m_searchCombo); m_popupMenu->setObjectName("search selection menu"); m_popupMenu->addAction(KIcon("edit-find"), i18n("Find in This Page"), this, SLOT(useFindInThisPage())); m_popupMenu->addSeparator(); int i=-1; for (QStringList::ConstIterator it = m_searchEngines.begin(); it != m_searchEngines.end(); ++it) { i++; KService::Ptr service = KService::serviceByDesktopPath(QString("searchproviders/%1.desktop").arg(*it)); if (!service) { continue; } const QString searchProviderPrefix = service->property("Keys").toStringList().first() + delimiter(); data.setData(searchProviderPrefix + "some keyword"); if (KUriFilter::self()->filterUri(data, list)) { QIcon icon; QString iconPath = KStandardDirs::locate("cache", KMimeType::favIconForUrl(data.uri()) + ".png"); if (iconPath.isEmpty()) { icon = KIcon("unknown"); } else { icon = QPixmap(iconPath); } QAction* action = m_popupMenu->addAction(icon, service->name()); action->setData(qVariantFromValue(i)); } } m_popupMenu->addSeparator(); m_popupMenu->addAction(KIcon("preferences-web-browser-shortcuts"), i18n("Select Search Engines..."), this, SLOT(selectSearchEngines())); connect(m_popupMenu, SIGNAL(triggered(QAction *)), SLOT(useSearchProvider(QAction *))); } m_popupMenu->popup(m_searchCombo->mapToGlobal(QPoint(0, m_searchCombo->height() + 1))); } void SearchBar::useFindInThisPage() { m_searchMode = FindInThisPage; setIcon(); } void SearchBar::useSearchProvider(QAction *action) { bool ok = false; const int id = action->data().toInt(&ok); if(!ok) { // Not a search engine entry selected return; } m_searchMode = UseSearchProvider; m_currentEngine = m_searchEngines.at(id); setIcon(); m_searchCombo->lineEdit()->selectAll(); } void SearchBar::selectSearchEngines() { m_process = new KProcess; *m_process << "kcmshell4" << "ebrowsing"; connect(m_process, SIGNAL(finished(int,QProcess::ExitStatus)), SLOT(searchEnginesSelected(int,QProcess::ExitStatus))); m_process->start(); if(!m_process->waitForStarted()) { kDebug(1202) << "Couldn't invoke kcmshell"; delete m_process; m_process = 0; } } void SearchBar::searchEnginesSelected(int exitCode, QProcess::ExitStatus exitStatus) { Q_UNUSED(exitCode); if(exitStatus == QProcess::NormalExit) { KConfigGroup config(KGlobal::config(), "SearchBar"); config.writeEntry("CurrentEngine", m_currentEngine); config.sync(); configurationChanged(); } delete m_process; m_process = 0; } void SearchBar::configurationChanged() { KConfigGroup config(KSharedConfig::openConfig("kuriikwsfilterrc"), "General"); const QString engine = config.readEntry("DefaultSearchEngine", "google"); QStringList favoriteEngines; favoriteEngines << "google" << "google_groups" << "google_news" << "webster" << "dmoz" << "wikipedia"; favoriteEngines = config.readEntry("FavoriteSearchEngines", favoriteEngines); delete m_popupMenu; m_popupMenu = 0; m_searchEngines.clear(); m_searchEngines << engine; for (QStringList::ConstIterator it = favoriteEngines.begin(); it != favoriteEngines.end(); ++it) if(*it!=engine) m_searchEngines << *it; if(engine.isEmpty()) { m_providerName = "Google"; } else { KDesktopFile file("services", "searchproviders/" + engine + ".desktop"); m_providerName = file.readName(); } config = KConfigGroup(KGlobal::config(), "SearchBar"); m_searchMode = (SearchModes) config.readEntry("Mode", (int) UseSearchProvider); m_currentEngine = config.readEntry("CurrentEngine", engine); if (m_currentEngine.isEmpty()) m_currentEngine = "google"; setIcon(); } void SearchBar::updateComboVisibility() { if (!m_part|| m_searchComboAction->associatedWidgets().isEmpty()) { m_searchCombo->setPluginActive(false); m_searchCombo->hide(); } else { m_searchCombo->setPluginActive(true); m_searchCombo->show(); } } void SearchBar::focusSearchbar() { m_searchCombo->setFocus(Qt::ShortcutFocusReason); } SearchBarCombo::SearchBarCombo(QWidget *parent) : KHistoryComboBox(parent), m_pluginActive(true) { setDuplicatesEnabled(false); setFixedWidth(180); connect(this, SIGNAL(cleared()), SLOT(historyCleared())); Q_ASSERT(useCompletion()); KConfigGroup config(KGlobal::config(), "SearchBar"); QStringList list = config.readEntry( "History list", QStringList() ); list.prepend(QString()); // empty item setHistoryItems(list, true); Q_ASSERT(currentText().isEmpty()); // KHistoryComboBox calls clearEditText } const QPixmap &SearchBarCombo::icon() const { return m_icon; } void SearchBarCombo::setIcon(const QPixmap &icon) { m_icon = icon; const QString editText = currentText(); if (count() == 0) { insertItem(0, m_icon, 0); } else { for(int i = 0; i < count(); i++) { setItemIcon(i, m_icon); } } setEditText(editText); } int SearchBarCombo::findHistoryItem(const QString &searchText) { for(int i = 0; i < count(); i++) { if (itemText(i) == searchText) { return i; } } return -1; } void SearchBarCombo::mousePressEvent(QMouseEvent *e) { QStyleOptionComplex opt; int x0 = QStyle::visualRect(layoutDirection(), style()->subControlRect(QStyle::CC_ComboBox, &opt, QStyle::SC_ComboBoxEditField, this), rect()).x(); if (e->x() > x0 + 2 && e->x() < lineEdit()->x()) { emit iconClicked(); e->accept(); } else { KHistoryComboBox::mousePressEvent(e); } } void SearchBarCombo::historyCleared() { setIcon(m_icon); } void SearchBarCombo::setPluginActive(bool pluginActive) { m_pluginActive = pluginActive; } void SearchBarCombo::show() { if (m_pluginActive) { KHistoryComboBox::show(); } } SearchBarCombo::~SearchBarCombo() { KConfigGroup config(KGlobal::config(), "SearchBar"); config.writeEntry( "History list", historyItems() ); } #include "searchbar.moc"