Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qgeopositioninfosource_wasm.cpp
Go to the documentation of this file.
1// Copyright (C) 2024 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
7
8#include <QtCore/QDebug>
9#include <QtCore/QPermission>
10#include <QtCore/QCoreApplication>
11
12#include <emscripten/val.h>
13#include <emscripten/bind.h>
14
15
16// QGeoPositionInfoSource implemented using the Web Geolocation API
17
19
21
24{
25 // QGeoPositionInfoSourceWasm should not be constructed if
26 // geolocation support is missing.
27 Q_ASSERT(!geolocation().isUndefined());
28
30 m_instanceId = m_dispatcher->registerInfoSourceInstance(this);
31
32 successCallback = val::module_property("qtGeolocationPositionSuccess").call<val>("bind", val::undefined(), m_instanceId);
33 errorCallback = val::module_property("qtGeolocationPositionError").call<val>("bind", val::undefined(), m_instanceId);
34
35}
36
38{
39 return val::global("navigator")["geolocation"];
40}
41
47
49{
50 // If msec is 0 we send updates as data becomes available, otherwise we force msec to be equal
51 // to or larger than the minimum update interval.
52 if (msec != 0 && msec < minimumUpdateInterval())
54
55 QGeoPositionInfoSource::setUpdateInterval(msec);
56}
57
58void QGeoPositionInfoSourceWasm::startUpdates()
59{
60 if (m_updates_running) {
61 qDebug() << "startUpdates() is called, but an update is already running.";
62 return;
63 }
64
65 if (preferredPositioningMethods() == 0) {
66 m_lastError = QGeoPositionInfoSource::UnknownSourceError;
67 return;
68 }
69
70 m_updates_running = true;
71 m_lastError = QGeoPositionInfoSource::NoError;
72
73 val options = val::object();
74 options.set("maximumAge", 0);
75
76 if (preferredPositioningMethods() & PositioningMethod::SatellitePositioningMethods)
77 options.set("enableHighAccuracy", true);
78
79 m_handlerId = geolocation().call<val>("watchPosition", successCallback, errorCallback, options);
80}
81
83{
84 geolocation().call<void>("clearWatch", m_handlerId);
85 m_updates_running = false;
86}
87
89{
90 if (timeout < minimumUpdateInterval()) {
91 emit errorOccurred(UpdateTimeoutError);
92 return;
93 }
94
95 if (m_singleUpdatePending) {
96 qDebug() << "requestUpdate() called while a previous update is still pending. Ignoring.";
97 return;
98 }
99
100 m_singleUpdatePending = true;
101 m_lastError = QGeoPositionInfoSource::NoError;
102
103 val options = val::object();
104 options.set("maximumAge", 0); // maximum cache age: 0: don't use cache
105 options.set("timeout", timeout);
106
107 if (preferredPositioningMethods() & PositioningMethod::SatellitePositioningMethods)
108 options.set("enableHighAccuracy", true);
109
110 geolocation().call<void>("getCurrentPosition", successCallback, errorCallback, options);
111}
112
114{
115 return QGeoPositionInfoSource::AllPositioningMethods;
116}
117
119{
120 PositioningMethods previousPreferredPositioningMethods = preferredPositioningMethods();
121 QGeoPositionInfoSource::setPreferredPositioningMethods(methods);
122 if (previousPreferredPositioningMethods == preferredPositioningMethods())
123 return;
124
125 if (m_updates_running)
126 reconfigureRunningSystem();
127}
128
129
131{
132 return 1000;
133}
134
135QGeoPositionInfo QGeoPositionInfoSourceWasm::lastKnownPosition(bool fromSatellitePositioningMethodsOnly) const
136{
137 Q_UNUSED(fromSatellitePositioningMethodsOnly);
138 return m_lastKnownPosition;
139}
140
142{
143 qDebug() << "QGeoPositionInfoSourceWasm::error";
144 return m_lastError;
145}
146
148{
149 // Populate a QGeoPositionInfo from the native GeolocationPosition. Some
150 // attributes are optional and may be null.
151 QGeoPositionInfo info;
152 info.setTimestamp(QDateTime::fromMSecsSinceEpoch(position["timestamp"].as<double>()));
153
154 GeolocationCoordinates coords = position["coords"];
155 val latitude = coords["latitude"];
156 val longitude = coords["longitude"];
157 val altitude = coords["altitude"];
158 info.setCoordinate(altitude.isNull() ?
159 QGeoCoordinate(latitude.as<double>(), longitude.as<double>()) :
160 QGeoCoordinate(latitude.as<double>(), longitude.as<double>(), altitude.as<double>())
161 );
162
163 if (val speed = coords["speed"]; !speed.isNull())
164 info.setAttribute(QGeoPositionInfo::GroundSpeed, speed.as<double>());
165 if (val heading = coords["heading"]; !heading.isNull())
166 info.setAttribute(QGeoPositionInfo::Direction, heading.as<double>());
167
168 info.setAttribute(QGeoPositionInfo::HorizontalAccuracy, coords["accuracy"].as<double>());
169 if (val altitudeAccuracy = coords["altitudeAccuracy"]; !altitudeAccuracy.isNull())
170 info.setAttribute(QGeoPositionInfo::VerticalAccuracy, altitudeAccuracy.as<double>());
171
172 m_lastKnownPosition = info;
173 m_singleUpdatePending = false;
174
175 emit positionUpdated(info);
176}
177
179{
180 qDebug() << "geolocationError";
181 qDebug() << "Handler ID:" << m_handlerId.as<int>();
182
183 int code = error["code"].as<int>();
184 QString message = error["message"].as<QString>();
185
186 QGeoPositionInfoSource::Error qtError = QGeoPositionInfoSource::UnknownSourceError;
187
188 switch (code) {
189 case 1:
190 qtError = QGeoPositionInfoSource::AccessError; // -> PERMISSION_DENIED
191 break;
192 case 2:
193 qtError = QGeoPositionInfoSource::UnknownSourceError; // -> POSITION_UNAVAILABLE
194 break;
195 case 3:
196 qtError = QGeoPositionInfoSource::UpdateTimeoutError; // -> TIMEOUT
197 break;
198 }
199
200 qDebug() << "Message: " << message;
201
202 m_lastError = qtError;
203 m_singleUpdatePending = false;
204
205 emit errorOccurred(qtError);
206}
207
208void QGeoPositionInfoSourceWasm::reconfigureRunningSystem()
209{
210 if (!m_updates_running)
211 return;
212
214 startUpdates();
215}
216
217
218QT_END_NAMESPACE
219
220#include "moc_qgeopositioninfosource_wasm_p.cpp"
static QGeoPositionInfoDispatcherWasm * instance()
void geolocationError(GeolocationPositionError error)
Error error() const override
Returns the type of error that last occurred.
void setPreferredPositioningMethods(PositioningMethods methods) override
void requestUpdate(int timeout=0) override
PositioningMethods supportedPositioningMethods() const override
Returns the positioning methods available to this source.
void geolocationSuccess(GeolocationPosition position)
QGeoPositionInfo lastKnownPosition(bool fromSatellitePositioningMethodsOnly=false) const override
Returns an update containing the last known position, or a null update if none is available.
Combined button and popup list for selecting options.
QT_BEGIN_NAMESPACE typedef emscripten::val GeolocationCoordinates
emscripten::val Geolocation
emscripten::val GeolocationPositionError
emscripten::val GeolocationPosition