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