]> git.sur5r.net Git - minitube/blob - src/autocomplete.cpp
Merge tag 'upstream/2.1.3'
[minitube] / src / autocomplete.cpp
1 /* $BEGIN_LICENSE
2
3 This file is part of Minitube.
4 Copyright 2009, Flavio Tordini <flavio.tordini@gmail.com>
5
6 Minitube is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 Minitube is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with Minitube.  If not, see <http://www.gnu.org/licenses/>.
18
19 $END_LICENSE */
20
21 #include "autocomplete.h"
22 #include "suggester.h"
23 #ifdef APP_MAC
24 #include "searchlineedit_mac.h"
25 #else
26 #include "searchlineedit.h"
27 #endif
28
29 AutoComplete::AutoComplete(SearchLineEdit *parent, QLineEdit *editor):
30     QObject(parent), editor(editor), suggester(0) {
31
32     buddy = parent;
33     enabled = true;
34
35     popup = new QListWidget;
36     popup->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
37     popup->setMouseTracking(true);
38     popup->setWindowOpacity(.9);
39     popup->installEventFilter(this);
40     popup->setWindowFlags(Qt::Popup);
41     popup->setFocusPolicy(Qt::NoFocus);
42     popup->setFocusProxy(buddy);
43
44     connect(popup, SIGNAL(itemClicked(QListWidgetItem*)), SLOT(doneCompletion()));
45
46     // connect(popup, SIGNAL(currentItemChanged(QListWidgetItem *, QListWidgetItem *)),
47     //    SLOT(currentItemChanged(QListWidgetItem *)));
48
49     // mouse hover
50     // connect(popup, SIGNAL(itemEntered(QListWidgetItem*)),
51     //    SLOT(currentItemChanged(QListWidgetItem *)));
52
53     timer = new QTimer(this);
54     timer->setSingleShot(true);
55     timer->setInterval(600);
56     connect(timer, SIGNAL(timeout()), SLOT(autoSuggest()));
57     connect(buddy, SIGNAL(textChanged(QString)), timer, SLOT(start()));
58
59 }
60
61 AutoComplete::~AutoComplete() {
62     delete popup;
63 }
64
65 bool AutoComplete::eventFilter(QObject *obj, QEvent *ev) {
66     if (obj != popup)
67         return false;
68
69     if (ev->type() == QEvent::FocusOut) {
70         popup->hide();
71         buddy->setFocus();
72         return true;
73     }
74
75     if (ev->type() == QEvent::MouseButtonPress) {
76         popup->hide();
77         buddy->setFocus();
78         buddy->setText(originalText);
79         return true;
80     }
81
82     if (ev->type() == QEvent::KeyPress) {
83
84         bool consumed = false;
85
86         QKeyEvent *keyEvent = static_cast<QKeyEvent*>(ev);
87         int key = keyEvent->key();
88         // qDebug() << keyEvent->text();
89         switch (key) {
90         case Qt::Key_Enter:
91         case Qt::Key_Return:
92             if (popup->currentItem()) {
93                 doneCompletion();
94                 consumed = true;
95             } else {
96                 buddy->setFocus();
97                 editor->event(ev);
98                 popup->hide();
99             }
100             break;
101
102         case Qt::Key_Escape:
103             buddy->setFocus();
104             editor->setText(originalText);
105             popup->hide();
106             consumed = true;
107             break;
108
109         case Qt::Key_Up:
110         case Qt::Key_Down:
111         case Qt::Key_Home:
112         case Qt::Key_End:
113         case Qt::Key_PageUp:
114         case Qt::Key_PageDown:
115             break;
116
117         default:
118             // qDebug() << keyEvent->text();
119             buddy->setFocus();
120             editor->event(ev);
121             popup->hide();
122             break;
123         }
124
125         return consumed;
126     }
127
128     return false;
129 }
130
131 void AutoComplete::showCompletion(const QStringList &choices) {
132
133     if (choices.isEmpty())
134         return;
135
136     popup->setUpdatesEnabled(false);
137     popup->clear();
138     for (int i = 0; i < choices.count(); ++i) {
139         QListWidgetItem * item;
140         item = new QListWidgetItem(popup);
141         item->setText(choices[i]);
142     }
143     popup->setCurrentItem(0);
144     popup->adjustSize();
145     popup->setUpdatesEnabled(true);
146
147     int h = popup->sizeHintForRow(0) * choices.count() + 4;
148     popup->resize(buddy->width(), h);
149
150     popup->move(buddy->mapToGlobal(QPoint(0, buddy->height())));
151
152     popup->setFocus();
153     popup->show();
154 }
155
156 void AutoComplete::doneCompletion() {
157     timer->stop();
158     popup->hide();
159     buddy->setFocus();
160     QListWidgetItem *item = popup->currentItem();
161     if (item) {
162         buddy->setText(item->text());
163         emit suggestionAccepted(item->text());
164     }
165 }
166
167 void AutoComplete::preventSuggest() {
168     // qDebug() << "preventSuggest";
169     timer->stop();
170     enabled = false;
171     popup->hide();
172 }
173
174 void AutoComplete::enableSuggest() {
175     // qDebug() << "enableSuggest";
176     enabled = true;
177 }
178
179 void AutoComplete::setSuggester(Suggester* suggester) {
180     if (this->suggester) this->suggester->disconnect();
181     this->suggester = suggester;
182     connect(suggester, SIGNAL(ready(QStringList)), SLOT(suggestionsReady(QStringList)));
183 }
184
185 void AutoComplete::autoSuggest() {
186     if (!enabled) return;
187     if (!buddy->hasFocus()) return;
188
189     QString query = editor->text();
190     originalText = query;
191     // qDebug() << "originalText" << originalText;
192     if (query.isEmpty()) {
193         popup->hide();
194         buddy->setFocus();
195         return;
196     }
197
198     if (suggester)
199         suggester->suggest(query);
200 }
201
202 void AutoComplete::suggestionsReady(QStringList suggestions) {
203     if (!enabled) return;
204     showCompletion(suggestions);
205 }
206
207 void AutoComplete::currentItemChanged(QListWidgetItem *current) {
208     if (current) {
209         // qDebug() << "current" << current->text();
210         current->setSelected(true);
211         buddy->setText(current->text());
212         editor->setSelection(originalText.length(), editor->text().length());
213     }
214 }