SVN commit 988313 by fyanardi:
Implemented a new feature for Konqueror searchbar plugin: suggestion engine. For now only google suggestion is available. Thanks to Germain Garand who reviewed this feature.
CCMAIL:
kfm-devel@...
M +5 -1 CMakeLists.txt
A SearchSuggestion.cpp [License: GPL (v2+)]
A SearchSuggestion.h [License: GPL (v2+)]
A SuggestionEngine.cpp [License: GPL (v2+)]
A SuggestionEngine.h [License: GPL (v2+)]
A engines (directory)
A engines/GoogleSuggestionEngine.cpp [License: GPL (v2+)]
A engines/GoogleSuggestionEngine.h [License: GPL (v2+)]
M +115 -4 searchbar.cpp
M +28 -1 searchbar.h
--- trunk/extragear/base/konq-plugins/searchbar/CMakeLists.txt #988312:988313
@@ -4,7 +4,11 @@
########### next target ###############
-set(searchbarplugin_PART_SRCS searchbar.cpp )
+set(searchbarplugin_PART_SRCS
+ searchbar.cpp
+ SearchSuggestion.cpp
+ SuggestionEngine.cpp
+ engines/GoogleSuggestionEngine.cpp)
kde4_add_plugin(searchbarplugin ${searchbarplugin_PART_SRCS})
--- trunk/extragear/base/konq-plugins/searchbar/searchbar.cpp #988312:988313
@@ -19,10 +19,13 @@
#include "searchbar.h"
+#include "SearchSuggestion.h"
+
#include <unistd.h>
#include <QLineEdit>
#include <QApplication>
#include <kaction.h>
+#include <KCompletionBox>
#include <kconfig.h>
#include <ksharedconfig.h>
#include <kdebug.h>
@@ -46,6 +49,8 @@
#include <qstyle.h>
#include <QPixmap>
#include <QMouseEvent>
+#include <QtGui/QCompleter>
+#include <QtCore/QTimer>
K_PLUGIN_FACTORY(SearchBarPluginFactory, registerPlugin<SearchBarPlugin>();)
K_EXPORT_PLUGIN(SearchBarPluginFactory("searchbarplugin"))
@@ -56,7 +61,8 @@
m_searchCombo(0),
m_searchMode(UseSearchProvider),
m_urlEnterLock(false),
- m_process(0)
+ m_process(0),
+ m_searchSuggestion(new SearchSuggestion(this))
{
m_searchCombo = new SearchBarCombo(0);
m_searchCombo->lineEdit()->installEventFilter(this);
@@ -73,7 +79,6 @@
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);
@@ -83,6 +88,12 @@
// parent is the KonqMainWindow and we want to listen to PartActivateEvent events.
parent->installEventFilter(this);
+ connect(m_searchCombo->lineEdit(), SIGNAL(textEdited(const QString &)), SLOT(searchTextChanged(const QString &)));
+ connect(m_searchSuggestion, SIGNAL(suggestionReceived(const QStringList &)),
+ SLOT(addSearchSuggestion(const QStringList &)));
+ m_timer = new QTimer(this);
+ m_timer->setSingleShot(true);
+ connect(m_timer, SIGNAL(timeout()), SLOT(requestSuggestion()));
}
SearchBarPlugin::~SearchBarPlugin()
@@ -409,8 +420,33 @@
m_searchCombo->setFocus(Qt::ShortcutFocusReason);
}
+void SearchBarPlugin::searchTextChanged(const QString &text)
+{
+ m_searchCombo->clearSuggestions();
+
+ if (m_searchMode != FindInThisPage && m_searchSuggestion->isEngineAvailable(m_currentEngine) && !text.isEmpty()) {
+ if (m_timer->isActive()) {
+ m_timer->stop();
+ }
+
+ // 400 ms delay before requesting for suggestions, so we don't flood the provider with suggestion request
+ m_timer->start(400);
+ }
+}
+
+void SearchBarPlugin::requestSuggestion() {
+ if (!m_searchCombo->lineEdit()->text().isEmpty()) {
+ m_searchSuggestion->requestSuggestion(m_currentEngine, m_searchCombo->lineEdit()->text());
+ }
+}
+
+void SearchBarPlugin::addSearchSuggestion(const QStringList &suggestions)
+{
+ m_searchCombo->setSuggestionItems(suggestions);
+}
+
SearchBarCombo::SearchBarCombo(QWidget *parent) :
- KHistoryComboBox(parent),
+ KHistoryComboBox(true, parent),
m_pluginActive(true)
{
setDuplicatesEnabled(false);
@@ -421,9 +457,11 @@
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
+
+ // use our own item delegate to display our fancy stuff :D
+ completionBox()->setItemDelegate(new SearchBarItemDelegate(this));
}
const QPixmap &SearchBarCombo::icon() const
@@ -480,6 +518,36 @@
m_pluginActive = pluginActive;
}
+void SearchBarCombo::setSuggestionItems(const QStringList &suggestions)
+{
+ if (m_suggestions.count() > 0) {
+ clearSuggestions();
+ }
+
+ m_suggestions = suggestions;
+ if (suggestions.count() > 0) {
+ int size = completionBox()->count();
+ QListWidgetItem *item = new QListWidgetItem(suggestions.at(0));
+ item->setData(Qt::UserRole, "suggestion");
+ completionBox()->insertItem(size + 1, item);
+ for (int i = 1; i < suggestions.count(); i++) {
+ completionBox()->insertItem(size + 1 + i, suggestions.at(i));
+ }
+ completionBox()->popup();
+ }
+}
+
+void SearchBarCombo::clearSuggestions()
+{
+ int size = completionBox()->count();
+ if (!m_suggestions.isEmpty() && size >= m_suggestions.count()) {
+ for (int i = size - 1; i >= size - m_suggestions.size(); i--) {
+ completionBox()->takeItem(i);
+ }
+ }
+ m_suggestions.clear();
+}
+
void SearchBarCombo::show()
{
if (m_pluginActive) {
@@ -493,4 +561,47 @@
config.writeEntry( "History list", historyItems() );
}
+SearchBarItemDelegate::SearchBarItemDelegate(QObject *parent)
+ : QItemDelegate(parent)
+{
+}
+
+void SearchBarItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
+{
+ QString userText = index.data(Qt::UserRole).toString();
+ QString text = index.data(Qt::DisplayRole).toString();
+
+ // Get item data
+ if (!userText.isEmpty()) {
+ // This font is for the "information" text, small size + italic + gray in color
+ QFont usrTxtFont = option.font;
+ usrTxtFont.setItalic(true);
+ usrTxtFont.setPointSize(6);
+
+ QFontMetrics usrTxtFontMetrics(usrTxtFont);
+ int width = usrTxtFontMetrics.width(userText);
+ QRect rect(option.rect.x(), option.rect.y(), option.rect.width() - width, option.rect.height());
+ QFontMetrics textFontMetrics(option.font);
+ QString elidedText = textFontMetrics.elidedText(text,
+ Qt::ElideRight, option.rect.width() - width - option.decorationSize.width());
+
+ QAbstractItemModel *itemModel = const_cast<QAbstractItemModel *>(index.model());
+ itemModel->setData(index, elidedText, Qt::DisplayRole);
+ QItemDelegate::paint(painter, option, index);
+ itemModel->setData(index, text, Qt::DisplayRole);
+
+ painter->setFont(usrTxtFont);
+ painter->setPen(QPen(QColor(Qt::gray)));
+ painter->drawText(option.rect, Qt::AlignRight, userText);
+
+ // Draw a separator above this item
+ if (index.row() > 0) {
+ painter->drawLine(option.rect.x(), option.rect.y(), option.rect.x() + option.rect.width(), option.rect.y());
+ }
+ }
+ else {
+ QItemDelegate::paint(painter, option, index);
+ }
+}
+
#include "searchbar.moc"
--- trunk/extragear/base/konq-plugins/searchbar/searchbar.h #988312:988313
@@ -31,10 +31,12 @@
#include <qpixmap.h>
#include <qstring.h>
#include <KProcess>
+#include <QtGui/QItemDelegate>
+class SearchSuggestion;
class KHTMLPart;
-
class QMenu;
+class QTimer;
/**
* Combo box which catches mouse clicks on the pixmap.
*/
@@ -75,6 +77,10 @@
*/
void setPluginActive(bool pluginActive);
+ void setSuggestionItems(const QStringList &suggestions);
+
+ void clearSuggestions();
+
public slots:
virtual void show();
@@ -97,6 +103,7 @@
private:
QPixmap m_icon;
bool m_pluginActive;
+ QStringList m_suggestions;
};
/**
@@ -156,6 +163,13 @@
void updateComboVisibility();
void focusSearchbar();
+
+ void searchTextChanged(const QString &text);
+
+ void addSearchSuggestion(const QStringList &suggestion);
+
+ void requestSuggestion();
+
private:
void nextSearchEntry();
void previousSearchEntry();
@@ -173,6 +187,19 @@
QStringList m_searchEngines;
QChar m_delimiter;
KProcess *m_process;
+ SearchSuggestion *m_searchSuggestion;
+ QTimer *m_timer;
};
+/**
+ * An item delegate for combo box completion items, to give some fancy stuff
+ * to the completion items
+ */
+class SearchBarItemDelegate : public QItemDelegate
+{
+public:
+ SearchBarItemDelegate(QObject *parent = 0);
+ virtual void paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const;
+};
+
#endif // SEARCHBAR_PLUGIN