]> git.sur5r.net Git - minitube/commitdiff
better search suggestions
authorFlavio Tordini <flavio.tordini@gmail.com>
Mon, 13 Oct 2014 14:12:45 +0000 (16:12 +0200)
committerFlavio <flavio.tordini@gmail.com>
Mon, 13 Oct 2014 14:12:45 +0000 (16:12 +0200)
src/Suggester.h [deleted file]
src/autocomplete.cpp
src/autocomplete.h
src/mainwindow.cpp
src/mainwindow.h
src/mediaview.cpp
src/searchlineedit.h
src/searchview.cpp
src/searchview.h

diff --git a/src/Suggester.h b/src/Suggester.h
deleted file mode 100644 (file)
index cca7f5f..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-/* $BEGIN_LICENSE
-
-This file is part of Minitube.
-Copyright 2009, Flavio Tordini <flavio.tordini@gmail.com>
-
-Minitube 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 3 of the License, or
-(at your option) any later version.
-
-Minitube 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 Minitube.  If not, see <http://www.gnu.org/licenses/>.
-
-$END_LICENSE */
-
-#ifndef SUGGESTER_H
-#define SUGGESTER_H
-
-#include <QtCore>
-
-class Suggestion {
-
-public:
-    Suggestion(QString value = QString(),
-               QString type = QString()) :
-        value(value), type(type) { }
-    QString value;
-    QString type;
-
-    bool operator==(const Suggestion &other) const {
-        return (value == other.value) && (type == other.type);
-    }
-
-    bool operator!=(const Suggestion &other) const {
-        return !(*this == other);
-    }
-
-    bool operator==(Suggestion *other) const {
-        qDebug() << "Comparing" << this << other;
-        return (value == other->value) && (type == other->type);
-    }
-
-    bool operator!=(Suggestion *other) const {
-        return !(this == other);
-    }
-
-};
-
-class Suggester : public QObject {
-
-    Q_OBJECT
-
-public:
-    Suggester(QObject *parent) : QObject(parent) { }
-    virtual void suggest(const QString &query) = 0;
-
-signals:
-    void ready(const QList<Suggestion*> &suggestions);
-
-};
-
-#endif // SUGGESTER_H
-
index e6e0d429af0fd4e9d08966c35a465d8371439154..cb0773a1cb85ee355e02bc711c9f805282286ade 100644 (file)
@@ -21,14 +21,13 @@ $END_LICENSE */
 #include "suggester.h"
 #ifdef APP_MAC
 #include "searchlineedit_mac.h"
+#include "macutils.h"
 #else
 #include "searchlineedit.h"
 #endif
 
 AutoComplete::AutoComplete(SearchLineEdit *buddy, QLineEdit *lineEdit):
