]> git.sur5r.net Git - minitube/blob - src/googlesuggest.cpp
Fixed message item not updating
[minitube] / src / googlesuggest.cpp
1 #include "googlesuggest.h"
2 #include "networkaccess.h"
3
4 #define GSUGGEST_URL "http://suggestqueries.google.com/complete/search?ds=yt&output=toolbar&hl=%1&q=%2"
5
6 namespace The {
7     NetworkAccess* http();
8 }
9
10 GSuggestCompletion::GSuggestCompletion(QLineEdit *parent): QObject(parent), editor(parent) {
11
12     popup = new QListWidget;
13     popup->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
14     popup->installEventFilter(this);
15     popup->setMouseTracking(true);
16
17     connect(popup, SIGNAL(itemClicked(QListWidgetItem*)),
18             SLOT(doneCompletion()));
19
20     connect(popup, SIGNAL(currentItemChanged(QListWidgetItem *, QListWidgetItem *)),
21             SLOT(currentItemChanged(QListWidgetItem *)));
22
23     // mouse hover
24     connect(popup, SIGNAL(itemEntered(QListWidgetItem*)),
25             SLOT(currentItemChanged(QListWidgetItem *)));
26
27     popup->setWindowFlags(Qt::Popup);
28     popup->setFocusPolicy(Qt::NoFocus);
29     popup->setFocusProxy(parent);
30
31     timer = new QTimer(this);
32     timer->setSingleShot(true);
33     timer->setInterval(100);
34     connect(timer, SIGNAL(timeout()), SLOT(autoSuggest()));
35     connect(editor, SIGNAL(textEdited(QString)), timer, SLOT(start()));
36
37 }
38
39 GSuggestCompletion::~GSuggestCompletion() {
40     delete popup;
41 }
42
43 bool GSuggestCompletion::eventFilter(QObject *obj, QEvent *ev) {
44     if (obj != popup)
45         return false;
46
47     if (ev->type() == QEvent::MouseButtonPress) {
48         popup->hide();
49         editor->setFocus();
50         editor->setText(originalText);
51         return true;
52     }
53
54     if (ev->type() == QEvent::KeyPress) {
55
56         bool consumed = false;
57
58         QKeyEvent *keyEvent = static_cast<QKeyEvent*>(ev);
59         int key = keyEvent->key();
60         switch (key) {
61         case Qt::Key_Enter:
62         case Qt::Key_Return:
63             if (popup->currentItem()) {
64                 doneCompletion();
65                 consumed = true;
66             } else {
67                 editor->setFocus();
68                 editor->event(ev);
69                 popup->hide();
70             }
71             break;
72
73         case Qt::Key_Escape:
74             editor->setFocus();
75             editor->setText(originalText);
76             popup->hide();
77             consumed = true;
78             break;
79
80         case Qt::Key_Up:
81         case Qt::Key_Down:
82         case Qt::Key_Home:
83         case Qt::Key_End:
84         case Qt::Key_PageUp:
85         case Qt::Key_PageDown:
86             break;
87
88         default:
89
90             editor->setFocus();
91             editor->event(ev);
92             popup->hide();
93             break;
94         }
95
96         return consumed;
97     }
98
99     return false;
100 }
101
102 void GSuggestCompletion::showCompletion(const QStringList &choices) {
103
104     if (choices.isEmpty())
105         return;
106
107     popup->setUpdatesEnabled(false);
108     popup->clear();
109     for (int i = 0; i < choices.count(); ++i) {
110         QListWidgetItem * item;
111         item = new QListWidgetItem(popup);
112         item->setText(choices[i]);
113     }
114     popup->setCurrentItem(0);
115     popup->adjustSize();
116     popup->setUpdatesEnabled(true);
117
118     int h = popup->sizeHintForRow(0) * choices.count() + 4;
119     popup->resize(popup->width(), h);
120
121     popup->move(editor->mapToGlobal(QPoint(0, editor->height()+4)));
122     popup->setFocus();
123     popup->show();
124 }
125
126 void GSuggestCompletion::doneCompletion() {
127     timer->stop();
128     popup->hide();
129     editor->setFocus();
130     QListWidgetItem *item = popup->currentItem();
131     if (item) {
132         editor->setText(item->text());
133         QKeyEvent *e;
134         e = new QKeyEvent(QEvent::KeyPress, Qt::Key_Enter, Qt::NoModifier);
135         QApplication::postEvent(editor, e);
136         e = new QKeyEvent(QEvent::KeyRelease, Qt::Key_Enter, Qt::NoModifier);
137         QApplication::postEvent(editor, e);
138     }
139 }
140
141 void GSuggestCompletion::preventSuggest() {
142     timer->stop();
143 }
144
145 void GSuggestCompletion::autoSuggest() {
146     QString query = editor->text();
147     originalText = query;
148     qDebug() << "originalText" << originalText;
149     if (query.isEmpty()) return;
150
151     QString locale = QLocale::system().name().replace("_", "-");
152     // case for system locales such as "C"
153     if (locale.length() < 2) {
154         locale = "en-US";
155     }
156
157     QString url = QString(GSUGGEST_URL).arg(locale, query);
158
159     QObject *reply = The::http()->get(url);
160     connect(reply, SIGNAL(data(QByteArray)), SLOT(handleNetworkData(QByteArray)));
161 }
162
163 void GSuggestCompletion::handleNetworkData(QByteArray response) {
164
165     QStringList choices;
166
167     QXmlStreamReader xml(response);
168     while (!xml.atEnd()) {
169         xml.readNext();
170         if (xml.tokenType() == QXmlStreamReader::StartElement)
171             if (xml.name() == "suggestion") {
172             QStringRef str = xml.attributes().value("data");
173             choices << str.toString();
174         }
175     }
176
177     showCompletion(choices);
178
179 }
180
181 void GSuggestCompletion::currentItemChanged(QListWidgetItem *current) {
182     if (current) {
183         qDebug() << "current" << current->text();
184         current->setSelected(true);
185         editor->setText(current->text());
186         editor->setSelection(originalText.length(), editor->text().length());
187     }
188 }