Implemented username saving to settings and loading. Saved username
[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 "common.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     connect(this, SIGNAL(reverseGeoReady(QString)),
57             m_mapViewScreen, SIGNAL(reverseGeoReady(QString)));
58     connect(m_mapViewScreen, SIGNAL(statusUpdate(QString,bool)),
59             this, SIGNAL(statusUpdate(QString,bool)));
60
61     connect(this, SIGNAL(userLocationReady(User*)),
62             m_mapViewScreen, SIGNAL(userLocationReady(User*)));
63     connect(this, SIGNAL(friendsLocationsReady(QList<User*>&)),
64             m_mapViewScreen, SIGNAL(friendsLocationsReady(QList<User*>&)));
65
66         connect(this, SIGNAL(autoCentering(bool)),
67             m_mapViewScreen, SIGNAL(enableAutoCentering(bool)));
68     connect(this, SIGNAL(positionReceived(QPointF, qreal)),
69             m_mapViewScreen, SIGNAL(positionReceived(QPointF, qreal)));
70     connect(m_mapViewScreen, SIGNAL(mapLocationChanged()),
71             this, SLOT(mapLocationChanged()));
72
73     connect(this, SIGNAL(zoomInKeyPressed()),
74             m_mapViewScreen, SIGNAL(zoomInKeyPressed()));
75     connect(this, SIGNAL(zoomOutKeyPressed()),
76             m_mapViewScreen, SIGNAL(zoomOutKeyPressed()));
77
78     connect(this, SIGNAL(requestOwnLocation()),
79             m_mapViewScreen, SIGNAL(requestOwnLocation()));
80     connect(m_mapViewScreen, SIGNAL(ownLocation(QPointF)),
81             this, SIGNAL(ownLocation(QPointF)));
82
83     connect(m_mapViewScreen, SIGNAL(requestReverseGeo()),
84             this, SIGNAL(requestReverseGeo()));
85
86     connect(m_mapViewScreen, SIGNAL(refreshUserData()),
87             this, SIGNAL(refreshUserData()));
88
89     this->toggleProgressIndicator(true);
90
91     grabZoomKeys(true);
92 }
93
94 MainWindow::~MainWindow()
95 {
96     qDebug() << __PRETTY_FUNCTION__;
97
98     grabZoomKeys(false);
99
100     if(m_webView)
101         delete m_webView;
102 }
103
104 void MainWindow::toggleProgressIndicator(bool value)
105 {
106     qDebug() << __PRETTY_FUNCTION__;
107 #ifdef Q_WS_MAEMO_5
108     setAttribute(Qt::WA_Maemo5ShowProgressIndicator, value);
109 #else
110     Q_UNUSED(value);
111 #endif // Q_WS_MAEMO_5
112 }
113
114 void MainWindow::createMenus()
115 {
116     qDebug() << __PRETTY_FUNCTION__;
117
118     m_toSettingsAct = new QAction(tr("Settings"), this);
119     m_toSettingsAct->setObjectName(tr("Settings"));
120     connect(m_toSettingsAct, SIGNAL(triggered()),
121         this, SLOT(openSettingsDialog()));
122     m_gpsToggleAct = new QAction(tr("GPS"), this);
123     m_gpsToggleAct->setCheckable(true);
124     m_gpsToggleAct->setChecked(true);
125     connect(m_gpsToggleAct, SIGNAL(toggled(bool)),
126         this, SLOT(gpsToggled(bool)));
127     connect(m_gpsToggleAct, SIGNAL(toggled(bool)),
128             m_mapViewScreen, SLOT(setOwnLocationCrosshairVisibility(bool)));
129     m_autoCenteringAct = new QAction(tr("Auto centering"), this);
130     m_autoCenteringAct->setCheckable(true);
131     m_autoCenteringAct->setChecked(true);
132     connect(m_autoCenteringAct, SIGNAL(toggled(bool)),
133         this, SLOT(autoCenteringToggled(bool))); 
134     connect(this, SIGNAL(enableGPS(bool)),
135             m_mapViewScreen, SIGNAL(gpsEnabled(bool)));
136
137     m_viewMenu = menuBar()->addMenu(tr("Main"));
138
139     m_viewMenu->addAction(m_toSettingsAct);
140     m_viewMenu->addAction(m_gpsToggleAct);
141     m_viewMenu->addAction(m_autoCenteringAct);
142     m_viewMenu->setObjectName(tr("Menu"));
143 }
144
145 void MainWindow::openSettingsDialog()
146 {
147     qDebug() << __PRETTY_FUNCTION__;
148     SettingsDialog *dialog = new SettingsDialog(this);
149     dialog->show();
150 }
151
152 void MainWindow::gpsToggled(bool checked)
153 {
154     qDebug() << __PRETTY_FUNCTION__;
155
156     if (checked)
157         emit enableGPS(true);
158     else
159         emit enableGPS(false);
160 }
161
162 void MainWindow::setGPSButton(bool enabled)
163 {
164     qDebug() << __PRETTY_FUNCTION__;
165
166     if (enabled) {
167         showMaemoInformationBox(tr("GPS enabled"));
168         m_gpsToggleAct->setChecked(true);
169         m_autoCenteringAct->setVisible(true);
170     }
171     else {
172         showMaemoInformationBox(tr("GPS disabled"));
173         m_gpsToggleAct->setChecked(false);
174         m_autoCenteringAct->setVisible(false);
175     }
176 }
177
178 void MainWindow::setAutoCenteringButton(bool enabled)
179 {
180     if (enabled) {
181         showMaemoInformationBox(tr("Auto centering enabled"));
182         m_autoCenteringAct->setChecked(true);
183     }
184     else {
185         showMaemoInformationBox(tr("Auto centering disabled"));
186         m_autoCenteringAct->setChecked(false);
187     }
188 }
189
190 void MainWindow::gpsTimeout()
191 {
192     qDebug() << __PRETTY_FUNCTION__;
193
194     showMaemoInformationBox(tr("GPS timeout"));
195 }
196
197 void MainWindow::gpsError(const QString &message)
198 {
199     qDebug() << __PRETTY_FUNCTION__;
200
201     showMaemoInformationBox(message);
202 }
203
204 void MainWindow::mapLocationChanged()
205 {
206     qDebug() << __PRETTY_FUNCTION__;
207
208     emit enableAutoCentering(false);
209 }
210
211 void MainWindow::autoCenteringToggled(bool checked)
212 {
213     qDebug() << __PRETTY_FUNCTION__ << checked;
214
215     if (checked)
216         emit enableAutoCentering(true);
217     else
218         emit enableAutoCentering(false);
219 }
220
221 void MainWindow::autoCenteringEnabled(bool enabled)
222 {
223     qDebug() << __PRETTY_FUNCTION__ << enabled;
224
225     emit autoCentering(enabled);
226 }
227
228 void MainWindow::showMaemoInformationBox(const QString &message)
229 {
230     qDebug() << __PRETTY_FUNCTION__;
231
232 #ifdef Q_WS_MAEMO_5
233     QMaemo5InformationBox::information(this, message, QMaemo5InformationBox::DefaultTimeout);
234 #else
235     Q_UNUSED(message);
236 #endif
237 }
238
239 void MainWindow::startLoginProcess(const QUrl &url)
240 {
241     qDebug() << __PRETTY_FUNCTION__;
242
243     m_loginUrl = url;
244     m_webView = new QWebView;
245     m_loginDialog = new LoginDialog(this);
246
247     connect(m_webView, SIGNAL(urlChanged(const QUrl &)),
248             this, SIGNAL(updateCredentials(QUrl)));
249     connect(m_webView, SIGNAL(loadFinished(bool)),
250             this, SLOT(loadDone(bool)));
251
252     connect(m_loginDialog, SIGNAL(loginDialogDone(QString,QString)),
253             this, SLOT(loginDialogDone(QString,QString)));
254
255     m_webView->hide();
256
257     emit fetchUsernameFromSettings();
258
259     if(!m_email.isEmpty()) {
260         m_loginDialog->setEmailField(m_email);
261     }
262
263     if(m_loginDialog->exec() != QDialog::Accepted) {
264         // if login dialog was canceled we need to stop processing webview
265         // stop and disconnect m_webView;
266         m_webView->stop();
267         disconnect(m_webView, SIGNAL(loadFinished(bool)),
268                    this, SLOT(loadDone(bool)));
269         disconnect(m_webView, SIGNAL(urlChanged(const QUrl &)),
270                    this, SLOT(updateCredentials(const QUrl &)));
271
272         emit cancelLoginProcess();
273     }
274     else {
275         m_webView->load(m_loginUrl);
276         toggleProgressIndicator(true);
277         m_refresh = true;
278     }
279 }
280
281 void MainWindow::loginDialogDone(const QString &email, const QString &password)
282 {
283     qDebug() << __PRETTY_FUNCTION__;
284
285     m_email = email;
286     m_password = password;
287 }
288
289 void MainWindow::loginFailed()
290 {
291     qDebug() << __PRETTY_FUNCTION__;
292
293     m_email.clear();
294     m_password.clear();
295
296     toggleProgressIndicator(false);
297
298 #ifdef Q_WS_MAEMO_5
299     QMaemo5InformationBox::information(this, tr("Invalid E-mail address or password"),
300                                        QMaemo5InformationBox::NoTimeout);
301
302 #endif // Q_WS_MAEMO_5
303
304     if(!m_email.isEmpty()) {
305         m_loginDialog->setEmailField(m_email);
306     }
307
308     if(m_loginDialog->exec() != QDialog::Accepted) {
309         // if login dialog was canceled we need to stop processing webview
310         // stop and disconnect m_webView;
311         m_webView->stop();
312         disconnect(m_webView, SIGNAL(loadFinished(bool)),
313                    this, SLOT(loadDone(bool)));
314         disconnect(m_webView, SIGNAL(urlChanged(const QUrl &)),
315                    this, SLOT(updateCredentials(const QUrl &)));
316
317         emit cancelLoginProcess();
318     }
319     else {
320         // re-load login page for webview
321         toggleProgressIndicator(true);
322         m_webView->load(m_loginUrl);
323     }
324 }
325
326 void MainWindow::loadDone(bool done)
327 {
328     qDebug() << __PRETTY_FUNCTION__;
329
330     // for the first time the login page is opened, we need to refresh it to get cookies working
331     if(m_refresh) {
332         m_webView->reload();
333         m_refresh = false;
334     }
335
336     if (done)
337     {
338         QWebFrame* frame = m_webView->page()->currentFrame();
339         if (frame!=NULL)
340         {
341             // set email box
342             QWebElementCollection emailCollection = frame->findAllElements("input[name=email]");
343
344             foreach (QWebElement element, emailCollection) {
345                 element.setAttribute("value", m_email.toAscii());
346             }
347             // set password box
348             QWebElementCollection passwordCollection = frame->findAllElements("input[name=pass]");
349             foreach (QWebElement element, passwordCollection) {
350                 element.setAttribute("value", m_password.toAscii());
351             }
352             // find connect button
353             QWebElementCollection buttonCollection = frame->findAllElements("input[name=login]");
354             foreach (QWebElement element, buttonCollection)
355             {
356                 QPoint pos(element.geometry().center());
357
358                 // send a mouse click event to the web page
359                 QMouseEvent event0(QEvent::MouseButtonPress, pos, Qt::LeftButton, Qt::LeftButton,
360                                    Qt::NoModifier);
361                 QApplication::sendEvent(m_webView->page(), &event0);
362                 QMouseEvent event1(QEvent::MouseButtonRelease, pos, Qt::LeftButton, Qt::LeftButton,
363                                    Qt::NoModifier);
364                 QApplication::sendEvent(m_webView->page(), &event1);
365             }
366         }
367     }
368 }
369
370 void MainWindow::grabZoomKeys(bool grab)
371 {
372     qDebug() << __PRETTY_FUNCTION__;
373 #ifdef Q_WS_MAEMO_5
374     // Can't grab keys unless we have a window id
375     if (!winId())
376         return;
377
378     unsigned long val = (grab) ? 1 : 0;
379     Atom atom = XInternAtom(QX11Info::display(), "_HILDON_ZOOM_KEY_ATOM", False);
380     if (!atom)
381         return;
382
383     XChangeProperty (QX11Info::display(),
384                      winId(),
385                      atom,
386                      XA_INTEGER,
387                      32,
388                      PropModeReplace,
389                      reinterpret_cast<unsigned char *>(&val),
390                      1);
391 #else
392     Q_UNUSED(grab);
393 #endif // Q_WS_MAEMO_5
394 }
395
396 void MainWindow::keyPressEvent(QKeyEvent* event)
397 {
398     qDebug() << __PRETTY_FUNCTION__;
399
400     switch (event->key()) {
401     case Qt::Key_F7:
402         event->accept();
403         emit zoomInKeyPressed();
404         break;
405
406     case Qt::Key_F8:
407         event->accept();
408         emit zoomOutKeyPressed();
409         break;
410     }
411     QWidget::keyPressEvent(event);
412 }
413
414 const QString MainWindow::username()
415 {
416     qDebug() << __PRETTY_FUNCTION__;
417     return m_email;
418 }
419
420 void MainWindow::setUsername(const QString &username)
421 {
422     qDebug() << __PRETTY_FUNCTION__;
423     m_email = username;
424 }