Small fix on facebookauthentication's credential handling method,
[situare] / src / ui / mainwindow.cpp
1 /*
2    Situare - A location system for Facebook
3    Copyright (C) 2010  Ixonos Plc. Authors:
4
5       Henri Lampela - henri.lampela@ixonos.com
6       Kaj Wallin - kaj.wallin@ixonos.com
7       Jussi Laitinen jussi.laitinen@ixonos.com
8
9    Situare is free software; you can redistribute it and/or
10    modify it under the terms of the GNU General Public License
11    version 2 as published by the Free Software Foundation.
12
13    Situare is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with Situare; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
21    USA.
22 */
23
24 #include <QtGui>
25
26 #ifdef Q_WS_MAEMO_5
27 #include <QtMaemo5/QMaemo5InformationBox>
28 #endif // Q_WS_MAEMO_5
29
30 #include "mainwindow.h"
31 #include "mapviewscreen.h"
32 #include "settingsdialog.h"
33 #include "facebookservice/facebookauthentication.h"
34 #include "situarecommon.h"
35
36 #include <QtGui/QX11Info>
37 #include <X11/Xlib.h>
38 #include <X11/Xatom.h>
39
40 MainWindow::MainWindow(QWidget *parent)
41     : QMainWindow(parent),
42     m_email(),
43     m_loginUrl(),
44     m_password(),
45     m_refresh(0),
46     m_webView(0)
47 {
48     qDebug() << __PRETTY_FUNCTION__;
49
50     m_mapViewScreen = new MapViewScreen(this);
51     setCentralWidget(m_mapViewScreen);
52     createMenus();
53     setWindowTitle(tr("Situare"));
54         show();
55
56     m_locationDialog = new UpdateLocationDialog(this);
57
58     connect(this, SIGNAL(reverseGeoReady(QString)),
59             m_locationDialog, SLOT(setAddress(QString)));
60     connect(m_locationDialog, SIGNAL(statusUpdate(QString,bool)), this,
61             SIGNAL(statusUpdate(QString,bool)));
62
63     connect(this, SIGNAL(userLocationReady(User*)),
64             m_mapViewScreen, SIGNAL(userLocationReady(User*)));
65     connect(this, SIGNAL(friendsLocationsReady(QList<User*>&)),
66             m_mapViewScreen, SIGNAL(friendsLocationsReady(QList<User*>&)));
67
68         connect(this, SIGNAL(autoCentering(bool)),
69             m_mapViewScreen, SLOT(enableAutoCentering(bool)));
70     connect(this, SIGNAL(positionReceived(QPointF, qreal)),
71             m_mapViewScreen, SLOT(positionReceived(QPointF, qreal)));
72     connect(m_mapViewScreen, SIGNAL(mapLocationChanged()), this, SLOT(mapLocationChanged()));
73
74     connect(this, SIGNAL(zoomInKeyPressed()),
75             m_mapViewScreen, SIGNAL(zoomInKeyPressed()));
76     connect(this, SIGNAL(zoomOutKeyPressed()),
77             m_mapViewScreen, SIGNAL(zoomOutKeyPressed()));
78
79     this->toggleProgressIndicator(true);
80
81     grabZoomKeys(true);
82 }
83
84 MainWindow::~MainWindow()
85 {
86     qDebug() << __PRETTY_FUNCTION__;
87
88     grabZoomKeys(false);
89
90     if(m_webView)
91         delete m_webView;
92 }
93
94 void MainWindow::toggleProgressIndicator(bool value)
95 {
96     qDebug() << __PRETTY_FUNCTION__;
97 #ifdef Q_WS_MAEMO_5
98     setAttribute(Qt::WA_Maemo5ShowProgressIndicator, value);
99 #else
100     Q_UNUSED(value);
101 #endif // Q_WS_MAEMO_5
102 }
103
104 void MainWindow::createMenus()
105 {
106     qDebug() << __PRETTY_FUNCTION__;
107
108     m_toSettingsAct = new QAction(tr("Settings"), this);
109     m_toSettingsAct->setObjectName(tr("Settings"));
110     connect(m_toSettingsAct, SIGNAL(triggered()), this, SLOT(openSettingsDialog()));
111         m_gpsToggleAct = new QAction(tr("GPS"), this);
112     m_gpsToggleAct->setCheckable(true);
113     m_gpsToggleAct->setChecked(true);
114     connect(m_gpsToggleAct, SIGNAL(toggled(bool)), this, SLOT(gpsToggled(bool)));
115     m_autoCenteringAct = new QAction(tr("Auto centering"), this);
116     m_autoCenteringAct->setCheckable(true);
117     m_autoCenteringAct->setChecked(true);
118     connect(m_autoCenteringAct, SIGNAL(toggled(bool)), this, SLOT(autoCenteringToggled(bool)));    
119
120     m_viewMenu = menuBar()->addMenu(tr("Main"));
121
122     m_viewMenu->addAction(m_toSettingsAct);
123         m_viewMenu->addAction(m_gpsToggleAct);
124     m_viewMenu->addAction(m_autoCenteringAct);
125     m_viewMenu->setObjectName(tr("Menu"));
126 }
127
128 void MainWindow::openLocationUpdateDialog()
129 {
130     qDebug() << __PRETTY_FUNCTION__;
131
132     emit requestReverseGeo();
133     m_locationDialog->exec();
134 }
135
136 void MainWindow::openSettingsDialog()
137 {
138     qDebug() << __PRETTY_FUNCTION__;
139     SettingsDialog *dialog = new SettingsDialog(this);
140     dialog->show();
141 }
142
143 void MainWindow::gpsToggled(bool checked)
144 {
145     qDebug() << __PRETTY_FUNCTION__;
146
147     if (checked)
148         emit enableGPS(true);
149     else
150         emit enableGPS(false);
151 }
152
153 void MainWindow::setGPSButton(bool enabled)
154 {
155     qDebug() << __PRETTY_FUNCTION__;
156
157     if (enabled) {
158         showMaemoInformationBox(tr("GPS enabled"));
159         m_gpsToggleAct->setChecked(true);
160         m_autoCenteringAct->setVisible(true);
161     }
162     else {
163         showMaemoInformationBox(tr("GPS disabled"));
164         m_gpsToggleAct->setChecked(false);
165         m_autoCenteringAct->setVisible(false);
166     }
167 }
168
169 void MainWindow::setAutoCenteringButton(bool enabled)
170 {
171     if (enabled) {
172         showMaemoInformationBox(tr("Auto centering enabled"));
173         m_autoCenteringAct->setChecked(true);
174     }
175     else {
176         showMaemoInformationBox(tr("Auto centering disabled"));
177         m_autoCenteringAct->setChecked(false);
178     }
179 }
180
181 void MainWindow::gpsTimeout()
182 {
183     qDebug() << __PRETTY_FUNCTION__;
184
185     showMaemoInformationBox(tr("GPS timeout"));
186 }
187
188 void MainWindow::gpsError(const QString &message)
189 {
190     qDebug() << __PRETTY_FUNCTION__;
191
192     showMaemoInformationBox(message);
193 }
194
195 void MainWindow::mapLocationChanged()
196 {
197     qDebug() << __PRETTY_FUNCTION__;
198
199     emit enableAutoCentering(false);
200 }
201
202 void MainWindow::autoCenteringToggled(bool checked)
203 {
204     qDebug() << __PRETTY_FUNCTION__ << checked;
205
206     if (checked)
207         emit enableAutoCentering(true);
208     else
209         emit enableAutoCentering(false);
210 }
211
212 void MainWindow::autoCenteringEnabled(bool enabled)
213 {
214     qDebug() << __PRETTY_FUNCTION__ << enabled;
215
216     emit autoCentering(enabled);
217 }
218
219 void MainWindow::showMaemoInformationBox(const QString &message)
220 {
221     qDebug() << __PRETTY_FUNCTION__;
222
223 #ifdef Q_WS_MAEMO_5
224     QMaemo5InformationBox::information(this, message, QMaemo5InformationBox::DefaultTimeout);
225 #else
226     Q_UNUSED(message);
227 #endif
228 }
229
230 void MainWindow::startLoginProcess(const QUrl &url)
231 {
232     qDebug() << __PRETTY_FUNCTION__;
233
234     m_loginUrl = url;
235     m_webView = new QWebView;
236     m_loginDialog = new LoginDialog(this);
237
238     connect(m_webView, SIGNAL(urlChanged(const QUrl &)),
239             this, SIGNAL(updateCredentials(QUrl)));
240     connect(m_webView, SIGNAL(loadFinished(bool)),
241             this, SLOT(loadDone(bool)));
242
243     connect(m_loginDialog, SIGNAL(loginDialogDone(QString,QString)),
244             this, SLOT(loginDialogDone(QString,QString)));
245
246     m_webView->hide();
247
248     if(m_loginDialog->exec() != QDialog::Accepted) {
249         // if login dialog was canceled we need to stop processing webview
250         // stop and disconnect m_webView;
251         m_webView->stop();
252         disconnect(m_webView, SIGNAL(loadFinished(bool)),
253                    this, SLOT(loadDone(bool)));
254         disconnect(m_webView, SIGNAL(urlChanged(const QUrl &)),
255                    this, SLOT(updateCredentials(const QUrl &)));
256
257         emit cancelLoginProcess();
258     }
259     else {
260         m_webView->load(m_loginUrl);
261         toggleProgressIndicator(true);
262         m_refresh = true;
263     }
264 }
265
266 void MainWindow::loginDialogDone(const QString &email, const QString &password)
267 {
268     qDebug() << __PRETTY_FUNCTION__;
269
270     m_email = email;
271     m_password = password;
272 }
273
274 void MainWindow::loginFailed()
275 {
276     qDebug() << __PRETTY_FUNCTION__;
277
278     m_email.clear();
279     m_password.clear();
280
281     toggleProgressIndicator(false);
282
283 #ifdef Q_WS_MAEMO_5
284     QMaemo5InformationBox::information(this, tr("Invalid E-mail address or password"),
285                                        QMaemo5InformationBox::NoTimeout);
286
287 #endif // Q_WS_MAEMO_5
288
289     if(m_loginDialog->exec() != QDialog::Accepted) {
290         // if login dialog was canceled we need to stop processing webview
291         // stop and disconnect m_webView;
292         m_webView->stop();
293         disconnect(m_webView, SIGNAL(loadFinished(bool)),
294                    this, SLOT(loadDone(bool)));
295         disconnect(m_webView, SIGNAL(urlChanged(const QUrl &)),
296                    this, SLOT(updateCredentials(const QUrl &)));
297
298         emit cancelLoginProcess();
299     }
300     else {
301         // re-load login page for webview
302         toggleProgressIndicator(true);
303         m_webView->load(m_loginUrl);
304     }
305 }
306
307 void MainWindow::loadDone(bool done)
308 {
309     qDebug() << __PRETTY_FUNCTION__;
310
311     // for the first time the login page is opened, we need to refresh it to get cookies working
312     if(m_refresh) {
313         m_webView->reload();
314         m_refresh = false;
315     }
316
317     if (done)
318     {
319         QWebFrame* frame = m_webView->page()->currentFrame();
320         if (frame!=NULL)
321         {
322             // set email box
323             QWebElementCollection emailCollection = frame->findAllElements("input[name=email]");
324
325             foreach (QWebElement element, emailCollection) {
326                 element.setAttribute("value", m_email.toAscii());
327             }
328             // set password box
329             QWebElementCollection passwordCollection = frame->findAllElements("input[name=pass]");
330             foreach (QWebElement element, passwordCollection) {
331                 element.setAttribute("value", m_password.toAscii());
332             }
333             // find connect button
334             QWebElementCollection buttonCollection = frame->findAllElements("input[name=login]");
335             foreach (QWebElement element, buttonCollection)
336             {
337                 QPoint pos(element.geometry().center());
338
339                 // send a mouse click event to the web page
340                 QMouseEvent event0(QEvent::MouseButtonPress, pos, Qt::LeftButton, Qt::LeftButton,
341                                    Qt::NoModifier);
342                 QApplication::sendEvent(m_webView->page(), &event0);
343                 QMouseEvent event1(QEvent::MouseButtonRelease, pos, Qt::LeftButton, Qt::LeftButton,
344                                    Qt::NoModifier);
345                 QApplication::sendEvent(m_webView->page(), &event1);
346             }
347         }
348     }
349 }
350
351 void MainWindow::grabZoomKeys(bool grab)
352 {
353     qDebug() << __PRETTY_FUNCTION__;
354 #ifdef Q_WS_MAEMO_5
355     // Can't grab keys unless we have a window id
356     if (!winId())
357         return;
358
359     unsigned long val = (grab) ? 1 : 0;
360     Atom atom = XInternAtom(QX11Info::display(), "_HILDON_ZOOM_KEY_ATOM", False);
361     if (!atom)
362         return;
363
364     XChangeProperty (QX11Info::display(),
365                      winId(),
366                      atom,
367                      XA_INTEGER,
368                      32,
369                      PropModeReplace,
370                      reinterpret_cast<unsigned char *>(&val),
371                      1);
372 #else
373     Q_UNUSED(grab);
374 #endif // Q_WS_MAEMO_5
375 }
376
377 void MainWindow::keyPressEvent(QKeyEvent* event)
378 {
379     qDebug() << __PRETTY_FUNCTION__;
380
381     switch (event->key()) {
382     case Qt::Key_F7:
383         event->accept();
384         emit zoomInKeyPressed();
385         break;
386
387     case Qt::Key_F8:
388         event->accept();
389         emit zoomOutKeyPressed();
390         break;
391     }
392     QWidget::keyPressEvent(event);
393 }