-    QObject(buddy), buddy(buddy), lineEdit(lineEdit), suggester(0) {
-
-    enabled = true;
+    QObject(buddy), buddy(buddy), lineEdit(lineEdit), enabled(true), suggester(0) {
 
     popup = new QListWidget();
     popup->setMouseTracking(true);
@@ -37,18 +36,17 @@ AutoComplete::AutoComplete(SearchLineEdit *buddy, QLineEdit *lineEdit):
     popup->setFocusPolicy(Qt::NoFocus);
     popup->setFocusProxy(buddy);
     popup->installEventFilter(this);
+    buddy->window()->installEventFilter(this);
 
+    // style
     popup->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
     popup->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
     popup->setWindowOpacity(.9);
     popup->setProperty("suggest", true);
-    popup->setFrameShape(QFrame::NoFrame);
-    popup->setAttribute(Qt::WA_TranslucentBackground);
-    popup->viewport()->setStyleSheet("border:0; border-radius:5px; background:palette(base)");
 
     connect(popup, SIGNAL(itemClicked(QListWidgetItem*)), SLOT(acceptSuggestion()));
     connect(popup, SIGNAL(currentItemChanged(QListWidgetItem*, QListWidgetItem*)),
-        SLOT(currentItemChanged(QListWidgetItem*)));
+            SLOT(currentItemChanged(QListWidgetItem*)));
     connect(popup, SIGNAL(itemEntered(QListWidgetItem*)), SLOT(itemEntered(QListWidgetItem *)));
 
     timer = new QTimer(this);
@@ -63,7 +61,17 @@ AutoComplete::~AutoComplete() {
 }
 
 bool AutoComplete::eventFilter(QObject *obj, QEvent *ev) {
-    if (obj != popup) return false;
+    if (obj != popup) {
+        switch (ev->type()) {
+        case QEvent::Move:
+        case QEvent::Resize:
+            adjustPosition();
+            break;
+        default:
+            break;
+        }
+        return false;
+    }
 
     if (ev->type() == QEvent::Leave) {
         popup->setCurrentItem(0);
@@ -72,10 +80,8 @@ bool AutoComplete::eventFilter(QObject *obj, QEvent *ev) {
         return true;
     }
 
-    if (ev->type() == QEvent::FocusOut) {
-        popup->hide();
-        buddy->setText(originalText);
-        buddy->setFocus();
+    if (ev->type() == QEvent::FocusOut || ev->type() == QEvent::MouseButtonPress) {
+        hideSuggestions();
         return true;
     }
 
@@ -90,17 +96,13 @@ bool AutoComplete::eventFilter(QObject *obj, QEvent *ev) {
                 acceptSuggestion();
                 consumed = true;
             } else {
-                buddy->setFocus();
                 lineEdit->event(ev);
-                popup->hide();
+                hideSuggestions();
             }
             break;
 
         case Qt::Key_Escape:
-            popup->hide();
-            popup->clear();
-            buddy->setText(originalText);
-            buddy->setFocus();
+            hideSuggestions();
             consumed = true;
             break;
 
@@ -137,15 +139,13 @@ bool AutoComplete::eventFilter(QObject *obj, QEvent *ev) {
 
 void AutoComplete::showCompletion(const QList<Suggestion *> &suggestions) {
     if (suggestions.isEmpty()) {
-        popup->clear();
-        popup->hide();
+        hideSuggestions();
         return;
     }
     popup->setUpdatesEnabled(false);
     popup->clear();
     for (int i = 0; i < suggestions.count(); ++i) {
-        QListWidgetItem * item;
-        item = new QListWidgetItem(popup);
+        QListWidgetItem *item = new QListWidgetItem(popup);
         Suggestion *s = suggestions[i];
         item->setText(s->value);
         if (!s->type.isEmpty())
@@ -156,25 +156,24 @@ void AutoComplete::showCompletion(const QList<Suggestion *> &suggestions) {
     for (int i = 0; i < suggestions.count(); ++i)
         h += popup->sizeHintForRow(i);
     popup->resize(buddy->width(), h);
-    popup->move(buddy->mapToGlobal(QPoint(0, buddy->height())));
-    popup->setFocus();
-
-    if (popup->isHidden()) popup->show();
+    adjustPosition();
     popup->setUpdatesEnabled(true);
+
+    if (popup->isHidden()) {
+        popup->show();
+        popup->setFocus();
+    }
 }
 
 void AutoComplete::acceptSuggestion() {
-    timer->stop();
-    originalText.clear();
-    popup->hide();
-    buddy->setFocus();
     int index = popup->currentIndex().row();
     if (index >= 0 && index < suggestions.size()) {
         Suggestion* suggestion = suggestions.at(index);
         buddy->setText(suggestion->value);
         emit suggestionAccepted(suggestion);
         emit suggestionAccepted(suggestion->value);
-        popup->clear();
+        originalText.clear();
+        hideSuggestions();
     } else qWarning() << "No suggestion for index" << index;
 }
 
@@ -182,7 +181,6 @@ void AutoComplete::preventSuggest() {
     timer->stop();
     enabled = false;
     popup->hide();
-    popup->setFrameShape(QFrame::NoFrame);
 }
 
 void AutoComplete::enableSuggest() {
@@ -197,15 +195,13 @@ void AutoComplete::setSuggester(Suggester* suggester) {
 
 void AutoComplete::suggest() {
     if (!enabled) return;
-    if (!buddy->hasFocus()) return;
 
     popup->setCurrentItem(0);
     popup->clearSelection();
 
     originalText = buddy->text();
     if (originalText.isEmpty()) {
-        popup->hide();
-        buddy->setFocus();
+        hideSuggestions();
         return;
     }
 
@@ -220,6 +216,25 @@ void AutoComplete::suggestionsReady(const QList<Suggestion *> &suggestions) {
     showCompletion(suggestions);
 }
 
+void AutoComplete::adjustPosition() {
+    popup->move(buddy->mapToGlobal(QPoint(0, buddy->height())));
+}
+
+void AutoComplete::hideSuggestions() {
+#ifdef APP_MAC
+    mac::fadeOutWindow(popup);
+#else
+    popup->hide();
+    popup->clear();
+#endif
+    if (!originalText.isEmpty()) {
+        buddy->setText(originalText);
+        originalText.clear();
+    }
+    buddy->setFocus();
+    timer->stop();
+}
+
 void AutoComplete::itemEntered(QListWidgetItem *item) {
     if (!item) return;
     item->setSelected(true);
index 6894d7eda6f7ed658b19c339d417f3aa3df4c3fb..1699ebe83ec3a71eaefa99b079ab5bab87818e8c 100644 (file)
@@ -37,21 +37,24 @@ public:
     void showCompletion(const QList<Suggestion*> &suggestions);
     void setSuggester(Suggester* suggester);
     QListWidget* getPopup() { return popup; }
-
-public slots:
-    void acceptSuggestion();
     void preventSuggest();
     void enableSuggest();
-    void suggest();
-    void itemEntered(QListWidgetItem *item);
-    void currentItemChanged(QListWidgetItem *item);
-    void suggestionsReady(const QList<Suggestion*> &suggestions);
 
 signals:
     void suggestionAccepted(Suggestion *suggestion);
     void suggestionAccepted(const QString &value);
 
+private slots:
+    void acceptSuggestion();
+    void suggest();
+    void itemEntered(QListWidgetItem *item);
+    void currentItemChanged(QListWidgetItem *item);
+    void suggestionsReady(const QList<Suggestion*> &suggestions);
+    void adjustPosition();
+
 private:
+    void hideSuggestions();
+
     SearchLineEdit *buddy;
     QLineEdit *lineEdit;
     QString originalText;
index 9ea7777b1c29fa42f7c58a832dcd258ba5219a85..d7093d6ffff15c7109fe2a5b1fbe8d383d672c52 100644 (file)
@@ -727,6 +727,7 @@ void MainWindow::createToolBars() {
 
 #ifdef APP_PHONON_SEEK
     seekSlider = new Phonon::SeekSlider(this);
+    seekSlider->setTracking(true);
     seekSlider->setIconVisible(false);
     seekSlider->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
     mainToolBar->addWidget(seekSlider);
@@ -774,8 +775,8 @@ void MainWindow::createToolBars() {
 #endif
     toolbarSearch->setMinimumWidth(toolbarSearch->fontInfo().pixelSize()*15);
     toolbarSearch->setSuggester(new YTSuggester(this));
-    connect(toolbarSearch, SIGNAL(search(const QString&)), this, SLOT(startToolbarSearch(const QString&)));
-    connect(toolbarSearch, SIGNAL(suggestionAccepted(const QString&)), SLOT(startToolbarSearch(const QString&)));
+    connect(toolbarSearch, SIGNAL(search(const QString&)), SLOT(search(const QString&)));
+    connect(toolbarSearch, SIGNAL(suggestionAccepted(Suggestion*)), SLOT(suggestionAccepted(Suggestion*)));
     toolbarSearch->setStatusTip(searchFocusAct->statusTip());
 #ifdef APP_MAC
     mainToolBar->addWidget(searchWrapper);
@@ -1512,29 +1513,25 @@ void MainWindow::toggleDownloads(bool show) {
     else goBack();
 }
 
-void MainWindow::startToolbarSearch(QString query) {
-    query = query.trimmed();
-
-    // check for empty query
-    if (query.length() == 0) {
-        return;
-    }
+void MainWindow::suggestionAccepted(Suggestion *suggestion) {
+    search(suggestion->value);
+}
 
+void MainWindow::search(const QString &query) {
+    QString q = query.trimmed();
+    if (q.length() == 0) return;
     SearchParams *searchParams = new SearchParams();
-    searchParams->setKeywords(query);
-
-    // go!
+    searchParams->setKeywords(q);
     showMedia(searchParams);
 }
 
 void MainWindow::dragEnterEvent(QDragEnterEvent *event) {
     if (event->mimeData()->hasFormat("text/uri-list")) {
         QList<QUrl> urls = event->mimeData()->urls();
-        if (urls.isEmpty())
-            return;
+        if (urls.isEmpty()) return;
         QUrl url = urls.first();
         QString videoId = YTSearch::videoIdFromUrl(url.toString());
-        if (!videoId.isNull())
+        if (!videoId.isEmpty())
             event->acceptProposedAction();
     }
 }
@@ -1547,7 +1544,7 @@ void MainWindow::dropEvent(QDropEvent *event) {
         return;
     QUrl url = urls.first();
     QString videoId = YTSearch::videoIdFromUrl(url.toString());
-    if (!videoId.isNull()) {
+    if (!videoId.isEmpty()) {
         setWindowTitle(url.toString());
         SearchParams *searchParams = new SearchParams();
         searchParams->setKeywords(videoId);
index be9ff146f3894fceab465b563cb567a1559a72d5..1c761714e2097561ae53c138e7fcb65fac115e8b 100644 (file)
@@ -31,7 +31,6 @@ $END_LICENSE */
 #include <phonon/mediaobject.h>
 #include <phonon/seekslider.h>
 #endif
-#include "view.h"
 
 class HomeView;
 class MediaView;
@@ -40,6 +39,7 @@ class SearchLineEdit;
 class UpdateChecker;
 class SearchParams;
 class VideoSource;
+class Suggestion;
 
 class MainWindow : public QMainWindow {
 
@@ -73,7 +73,8 @@ public slots:
     void restore();
     void messageReceived(const QString &message);
     void quit();
-    void startToolbarSearch(QString query);
+    void suggestionAccepted(Suggestion *suggestion);
+    void search(const QString &query);
     void goBack();
     void showMessage(QString message);
 #ifdef APP_ACTIVATION
index 2279404bc8a637e276437424d85f7529c89207e9..7b62b1ee5f6611ee3f6dbc404ad1a63f4dc60cc4 100644 (file)
@@ -102,7 +102,7 @@ void MediaView::initialize() {
     connect(playlistModel, SIGNAL(haveSuggestions(const QStringList &)),
             sidebar, SLOT(showSuggestions(const QStringList &)));
     connect(sidebar, SIGNAL(suggestionAccepted(QString)),
-            MainWindow::instance(), SLOT(startToolbarSearch(QString)));
+            MainWindow::instance(), SLOT(search(QString)));
     splitter->addWidget(sidebar);
 
     videoAreaWidget = new VideoAreaWidget(this);
@@ -301,7 +301,8 @@ void MediaView::disappear() {
 
 }
 
-void MediaView::handleError(QString /* message */) {
+void MediaView::handleError(QString message) {
+    qWarning() << __PRETTY_FUNCTION__ << message;
 #ifdef APP_PHONON_SEEK
     mediaObject->play();
 #else
index 21245652d8941071e5b9e7ceae40d1e0d1ee23df..5f9fd858d3496cf0ded401c2cb593af14ca704fb 100644 (file)
@@ -41,7 +41,7 @@ signals:
     void textChanged(const QString &text);
     void textEdited(const QString &text);
     void search(const QString &text);
-    void suggestionAccepted(const QString &suggestion);
+    void suggestionAccepted(Suggestion *suggestion);
 
 public:
     SearchLineEdit(QWidget *parent = 0);
index 77aa0dfc0c9d83d9b1714090ddbe598039d33a8e..42707d477aa15a1ad919e43c75a16a6e53211cfe 100644 (file)
@@ -134,10 +134,9 @@ SearchView::SearchView(QWidget *parent) : QWidget(parent) {
 
     queryEdit = new SearchLineEdit(this);
     queryEdit->setFont(biggerFont);
-    queryEdit->setMinimumWidth(queryEdit->fontInfo().pixelSize()*15);
     connect(queryEdit, SIGNAL(search(const QString&)), SLOT(watch(const QString&)));
-    connect(queryEdit, SIGNAL(textChanged(const QString &)), SLOT(textChanged(const QString &)));
-    connect(queryEdit, SIGNAL(suggestionAccepted(const QString&)), SLOT(watch(const QString&)));
+    connect(queryEdit, SIGNAL(textEdited(const QString &)), SLOT(textChanged(const QString &)));
+    connect(queryEdit, SIGNAL(suggestionAccepted(Suggestion*)), SLOT(suggestionAccepted(Suggestion*)));
 
     youtubeSuggest = new YTSuggester(this);
     channelSuggest = new ChannelSuggest(this);
@@ -398,3 +397,7 @@ void SearchView::searchTypeChanged(int index) {
     queryEdit->selectAll();
     queryEdit->setFocus();
 }
+
+void SearchView::suggestionAccepted(Suggestion *suggestion) {
+    watch(suggestion->value);
+}
index 490a9a2a4262ad5efedfa16018fe7a16a6e145cd..f513c61e9e9f70fd9ed548eb22cab948d637a51c 100644 (file)
@@ -31,6 +31,7 @@ class SearchLineEdit;
 class SearchParams;
 class YTSuggester;
 class ChannelSuggest;
+class Suggestion;
 
 class SearchView : public QWidget, public View {
 
@@ -58,6 +59,7 @@ private slots:
     void watch();
     void textChanged(const QString &text);
     void searchTypeChanged(int index);
+    void suggestionAccepted(Suggestion *suggestion);
 
 private:
     YTSuggester *youtubeSuggest;