From 82e3bd235348a1c296558557838ec8094d3a77b9 Mon Sep 17 00:00:00 2001 From: Chris Adams Date: Mon, 17 Dec 2018 14:13:30 +1000 Subject: [PATCH] [systemsettings] Expose LocationMode. Contributes to JB#33753 Previously, the UI determined the location mode from the other values. This commit moves this logic into systemsettings directly. --- src/locationsettings.cpp | 186 +++++++++++++++++++++++++++++++++++---- src/locationsettings.h | 14 +++ src/locationsettings_p.h | 8 ++ 3 files changed, 192 insertions(+), 16 deletions(-) diff --git a/src/locationsettings.cpp b/src/locationsettings.cpp index e55b39f..7636dc9 100644 --- a/src/locationsettings.cpp +++ b/src/locationsettings.cpp @@ -35,8 +35,9 @@ #include #include -#include #include +#include +#include #include #include @@ -51,6 +52,7 @@ const QString LocationSettingsDir = QStringLiteral("/etc/location/"); const QString LocationSettingsFile = QStringLiteral("/etc/location/location.conf"); const QString LocationSettingsKeys = QStringLiteral( "enabled" ";" + "custom_mode" ";" "agps_providers" ";" "gps\\enabled" ";" "mls\\enabled" ";" @@ -74,6 +76,9 @@ LocationSettingsPrivate::LocationSettingsPrivate(LocationSettings::Mode mode, Lo , m_mlsEnabled(true) , m_mlsOnlineState(LocationSettings::OnlineAGpsAgreementNotAccepted) , m_hereState(LocationSettings::OnlineAGpsAgreementNotAccepted) + , m_locationMode(LocationSettings::CustomMode) + , m_settingLocationMode(true) + , m_settingMultipleSettings(false) , m_connMan(Q_NULLPTR) , m_gpsTech(Q_NULLPTR) , m_gpsTechInterface(mode == LocationSettings::AsynchronousMode @@ -83,6 +88,14 @@ LocationSettingsPrivate::LocationSettingsPrivate(LocationSettings::Mode mode, Lo "net.connman.Technology", QDBusConnection::systemBus())) { + connect(q, &LocationSettings::gpsEnabledChanged, + this, &LocationSettingsPrivate::recalculateLocationMode); + connect(q, &LocationSettings::mlsEnabledChanged, + this, &LocationSettingsPrivate::recalculateLocationMode); + connect(q, &LocationSettings::mlsOnlineStateChanged, + this, &LocationSettingsPrivate::recalculateLocationMode); + connect(q, &LocationSettings::hereStateChanged, + this, &LocationSettingsPrivate::recalculateLocationMode); connect(&m_watcher, SIGNAL(fileChanged(QString)), this, SLOT(readSettings())); connect(&m_watcher, SIGNAL(directoryChanged(QString)), this, SLOT(readSettings())); @@ -94,6 +107,8 @@ LocationSettingsPrivate::LocationSettingsPrivate(LocationSettings::Mode mode, Lo qWarning() << "Unable to follow location configuration file changes"; } + this->m_settingLocationMode = false; + if (m_gpsTechInterface) { QDBusConnection::systemBus().connect("net.connman", "/net/connman/technology/gps", @@ -146,6 +161,59 @@ void LocationSettingsPrivate::findGpsTech() emit q->gpsFlightModeChanged(); } +LocationSettings::LocationMode +LocationSettingsPrivate::calculateLocationMode() const +{ + if (m_gpsEnabled + && (!mlsAvailable() || + (m_mlsEnabled && m_mlsOnlineState == LocationSettings::OnlineAGpsEnabled)) + && (!hereAvailable() || m_hereState == LocationSettings::OnlineAGpsEnabled)) { + return LocationSettings::HighAccuracyMode; + } else if (!m_gpsEnabled + && (!mlsAvailable() || + (m_mlsEnabled && + (m_mlsOnlineState == LocationSettings::OnlineAGpsEnabled + || m_mlsOnlineState == LocationSettings::OnlineAGpsAgreementNotAccepted))) + && (!hereAvailable() || + (m_hereState == LocationSettings::OnlineAGpsEnabled + || m_hereState == LocationSettings::OnlineAGpsAgreementNotAccepted))) { + return LocationSettings::BatterySavingMode; + } else if (m_gpsEnabled + && (!mlsAvailable() || + (m_mlsEnabled && + (m_mlsOnlineState == LocationSettings::OnlineAGpsDisabled + || m_mlsOnlineState == LocationSettings::OnlineAGpsAgreementNotAccepted))) + && (!hereAvailable() || + (m_hereState == LocationSettings::OnlineAGpsDisabled + || m_hereState == LocationSettings::OnlineAGpsAgreementNotAccepted))) { + return LocationSettings::DeviceOnlyMode; + } else { + return LocationSettings::CustomMode; + } +} + +void LocationSettingsPrivate::recalculateLocationMode() +{ + if (!m_settingLocationMode && m_locationMode != LocationSettings::CustomMode) { + LocationSettings::LocationMode currentMode = calculateLocationMode(); + if (currentMode != m_locationMode) { + m_locationMode = currentMode; + emit q->locationModeChanged(); + } + } +} + +bool LocationSettingsPrivate::mlsAvailable() const +{ + return QFile::exists(QStringLiteral("/usr/libexec/geoclue-mlsdb")); +} + +bool LocationSettingsPrivate::hereAvailable() const +{ + return QFile::exists(QStringLiteral("/usr/libexec/geoclue-here")); +} + + LocationSettings::LocationSettings(QObject *parent) : QObject(parent) , d_ptr(new LocationSettingsPrivate(LocationSettings::AsynchronousMode, this)) @@ -269,7 +337,8 @@ void LocationSettings::setMlsOnlineState(LocationSettings::OnlineAGpsState state bool LocationSettings::mlsAvailable() const { - return QFile::exists(QStringLiteral("/usr/libexec/geoclue-mlsdb")); + Q_D(const LocationSettings); + return d->mlsAvailable(); } LocationSettings::OnlineAGpsState LocationSettings::hereState() const @@ -291,7 +360,75 @@ void LocationSettings::setHereState(LocationSettings::OnlineAGpsState state) bool LocationSettings::hereAvailable() const { - return QFile::exists(QStringLiteral("/usr/libexec/geoclue-here")); + Q_D(const LocationSettings); + return d->hereAvailable(); +} + +LocationSettings::LocationMode LocationSettings::locationMode() const +{ + Q_D(const LocationSettings); + return d->m_locationMode; +} + +void LocationSettings::setLocationMode(LocationMode locationMode) +{ + Q_D(LocationSettings); + + LocationSettings::LocationMode oldLocationMode = this->locationMode(); + if (oldLocationMode == locationMode) { + return; + } + + d->m_settingLocationMode = true; + d->m_settingMultipleSettings = true; + d->m_locationMode = locationMode; + + if (locationMode == HighAccuracyMode) { + setGpsEnabled(true); + if (mlsAvailable()) { + setMlsEnabled(true); + if (mlsOnlineState() != LocationSettings::OnlineAGpsAgreementNotAccepted) { + setMlsOnlineState(LocationSettings::OnlineAGpsEnabled); + } + } + if (hereAvailable()) { + if (hereState() != LocationSettings::OnlineAGpsAgreementNotAccepted) { + setHereState(LocationSettings::OnlineAGpsEnabled); + } + } + } else if (locationMode == BatterySavingMode) { + setGpsEnabled(false); + if (mlsAvailable()) { + setMlsEnabled(true); + if (mlsOnlineState() != LocationSettings::OnlineAGpsAgreementNotAccepted) { + setMlsOnlineState(LocationSettings::OnlineAGpsEnabled); + } + } + if (hereAvailable()) { + if (hereState() != LocationSettings::OnlineAGpsAgreementNotAccepted) { + setHereState(LocationSettings::OnlineAGpsEnabled); + } + } + } else if (locationMode == DeviceOnlyMode) { + setGpsEnabled(true); + if (mlsAvailable()) { + setMlsEnabled(true); + if (mlsOnlineState() != LocationSettings::OnlineAGpsAgreementNotAccepted) { + setMlsOnlineState(LocationSettings::OnlineAGpsDisabled); + } + } + if (hereAvailable()) { + if (hereState() != LocationSettings::OnlineAGpsAgreementNotAccepted) { + setHereState(LocationSettings::OnlineAGpsDisabled); + } + } + } + + d->m_settingMultipleSettings = false; + d->writeSettings(); + emit locationModeChanged(); + + d->m_settingLocationMode = false; } void LocationSettingsPrivate::readSettings() @@ -314,21 +451,22 @@ void LocationSettingsPrivate::readSettings() } // read the deprecated keys first, for compatibility purposes: - bool oldMlsEnabled = locationSettingsValues[9] != NULL && strcmp(locationSettingsValues[9], "true") == 0; - bool oldHereEnabled = locationSettingsValues[10] != NULL && strcmp(locationSettingsValues[10], "true") == 0; - bool oldHereAgreementAccepted = locationSettingsValues[11] != NULL && strcmp(locationSettingsValues[11], "true") == 0; + bool oldMlsEnabled = locationSettingsValues[10] != NULL && strcmp(locationSettingsValues[10], "true") == 0; + bool oldHereEnabled = locationSettingsValues[11] != NULL && strcmp(locationSettingsValues[11], "true") == 0; + bool oldHereAgreementAccepted = locationSettingsValues[12] != NULL && strcmp(locationSettingsValues[12], "true") == 0; // then read the new key values (overriding with deprecated values if needed): bool locationEnabled = locationSettingsValues[0] != NULL && strcmp(locationSettingsValues[0], "true") == 0; - // skip over the agps_providers value at [1] - bool gpsEnabled = locationSettingsValues[2] != NULL && strcmp(locationSettingsValues[2], "true") == 0; - bool mlsEnabled = oldMlsEnabled || (locationSettingsValues[3] != NULL && strcmp(locationSettingsValues[3], "true") == 0); - bool mlsAgreementAccepted = locationSettingsValues[4] != NULL && strcmp(locationSettingsValues[4], "true") == 0; - bool mlsOnlineEnabled = locationSettingsValues[5] != NULL && strcmp(locationSettingsValues[5], "true") == 0; - bool hereEnabled = oldHereEnabled || (locationSettingsValues[6] != NULL && strcmp(locationSettingsValues[6], "true") == 0); - bool hereAgreementAccepted = oldHereAgreementAccepted || (locationSettingsValues[7] != NULL && strcmp(locationSettingsValues[7], "true") == 0); - // skip over here\online_enabled value at [8] - - const int expectedCount = 12; // should equal: LocationSettingsKeys.split(';').count(); + bool customMode = locationSettingsValues[1] != NULL && strcmp(locationSettingsValues[1], "true") == 0; + // skip over the agps_providers value at [2] + bool gpsEnabled = locationSettingsValues[3] != NULL && strcmp(locationSettingsValues[3], "true") == 0; + bool mlsEnabled = oldMlsEnabled || (locationSettingsValues[4] != NULL && strcmp(locationSettingsValues[4], "true") == 0); + bool mlsAgreementAccepted = locationSettingsValues[5] != NULL && strcmp(locationSettingsValues[5], "true") == 0; + bool mlsOnlineEnabled = locationSettingsValues[6] != NULL && strcmp(locationSettingsValues[6], "true") == 0; + bool hereEnabled = oldHereEnabled || (locationSettingsValues[7] != NULL && strcmp(locationSettingsValues[7], "true") == 0); + bool hereAgreementAccepted = oldHereAgreementAccepted || (locationSettingsValues[8] != NULL && strcmp(locationSettingsValues[8], "true") == 0); + // skip over here\online_enabled value at [9] + + const int expectedCount = 13; // should equal: LocationSettingsKeys.split(';').count(); for (int i = 0; i < expectedCount; ++i) { if (locationSettingsValues[i] != NULL) { free(locationSettingsValues[i]); @@ -366,10 +504,24 @@ void LocationSettingsPrivate::readSettings() m_mlsOnlineState = mlsOnlineState; emit q->mlsOnlineStateChanged(); } + + if ((m_locationMode == LocationSettings::CustomMode) != customMode) { + if (customMode) { + m_locationMode = LocationSettings::CustomMode; + emit q->locationModeChanged(); + } else { + m_locationMode = calculateLocationMode(); + emit q->locationModeChanged(); + } + } } void LocationSettingsPrivate::writeSettings() { + if (m_settingMultipleSettings) { + return; // wait to write settings until all settings have been set. + } + // new file would be owned by creating process uid. we cannot allow this since the access is handled with group if (!QFile(LocationSettingsFile).exists()) { qWarning() << "Location settings configuration file does not exist. Refusing to create new."; @@ -389,6 +541,8 @@ void LocationSettingsPrivate::writeSettings() QString locationSettingsValues; locationSettingsValues.append(boolToString(m_locationEnabled)); locationSettingsValues.append(";"); + locationSettingsValues.append(boolToString(m_locationMode == LocationSettings::CustomMode)); + locationSettingsValues.append(";"); locationSettingsValues.append(agps_providers); locationSettingsValues.append(";"); locationSettingsValues.append(boolToString(m_gpsEnabled)); diff --git a/src/locationsettings.h b/src/locationsettings.h index 155078b..01cd4ed 100644 --- a/src/locationsettings.h +++ b/src/locationsettings.h @@ -56,7 +56,10 @@ class SYSTEMSETTINGS_EXPORT LocationSettings : public QObject Q_PROPERTY(OnlineAGpsState mlsOnlineState READ mlsOnlineState WRITE setMlsOnlineState NOTIFY mlsOnlineStateChanged) Q_PROPERTY(bool mlsAvailable READ mlsAvailable CONSTANT) + Q_PROPERTY(LocationMode locationMode READ locationMode WRITE setLocationMode NOTIFY locationModeChanged) + Q_ENUMS(OnlineAGpsState) + Q_ENUMS(LocationMode) public: enum Mode { @@ -93,6 +96,16 @@ class SYSTEMSETTINGS_EXPORT LocationSettings : public QObject void setMlsOnlineState(OnlineAGpsState state); bool mlsAvailable() const; + enum LocationMode { + HighAccuracyMode, + BatterySavingMode, + DeviceOnlyMode, + CustomMode + }; + + LocationMode locationMode() const; + void setLocationMode(LocationMode locationMode); + signals: void hereStateChanged(); void locationEnabledChanged(); @@ -100,6 +113,7 @@ class SYSTEMSETTINGS_EXPORT LocationSettings : public QObject void gpsFlightModeChanged(); void mlsEnabledChanged(); void mlsOnlineStateChanged(); + void locationModeChanged(); private: LocationSettingsPrivate *d_ptr; diff --git a/src/locationsettings_p.h b/src/locationsettings_p.h index 7adab66..a0e7c85 100644 --- a/src/locationsettings_p.h +++ b/src/locationsettings_p.h @@ -56,14 +56,21 @@ class LocationSettingsPrivate : public QObject LocationSettingsPrivate(LocationSettings::Mode mode, LocationSettings *settings); ~LocationSettingsPrivate(); + LocationSettings::LocationMode calculateLocationMode() const; void writeSettings(); + bool mlsAvailable() const; + bool hereAvailable() const; + QFileSystemWatcher m_watcher; bool m_locationEnabled; bool m_gpsEnabled; bool m_mlsEnabled; LocationSettings::OnlineAGpsState m_mlsOnlineState; LocationSettings::OnlineAGpsState m_hereState; + LocationSettings::LocationMode m_locationMode; + bool m_settingLocationMode; + bool m_settingMultipleSettings; NetworkManager *m_connMan; NetworkTechnology *m_gpsTech; QDBusInterface *m_gpsTechInterface; @@ -73,6 +80,7 @@ private slots: void readSettings(); void findGpsTech(); void gpsTechPropertyChanged(const QString &propertyName, const QVariant &value); + void recalculateLocationMode(); }; #endif // NEMO_SYSTEMSETTINGS_LOCATIONSETTINGS_P_H