]> git.sur5r.net Git - minitube/commitdiff
Google suggest
authorFlavio Tordini <flavio.tordini@gmail.com>
Tue, 21 Jul 2009 20:14:45 +0000 (22:14 +0200)
committerFlavio Tordini <flavio.tordini@gmail.com>
Tue, 21 Jul 2009 20:14:45 +0000 (22:14 +0200)
minitube.pro
src/googlesuggest.cpp [new file with mode: 0644]
src/googlesuggest.h [new file with mode: 0644]
src/searchlineedit.cpp
src/searchlineedit.h

index eb397e5471dc1e31b86d5b8554c372f921bbfb09..1518c59b584532ec9e4f3dec467998c66e556238 100755 (executable)
@@ -1,6 +1,5 @@
 # On some distro, Phonon headers cannot be found
 INCLUDEPATH += /usr/include/phonon
-
 CONFIG += release
 TEMPLATE = app
 
@@ -41,7 +40,8 @@ HEADERS += src/MainWindow.h \
     src/searchparams.h \
     src/minisplitter.h \
     src/loadingwidget.h \
-    src/videoareawidget.h
+    src/videoareawidget.h \
+    src/googlesuggest.h
 SOURCES += src/main.cpp \
     src/MainWindow.cpp \
     src/SearchView.cpp \
@@ -65,7 +65,8 @@ SOURCES += src/main.cpp \
     src/searchparams.cpp \
     src/minisplitter.cpp \
     src/loadingwidget.cpp \
-    src/videoareawidget.cpp
+    src/videoareawidget.cpp \
+    src/googlesuggest.cpp
 RESOURCES += resources.qrc
 DESTDIR = build/target/
 OBJECTS_DIR = build/obj/
