]> git.sur5r.net Git - minitube/blob - src/autocomplete.cpp
ac09e9c5510b90bd08a4b4e2491b61982bb5b4ea
[minitube] / src / autocomplete.cpp
1 #include "autocomplete.h"
2 #include "suggester.h"
3 #ifdef APP_MAC
4 #include "searchlineedit_mac.h"
5 #else
6 #include "searchlineedit.h"
7 #endif
8
9 AutoComplete::AutoComplete(SearchLineEdit *parent, QLineEdit *editor):
10     QObject(parent), editor(editor), suggester(0) {
11
12     buddy = parent;
13     enabled = true;
14
15     popup = new QListWidget;
16     popup->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
17     popup->setMouseTracking(true);
18     popup->setWindowOpacity(.9);
19     popup->installEventFilter(this);
20     popup->setWindowFlags(Qt::Popup);
21     popup->setFocusPolicy(Qt::NoFocus);
22     popup->setFocusProxy(buddy);
23
24     connect(popup, SIGNAL(itemClicked(QListWidgetItem*)), SLOT(doneCompletion()));
25
26     // connect(popup, SIGNAL(currentItemChanged(QListWidgetItem *, QListWidgetItem *)),
27     //    SLOT(currentItemChanged(QListWidgetItem *)));
28
29     // mouse hover
30     // connect(popup, SIGNAL(itemEntered(QListWidgetItem*)),
31     //    SLOT(currentItemChanged(QListWidgetItem *)));
32
33     timer = new QTimer(this);
34     timer->setSingleShot(true);
35     timer->setInterval(600);
36     connect(timer, SIGNAL(timeout()), SLOT(autoSuggest()));
37     connect(buddy, SIGNAL(textChanged(QString)), timer, SLOT(start()));
38
39 }
40
41 AutoComplete::~AutoComplete() {
42     delete popup;
43 }
44
45 bool AutoComplete::eventFilter(QObject *obj, QEvent *ev) {
46     if (obj != popup)
47         return false;
48
49     if (ev->type() == QEvent::FocusOut) {
50         popup->hide();
51         buddy->setFocus();
52         return true;
53     }
54
55     if (ev->type() == QEvent::MouseButtonPress) {
56         popup->hide();
57         buddy->setFocus();
58         buddy->setText(originalText);
59         return true;
60     }
61
62     if (ev->type() == QEvent::KeyPress) {
63
64         bool consumed = false;
65
66         QKeyEvent *keyEvent = static_cast<QKeyEvent*>(ev);
67         int key = keyEvent->key();
68         // qDebug() << keyEvent->text();
69         switch (key) {
70         case Qt::Key_Enter:
71         case Qt::Key_Return:
72             if (popup->currentItem()) {
73                 doneCompletion();
74                 consumed = true;
75             } else {
76                 buddy->setFocus();
77                 editor->event(ev);
78                 popup->hide();
79             }
80             break;
81
82         case Qt::Key_Escape:
83             buddy->setFocus();
84             editor->setText(originalText);
85             popup->hide();
86             consumed = true;
87             break;
88
89         case Qt::Key_Up:
90         case Qt::Key_Down:
91         case Qt::Key_Home:
92         case Qt::Key_End:
93         case Qt::Key_PageUp:
94         case Qt::Key_PageDown:
95             break;
96
97         default:
98             // qDebug() << keyEvent->text();
99             buddy->setFocus();
100             editor->event(ev);
101             popup->hide();
102             break;
103         }
104
105         return consumed;
106     }
107
108     return false;
109 }
110
111 void AutoComplete::showCompletion(const QStringList &choices) {
112
113     if (choices.isEmpty())
114         return;
115
116     popup->setUpdatesEnabled(false);
117     popup->clear();
118     for (int i = 0; i < choices.count(); ++i) {
119         QListWidgetItem * item;
120         item = new QListWidgetItem(popup);
121         item->setText(choices[i]);
122     }
123     popup->setCurrentItem(0);
124     popup->adjustSize();
125     popup->setUpdatesEnabled(true);
126
127     int h = popup->sizeHintForRow(0) * choices.count() + 4;
128     popup->resize(buddy->width(), h);
129
130     popup->move(buddy->mapToGlobal(QPoint(0, buddy->height())));
131
132     popup->setFocus();
133     popup->show();
134 }
135
136 void AutoComplete::doneCompletion() {
137     timer->stop();
138     popup->hide();
139     buddy->setFocus();
140     QListWidgetItem *item = popup->currentItem();
141     if (item) {
142         buddy->setText(item->text());
143         emit suggestionAccepted(item->text());
144     }
145 }
146
147 void AutoComplete::preventSuggest() {
148     // qDebug() << "preventSuggest";
149     timer->stop();
150     enabled = false;
151     popup->hide();
152 }
153
154 void AutoComplete::enableSuggest() {
155     // qDebug() << "enableSuggest";
156     enabled = true;
157 }
158
159 void AutoComplete::setSuggester(Suggester* suggester) {
160     if (this->suggester) this->suggester->disconnect();
161     this->suggester = suggester;
162     connect(suggester, SIGNAL(ready(QStringList)), SLOT(suggestionsReady(QStringList)));
163 }
164
165 void AutoComplete::autoSuggest() {
166     if (!enabled) return;
167     if (!buddy->hasFocus()) return;
168
169     QString query = editor->text();
170     originalText = query;
171     // qDebug() << "originalText" << originalText;
172     if (query.isEmpty()) {
173         popup->hide();
174         buddy->setFocus();
175         return;
176     }
177
178     if (suggester)
179         suggester->suggest(query);
180 }
181
182 void AutoComplete::suggestionsReady(QStringList suggestions) {
183     if (!enabled) return;
184     showCompletion(suggestions);
185 }
186
187 void AutoComplete::currentItemChanged(QListWidgetItem *current) {
188     if (current) {
189         // qDebug() << "current" << current->text();
190         current->setSelected(true);
191         buddy->setText(current->text());
192         editor->setSelection(originalText.length(), editor->text().length());
193     }
194 }