Power save mode review and iteration.
[situare] / src / gps / gpspositionprivateliblocation.cpp
1 /*
2    Situare - A location system for Facebook
3    Copyright (C) 2010  Ixonos Plc. Authors:
4
5        Jussi Laitinen - jussi.laitinen@ixonos.com
6
7    Situare is free software; you can redistribute it and/or
8    modify it under the terms of the GNU General Public License
9    version 2 as published by the Free Software Foundation.
10
11    Situare is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with Situare; if not, write to the Free Software
18    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
19    USA.
20 */
21
22 #include <QFile>
23 #include <QDir>
24 #include <QApplication>
25 #include <QDebug>
26 #include <QTimer>
27
28 #include "common.h"
29 #include "gpscommon.h"
30 #include "gpsposition.h"
31 #include "gpspositionprivateliblocation.h"
32 #include "liblocationwrapper.h"
33
34 const int POWER_SAVE_START_DELAY_MS = 1000*10;
35
36 GPSPositionPrivate::GPSPositionPrivate(QObject *parent)
37     : QObject(parent),
38       m_liblocationWrapper(0),
39       m_initialized(false),
40       m_powerSave(false),
41       m_running(false),
42       m_updateInterval(DEFAULT_UPDATE_INTERVAL)
43 {
44     qDebug() << __PRETTY_FUNCTION__;
45
46     m_parent = static_cast<GPSPosition*>(parent);
47
48     m_delayedPowerSaveTimer = new QTimer(this);
49     m_delayedPowerSaveTimer->setInterval(POWER_SAVE_START_DELAY_MS);
50     connect(m_delayedPowerSaveTimer, SIGNAL(timeout()),
51             this, SLOT(delayedPowerSaveStart()));
52 }
53
54 void GPSPositionPrivate::delayedPowerSaveStart()
55 {
56     qDebug() << __PRETTY_FUNCTION__;
57
58     m_powerSave = true;
59     m_delayedPowerSaveTimer->stop();
60     m_liblocationWrapper->stopUpdates();
61 }
62
63 bool GPSPositionPrivate::isInitialized()
64 {
65     qDebug() << __PRETTY_FUNCTION__;
66
67     return m_initialized;
68 }
69
70 void GPSPositionPrivate::setMode(GPSPosition::Mode mode, const QString &filePath)
71 {
72     qDebug() << __PRETTY_FUNCTION__;
73
74     Q_UNUSED(filePath);
75
76     if (m_liblocationWrapper) {
77         disconnect(m_liblocationWrapper, 0, 0, 0);
78         delete m_liblocationWrapper;
79     }
80
81     if (mode == GPSPosition::Default) {
82         m_liblocationWrapper = new LiblocationWrapper(this);
83
84         if (!m_liblocationWrapper) {     
85             m_initialized = false;
86             emit m_parent->error(SituareError::GPS_INITIALIZATION_FAILED);
87             return;
88         }
89     }
90
91     if (m_liblocationWrapper) {
92         m_initialized = true;
93         m_liblocationWrapper->init(m_updateInterval);
94
95         connect(m_liblocationWrapper, SIGNAL(locationChanged(const GeoPositionInfo &)),
96                 this, SLOT(positionUpdated(const GeoPositionInfo &)));
97         connect(m_liblocationWrapper, SIGNAL(errorMessage(const QString &)),
98                 this, SLOT(locationError(const QString &)));
99     }
100 }
101
102 void GPSPositionPrivate::setPowerSave(bool enabled)
103 {
104     qDebug() << __PRETTY_FUNCTION__;
105
106     if (isRunning()) {
107         if (enabled) {
108             m_delayedPowerSaveTimer->start();
109         } else {
110             m_powerSave = false;
111             m_delayedPowerSaveTimer->stop();
112             m_liblocationWrapper->startUpdates();
113         }
114     }
115     else {
116         m_powerSave = false;
117     }
118 }
119
120 void GPSPositionPrivate::start()
121 {
122     qDebug() << __PRETTY_FUNCTION__;
123
124     if (m_initialized && !isRunning()) {
125         m_liblocationWrapper->startUpdates();
126         m_running = true;
127     }
128 }
129
130 void GPSPositionPrivate::stop()
131 {
132     qDebug() << __PRETTY_FUNCTION__;
133
134     if (m_initialized && isRunning()) {
135         m_liblocationWrapper->stopUpdates();
136         m_running = false;
137     }
138 }
139
140 bool GPSPositionPrivate::isRunning()
141 {
142     qDebug() << __PRETTY_FUNCTION__;
143
144     return m_running;
145 }
146
147 QPointF GPSPositionPrivate::lastPosition()
148 {
149     qDebug() << __PRETTY_FUNCTION__;
150
151     GeoPositionInfo positionInfo =  m_liblocationWrapper->lastKnownPosition();
152
153     return QPointF(positionInfo.coordinate().longitude(), positionInfo.coordinate().latitude());
154 }
155
156 void GPSPositionPrivate::requestLastPosition()
157 {
158     qDebug() << __PRETTY_FUNCTION__;
159
160     GeoPositionInfo positionInfo = m_liblocationWrapper->lastKnownPosition();
161
162     if (positionInfo.isValid()) {
163         GeoCoordinate coordinate = positionInfo.coordinate();
164         emit m_parent->position(QPointF(coordinate.longitude(), coordinate.latitude()),
165                       accuracy(positionInfo));
166     }
167 }
168
169 void GPSPositionPrivate::requestUpdate()
170 {
171     qDebug() << __PRETTY_FUNCTION__;
172
173     if (m_powerSave)
174         m_liblocationWrapper->startUpdates();
175     else
176         requestLastPosition();
177 }
178
179 void GPSPositionPrivate::positionUpdated(const GeoPositionInfo &positionInfo)
180 {
181     qDebug() << __PRETTY_FUNCTION__;
182
183     if (positionInfo.coordinate().isValid()) {
184         GeoCoordinate coordinate = positionInfo.coordinate();
185         emit m_parent->position(QPointF(coordinate.longitude(), coordinate.latitude()),
186                       accuracy(positionInfo));
187     }
188
189     if (m_powerSave)
190         m_liblocationWrapper->stopUpdates();
191 }
192
193 void GPSPositionPrivate::locationError(const QString &errorMessage)
194 {
195     qDebug() << __PRETTY_FUNCTION__;
196
197     Q_UNUSED(errorMessage);
198
199     emit m_parent->error(SituareError::GPS_INITIALIZATION_FAILED);
200 }
201
202 void GPSPositionPrivate::setUpdateInterval(int interval)
203 {
204     qDebug() << __PRETTY_FUNCTION__;
205
206     if (m_updateInterval != interval) {
207         m_updateInterval = interval;
208         m_liblocationWrapper->init(m_updateInterval);
209     }
210 }
211
212 qreal GPSPositionPrivate::accuracy(const GeoPositionInfo &positionInfo)
213 {
214     qDebug() << __PRETTY_FUNCTION__;
215
216     if (positionInfo.isAccurate())
217         return positionInfo.accuracy();
218     else
219         return GPS_ACCURACY_UNDEFINED;
220 }