@@ -105,6 +106,7 @@ unix {
     translations.files += $$DESTDIR/locale
     desktop.path = $$DATADIR/applications
     desktop.files += minitube.desktop
+    
     # iconxpm.path = $$DATADIR/pixmaps
     # iconxpm.files += data/minitube.xpm
     iconsvg.path = $$DATADIR/icons/hicolor/scalable/apps
diff --git a/src/googlesuggest.cpp b/src/googlesuggest.cpp
new file mode 100644 (file)
index 0000000..0ad1932
--- /dev/null
@@ -0,0 +1,178 @@
+#include "googlesuggest.h"
+#include "networkaccess.h"
+
+#define GSUGGEST_URL "http://suggestqueries.google.com/complete/search?output=toolbar&hl=%1&q=%2"
+
+namespace The {
+    NetworkAccess* http();
+}
+
+GSuggestCompletion::GSuggestCompletion(QLineEdit *parent): QObject(parent), editor(parent) {
+
+    popup = new QListWidget;
+    popup->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+
+    popup->installEventFilter(this);
+    popup->setMouseTracking(true);
+
+    connect(popup, SIGNAL(itemClicked(QListWidgetItem*)),
+            SLOT(doneCompletion()));
+
+    connect(popup, SIGNAL(currentItemChanged(QListWidgetItem *, QListWidgetItem *)),
+            SLOT(currentItemChanged(QListWidgetItem *)));
+
+    connect(popup, SIGNAL(itemEntered(QListWidgetItem*)),
+            SLOT(currentItemChanged(QListWidgetItem *)));
+
+    popup->setWindowFlags(Qt::Popup);
+    popup->setFocusPolicy(Qt::NoFocus);
+    popup->setFocusProxy(parent);
+
+    timer = new QTimer(this);
+    timer->setSingleShot(true);
+    timer->setInterval(250);
+    connect(timer, SIGNAL(timeout()), SLOT(autoSuggest()));
+    connect(editor, SIGNAL(textEdited(QString)), timer, SLOT(start()));
+
+}
+
+GSuggestCompletion::~GSuggestCompletion() {
+    delete popup;
+}
+
+bool GSuggestCompletion::eventFilter(QObject *obj, QEvent *ev) {
+    if (obj != popup)
+        return false;
+
+    if (ev->type() == QEvent::MouseButtonPress) {
+        popup->hide();
+        editor->setFocus();
+        editor->setText(originalText);
+        return true;
+    }
+
+    if (ev->type() == QEvent::KeyPress) {
+
+        bool consumed = false;
+        int key = static_cast<QKeyEvent*>(ev)->key();
+        switch (key) {
+        case Qt::Key_Enter:
+        case Qt::Key_Return:
+            if (popup->currentItem()) {
+                doneCompletion();
+                consumed = true;
+            } else {
+                editor->setFocus();
+                editor->event(ev);
+                popup->hide();
+            }
+            break;
+
+        case Qt::Key_Escape:
+            editor->setFocus();
+            editor->setText(originalText);
+            popup->hide();
+            consumed = true;
+            break;
+
+        case Qt::Key_Up:
+        case Qt::Key_Down:
+        case Qt::Key_Home:
+        case Qt::Key_End:
+        case Qt::Key_PageUp:
+        case Qt::Key_PageDown:
+            break;
+
+        default:
+            editor->setFocus();
+            editor->event(ev);
+            popup->hide();
+            break;
+        }
+
+        return consumed;
+    }
+
+    return false;
+}
+
+void GSuggestCompletion::showCompletion(const QStringList &choices) {
+
+    if (choices.isEmpty())
+        return;
+
+    popup->setUpdatesEnabled(false);
+    popup->clear();
+    for (int i = 0; i < choices.count(); ++i) {
+        QListWidgetItem * item;
+        item = new QListWidgetItem(popup);
+        item->setText(choices[i]);
+    }
+    popup->setCurrentItem(0);
+    popup->adjustSize();
+    popup->setUpdatesEnabled(true);
+
+    popup->move(editor->mapToGlobal(QPoint(0, editor->height())));
+    popup->setFocus();
+    popup->show();
+}
+
+void GSuggestCompletion::doneCompletion() {
+    timer->stop();
+    popup->hide();
+    editor->setFocus();
+    QListWidgetItem *item = popup->currentItem();
+    if (item) {
+        editor->setText(item->text());
+        QKeyEvent *e;
+        e = new QKeyEvent(QEvent::KeyPress, Qt::Key_Enter, Qt::NoModifier);
+        QApplication::postEvent(editor, e);
+        e = new QKeyEvent(QEvent::KeyRelease, Qt::Key_Enter, Qt::NoModifier);
+        QApplication::postEvent(editor, e);
+    }
+}
+
+void GSuggestCompletion::preventSuggest() {
+    timer->stop();
+}
+
+void GSuggestCompletion::autoSuggest() {
+    QString str = editor->text();
+    originalText = str;
+    qDebug() << "originalText" << originalText;
+    if (str.isEmpty()) return;
+
+    QString url = QString(GSUGGEST_URL).arg(QLocale::system().name().replace("_", "-"), str);
+
+    QObject *reply = The::http()->get(url);
+    connect(reply, SIGNAL(data(QByteArray)), SLOT(handleNetworkData(QByteArray)));
+}
+
+void GSuggestCompletion::handleNetworkData(QByteArray response) {
+
+    QStringList choices;
+
+    QXmlStreamReader xml(response);
+    while (!xml.atEnd()) {
+        xml.readNext();
+        if (xml.tokenType() == QXmlStreamReader::StartElement)
+            if (xml.name() == "suggestion") {
+            QStringRef str = xml.attributes().value("data");
+            choices << str.toString();
+        }
+    }
+
+    showCompletion(choices);
+
+}
+
+void GSuggestCompletion::currentItemChanged(QListWidgetItem *current) {
+    if (current) {
+        qDebug() << "current" << current->text();
+        current->setSelected(true);
+        editor->setText(current->text());
+        editor->setSelection(originalText.length(), editor->text().length());
+    } else {
+        popup->clearSelection();
+    }
+}
diff --git a/src/googlesuggest.h b/src/googlesuggest.h
new file mode 100644 (file)
index 0000000..8ca766b
--- /dev/null
@@ -0,0 +1,30 @@
+#ifndef GOOGLESUGGEST_H
+#define GOOGLESUGGEST_H
+
+#include <QtGui>
+
+class GSuggestCompletion : public QObject {
+    Q_OBJECT
+
+public:
+    GSuggestCompletion(QLineEdit *parent);
+    ~GSuggestCompletion();
+    bool eventFilter(QObject *obj, QEvent *ev);
+    void showCompletion(const QStringList &choices);
+
+public slots:
+    void doneCompletion();
+    void preventSuggest();
+    void autoSuggest();
+    void handleNetworkData(QByteArray response);
+    void currentItemChanged(QListWidgetItem *current);
+
+private:
+    QLineEdit *editor;
+    QString originalText;
+    QListWidget *popup;
+    QTimer *timer;
+
+};
+
+#endif // GOOGLESUGGEST_H
index 8a42d8afd10362ecc27507395e2726a88354e83a..3c4e1faa79040555fd2bd565092d8ca81751d7b2 100644 (file)
 #include <QtGui/QStyle>
 #include <QtGui/QStyleOptionFrameV2>
 
+#include "googlesuggest.h"
+
 ClearButton::ClearButton(QWidget *parent)
-  : QAbstractButton(parent)
+        : QAbstractButton(parent)
 {
     setCursor(Qt::ArrowCursor);
     setToolTip(tr("Clear"));
@@ -95,8 +97,8 @@ protected:
 };
 
 SearchButton::SearchButton(QWidget *parent)
-  : QAbstractButton(parent),
-    m_menu(0)
+        : QAbstractButton(parent),
+        m_menu(0)
 {
     setObjectName(QLatin1String("SearchButton"));
     setCursor(Qt::ArrowCursor);
@@ -159,7 +161,7 @@ void SearchButton::paintEvent(QPaintEvent *event)
     - When there is text a clear button is displayed on the right hand side
  */
 SearchLineEdit::SearchLineEdit(QWidget *parent) : ExLineEdit(parent),
-    m_searchButton(new SearchButton(this))
+m_searchButton(new SearchButton(this))
 {
     connect(lineEdit(), SIGNAL(textChanged(const QString &)),
             this, SIGNAL(textChanged(const QString &)));
@@ -172,6 +174,9 @@ SearchLineEdit::SearchLineEdit(QWidget *parent) : ExLineEdit(parent),
 
     QSizePolicy policy = sizePolicy();
     setSizePolicy(QSizePolicy::Preferred, policy.verticalPolicy());
+
+    // completion
+    completion = new GSuggestCompletion(m_lineEdit);
 }
 
 void SearchLineEdit::paintEvent(QPaintEvent *event)
@@ -238,5 +243,6 @@ QMenu *SearchLineEdit::menu() const
 
 void SearchLineEdit::returnPressed()
 {
+    completion->preventSuggest();
     emit search(lineEdit()->text());
 }
index b7b80056e63691f518d4380da9728845a6c18082..99ab26678c052ba86a95840294e5c088b4db4f8e 100644 (file)
@@ -48,6 +48,7 @@ class QMenu;
 QT_END_NAMESPACE
 
 class SearchButton;
+class GSuggestCompletion;
 
 /*
     Clear button on the right hand side of the search widget.
@@ -97,6 +98,8 @@ private:
 
     SearchButton *m_searchButton;
     QString m_inactiveText;
+
+    GSuggestCompletion *completion;
 };
 
 #endif // SEARCHLINEEDIT_H