]> git.sur5r.net Git - minitube/blob - src/autocomplete.cpp
Moved filename chars function to DataUtils
[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     popup->setFrameShape(QFrame::NoFrame);
45     popup->setAttribute(Qt::WA_TranslucentBackground);
46     popup->viewport()->setStyleSheet("border:0; border-radius:5px; background:palette(base)");
47
48     connect(popup, SIGNAL(itemClicked(QListWidgetItem*)), SLOT(doneCompletion()));
49
50     // connect(popup, SIGNAL(currentItemChanged(QListWidgetItem *, QListWidgetItem *)),
51     //    SLOT(currentItemChanged(QListWidgetItem *)));
52
53     // mouse hover
54     // connect(popup, SIGNAL(itemEntered(QListWidgetItem*)),
55     //    SLOT(currentItemChanged(QListWidgetItem *)));
56
57     timer = new QTimer(this);
58     timer->setSingleShot(true);
59     timer->setInterval(600);
60     connect(timer, SIGNAL(timeout()), SLOT(autoSuggest()));
61     connect(buddy, SIGNAL(textChanged(QString)), timer, SLOT(start()));
62
63 }
64
65 AutoComplete::~AutoComplete() {
66     delete popup;
67 }
68
69 bool AutoComplete::eventFilter(QObject *obj, QEvent *ev) {
70     if (obj != popup)
71         return false;
72
73     if (ev->type() == QEvent::FocusOut) {
74         popup->hide();
75         buddy->setFocus();
76         return true;
77     }
78
79     if (ev->type() == QEvent::MouseButtonPress) {
80         popup->hide();
81         buddy->setFocus();
82         buddy->setText(originalText);
83         return true;
84     }
85
86     if (ev->type() == QEvent::KeyPress) {
87
88         bool consumed = false;
89
90         QKeyEvent *keyEvent = static_cast<QKeyEvent*>(ev);
91         int key = keyEvent->key();
92         // qDebug() << keyEvent->text();
93         switch (key) {
94         case Qt::Key_Enter:
95         case Qt::Key_Return:
96             if (popup->currentItem()) {
97                 doneCompletion();
98                 consumed = true;
99             } else {
100                 buddy->setFocus();
101                 editor->event(ev);
102                 popup->hide();
103             }
104             break;
105
106         case Qt::Key_Escape:
107             buddy->setFocus();
108             editor->setText(originalText);
109             popup->hide();
110             consumed = true;
111             break;
112
113         case Qt::Key_Up:
114         case Qt::Key_Down:
115         case Qt::Key_Home:
116         case Qt::Key_End:
117         case Qt::Key_PageUp:
118         case Qt::Key_PageDown:
119             break;
120
121         default:
122             // qDebug() << keyEvent->text();
123             buddy->setFocus();
124             editor->event(ev);
125             popup->hide();
126             break;
127         }
128
129         return consumed;
130     }
131
132     return false;
133 }
134
135 void AutoComplete::showCompletion(const QStringList &choices) {
136
137     if (choices.isEmpty())
138         return;
139
140     popup->setUpdatesEnabled(false);
141     popup->clear();
142     for (int i = 0; i < choices.count(); ++i) {
143         QListWidgetItem * item;
144         item = new QListWidgetItem(popup);
145         item->setText(choices[i]);
146     }
147     popup->setCurrentItem(0);
148     popup->adjustSize();
149     popup->setUpdatesEnabled(true);
150
151     int h = popup->sizeHintForRow(0) * choices.count() + 4;
152     popup->resize(buddy->width(), h);
153
154     popup->move(buddy->mapToGlobal(QPoint(0, buddy->height())));
155
156     popup->setFrameShape(QFrame::NoFrame);
157
158     popup->setFocus();
159     popup->show();
160 }
161
162 void AutoComplete::doneCompletion() {
163     timer->stop();
164     popup->hide();
165     buddy->setFocus();
166     QListWidgetItem *item = popup->currentItem();
167     if (item) {
168         buddy->setText(item->text());
169         emit suggestionAccepted(item->text());
170     }
171 }
172
173 void AutoComplete::preventSuggest() {
174     // qDebug() << "preventSuggest";
175     timer->stop();
176     enabled = false;
177     popup->hide();
178     popup->setFrameShape(QFrame::NoFrame);
179 }
180
181 void AutoComplete::enableSuggest() {
182     // qDebug() << "enableSuggest";
183     enabled = true;
184 }
185
186 void AutoComplete::setSuggester(Suggester* suggester) {
187     if (this->suggester) this->suggester->disconnect();
188     this->suggester = suggester;
189     connect(suggester, SIGNAL(ready(QStringList)), SLOT(suggestionsReady(QStringList)));
190 }
191
192 void AutoComplete::autoSuggest() {
193     if (!enabled) return;
194     if (!buddy->hasFocus()) return;
195
196     QString query = editor->text();
197     originalText = query;
198     // qDebug() << "originalText" << originalText;
199     if (query.isEmpty()) {
200         popup->hide();
201         buddy->setFocus();
202         return;
203     }
204
205     if (suggester)
206         suggester->suggest(query);
207 }
208
209 void AutoComplete::suggestionsReady(QStringList suggestions) {
210     if (!enabled) return;
211     showCompletion(suggestions);
212 }
213
214 void AutoComplete::currentItemChanged(QListWidgetItem *current) {
215     if (current) {
216         // qDebug() << "current" << current->text();
217         current->setSelected(true);
218         buddy->setText(current->text());
219         editor->setSelection(originalText.length(), editor->text().length());
220     }
221 }