Skip to content

Commit

Permalink
Introduce the OCC::NetworkInformation class
Browse files Browse the repository at this point in the history
  • Loading branch information
erikjv committed Apr 16, 2024
1 parent f47adaf commit 6936f77
Show file tree
Hide file tree
Showing 11 changed files with 174 additions and 85 deletions.
1 change: 1 addition & 0 deletions src/gui/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ set(client_SRCS
ignorelisteditor.cpp
lockwatcher.cpp
logbrowser.cpp
networkinformation.cpp
networksettings.cpp
ocssharejob.cpp
openfilemanager.cpp
Expand Down
3 changes: 2 additions & 1 deletion src/gui/accountsettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "folderwizard/folderwizard.h"
#include "gui/accountmodalwidget.h"
#include "gui/models/models.h"
#include "gui/networkinformation.h"
#include "gui/qmlutils.h"
#include "gui/selectivesyncwidget.h"
#include "gui/spaces/spaceimageprovider.h"
Expand Down Expand Up @@ -407,7 +408,7 @@ void AccountSettings::slotEnableCurrentFolder(Folder *folder, bool terminate)

void AccountSettings::slotForceSyncCurrentFolder(Folder *folder)
{
if (Utility::internetConnectionIsMetered() && ConfigFile().pauseSyncWhenMetered()) {
if (NetworkInformation::instance()->isMetered() && ConfigFile().pauseSyncWhenMetered()) {
auto messageBox = new QMessageBox(QMessageBox::Question, tr("Internet connection is metered"),
tr("Synchronization is paused because the Internet connection is a metered connection"
"<p>Do you really want to force a Synchronization now?"),
Expand Down
67 changes: 32 additions & 35 deletions src/gui/accountstate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "libsync/creds/abstractcredentials.h"
#include "libsync/creds/httpcredentials.h"

#include "gui/networkinformation.h"
#include "gui/quotainfo.h"
#include "gui/settingsdialog.h"
#include "gui/spacemigration.h"
Expand All @@ -34,7 +35,6 @@
#include "theme.h"

#include <QFontMetrics>
#include <QNetworkInformation>
#include <QRandomGenerator>
#include <QSettings>
#include <QTimer>
Expand Down Expand Up @@ -113,42 +113,39 @@ AccountState::AccountState(AccountPtr account)
},
Qt::QueuedConnection);

#if QT_VERSION >= QT_VERSION_CHECK(6, 3, 0)
if (QNetworkInformation *qNetInfo = QNetworkInformation::instance()) {
connect(qNetInfo, &QNetworkInformation::reachabilityChanged, this, [this](QNetworkInformation::Reachability reachability) {
switch (reachability) {
case QNetworkInformation::Reachability::Online:
[[fallthrough]];
case QNetworkInformation::Reachability::Site:
[[fallthrough]];
case QNetworkInformation::Reachability::Unknown:
// the connection might not yet be established
QTimer::singleShot(0, this, [this] { checkConnectivity(false); });
break;
case QNetworkInformation::Reachability::Disconnected:
// explicitly set disconnected, this way a successful checkConnectivity call above will trigger a local discover
if (state() != State::SignedOut) {
setState(State::Disconnected);
}
[[fallthrough]];
case QNetworkInformation::Reachability::Local:
break;
connect(NetworkInformation::instance(), &NetworkInformation::reachabilityChanged, this, [this](NetworkInformation::Reachability reachability) {
switch (reachability) {
case NetworkInformation::Reachability::Online:
[[fallthrough]];
case NetworkInformation::Reachability::Site:
[[fallthrough]];
case NetworkInformation::Reachability::Unknown:
// the connection might not yet be established
QTimer::singleShot(0, this, [this] { checkConnectivity(false); });
break;
case NetworkInformation::Reachability::Disconnected:
// explicitly set disconnected, this way a successful checkConnectivity call above will trigger a local discover
if (state() != State::SignedOut) {
setState(State::Disconnected);
}
});
[[fallthrough]];
case NetworkInformation::Reachability::Local:
break;
}
});

connect(qNetInfo, &QNetworkInformation::isMeteredChanged, this, [this](bool isMetered) {
if (ConfigFile().pauseSyncWhenMetered()) {
if (state() == State::Connected && isMetered) {
qCInfo(lcAccountState) << "Network switched to a metered connection, setting account state to PausedDueToMetered";
setState(State::PausedDueToMetered);
} else if (state() == State::PausedDueToMetered && !isMetered) {
qCInfo(lcAccountState) << "Network switched to a NON-metered connection, setting account state to Connected";
setState(State::Connected);
}
connect(NetworkInformation::instance(), &NetworkInformation::isMeteredChanged, this, [this](bool isMetered) {
if (ConfigFile().pauseSyncWhenMetered()) {
if (state() == State::Connected && isMetered) {
qCInfo(lcAccountState) << "Network switched to a metered connection, setting account state to PausedDueToMetered";
setState(State::PausedDueToMetered);
} else if (state() == State::PausedDueToMetered && !isMetered) {
qCInfo(lcAccountState) << "Network switched to a NON-metered connection, setting account state to Connected";
setState(State::Connected);
}
});
}
#endif
}
});

// as a fallback and to recover after server issues we also poll
auto timer = new QTimer(this);
timer->setInterval(ConnectionValidator::DefaultCallingInterval);
Expand Down Expand Up @@ -242,7 +239,7 @@ void AccountState::setState(State state)
_connectionValidator->deleteLater();
_connectionValidator.clear();
checkConnectivity();
} else if (_state == Connected && Utility::internetConnectionIsMetered() && ConfigFile().pauseSyncWhenMetered()) {
} else if (_state == Connected && NetworkInformation::instance()->isMetered() && ConfigFile().pauseSyncWhenMetered()) {
_state = PausedDueToMetered;
}
}
Expand Down
2 changes: 0 additions & 2 deletions src/gui/application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,6 @@
#include <QMessageBox>
#include <QPushButton>

#include <QNetworkInformation>

namespace OCC {

Q_LOGGING_CATEGORY(lcApplication, "gui.application", QtInfoMsg)
Expand Down
10 changes: 0 additions & 10 deletions src/gui/guiutility.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
#include <QDesktopServices>
#include <QLoggingCategory>
#include <QMessageBox>
#include <QNetworkInformation>
#include <QQuickWidget>
#include <QUrlQuery>

Expand Down Expand Up @@ -96,15 +95,6 @@ QString Utility::vfsFreeSpaceActionText()
return QCoreApplication::translate("utility", "Free up local space");
}

bool Utility::internetConnectionIsMetered()
{
if (auto *qNetInfo = QNetworkInformation::instance()) {
return qNetInfo->isMetered();
}

return false;
}

void Utility::markDirectoryAsSyncRoot(const QString &path, const QUuid &accountUuid)
{
Q_ASSERT(getDirectorySyncRootMarkings(path).first.isEmpty());
Expand Down
2 changes: 0 additions & 2 deletions src/gui/guiutility.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,6 @@ namespace Utility {

QString socketApiSocketPath();

bool internetConnectionIsMetered();

OWNCLOUDGUI_EXPORT void markDirectoryAsSyncRoot(const QString &path, const QUuid &accountUuid);
std::pair<QString, QUuid> getDirectorySyncRootMarkings(const QString &path);
void unmarkDirectoryAsSyncRoot(const QString &path);
Expand Down
26 changes: 2 additions & 24 deletions src/gui/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "common/utility.h"
#include "gui/application.h"
#include "gui/logbrowser.h"
#include "gui/networkinformation.h"
#include "libsync/configfile.h"
#include "libsync/platform.h"
#include "libsync/theme.h"
Expand All @@ -39,7 +40,6 @@
#include <QCommandLineParser>
#include <QLibraryInfo>
#include <QMessageBox>
#include <QNetworkInformation>
#include <QProcess>
#include <QTimer>
#include <QTranslator>
Expand Down Expand Up @@ -249,28 +249,6 @@ void setupLogging(const CommandLineOptions &options)
qCInfo(lcMain) << "Arguments:" << qApp->arguments();
}

void loadQNetworkInformationBackend()
{
if (!QNetworkInformation::loadDefaultBackend()) {
qCWarning(lcMain) << "Failed to load default backend of QNetworkInformation.";
if (!QNetworkInformation::loadBackendByFeatures(QNetworkInformation::Feature::Metered)) {
qCWarning(lcMain) << "Failed to load backend of QNetworkInformation by metered feature.";
if (!QNetworkInformation::loadBackendByFeatures(QNetworkInformation::Feature::Reachability)) {
qCWarning(lcMain) << "Failed to load backend of QNetworkInformation by reachability feature.";
qCWarning(lcMain) << "Available backends:" << QNetworkInformation::availableBackends().join(QStringLiteral(", "));
return;
}
}
}
qCDebug(lcMain) << "Loaded network information backend:" << QNetworkInformation::instance()->backendName();
qCDebug(lcMain) << "Supported features:" << QNetworkInformation::instance()->supportedFeatures();
qCDebug(lcMain) << "Available backends:" << QNetworkInformation::availableBackends().join(QStringLiteral(", "));
if (auto qni = QNetworkInformation::instance()) {
QObject::connect(qni, &QNetworkInformation::reachabilityChanged,
[](QNetworkInformation::Reachability reachability) { qCInfo(lcMain) << "Connection Status changed to:" << reachability; });
}
}

QString setupTranslations(QApplication *app)
{
const auto trPath = Translations::translationsDirectoryPath();
Expand Down Expand Up @@ -474,7 +452,7 @@ int main(int argc, char **argv)
}

setupLogging(options);
loadQNetworkInformationBackend();
NetworkInformation::initialize();

platform->setApplication(&app);

Expand Down
82 changes: 82 additions & 0 deletions src/gui/networkinformation.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
* Copyright (C) by Erik Verbruggen <erik@verbruggen.consulting>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/

#include "networkinformation.h"

#include <QLoggingCategory>

using namespace OCC;

Q_LOGGING_CATEGORY(lcNetInfo, "gui.netinfo", QtInfoMsg)

NetworkInformation *NetworkInformation::_instance;

static void loadQNetworkInformationBackend()
{
if (!QNetworkInformation::loadDefaultBackend()) {
qCWarning(lcNetInfo) << "Failed to load default backend of QNetworkInformation.";
if (!QNetworkInformation::loadBackendByFeatures(QNetworkInformation::Feature::Metered)) {
qCWarning(lcNetInfo) << "Failed to load backend of QNetworkInformation by metered feature.";
if (!QNetworkInformation::loadBackendByFeatures(QNetworkInformation::Feature::Reachability)) {
qCWarning(lcNetInfo) << "Failed to load backend of QNetworkInformation by reachability feature.";
qCWarning(lcNetInfo) << "Available backends:" << QNetworkInformation::availableBackends().join(QStringLiteral(", "));
return;
}
}
}
qCDebug(lcNetInfo) << "Loaded network information backend:" << QNetworkInformation::instance()->backendName();
qCDebug(lcNetInfo) << "Supported features:" << QNetworkInformation::instance()->supportedFeatures();
qCDebug(lcNetInfo) << "Available backends:" << QNetworkInformation::availableBackends().join(QStringLiteral(", "));
if (auto qni = QNetworkInformation::instance()) {
QObject::connect(qni, &QNetworkInformation::reachabilityChanged,
[](QNetworkInformation::Reachability reachability) { qCInfo(lcNetInfo) << "Connection Status changed to:" << reachability; });
}
}

void NetworkInformation::initialize()
{
Q_ASSERT(!_instance);

_instance = new NetworkInformation;

loadQNetworkInformationBackend();

if (auto qni = QNetworkInformation::instance()) {
connect(qni, &QNetworkInformation::isMeteredChanged, _instance, &NetworkInformation::isMeteredChanged);
connect(qni, &QNetworkInformation::reachabilityChanged, _instance, &NetworkInformation::reachabilityChanged);
}
}

NetworkInformation *NetworkInformation::instance()
{
return _instance;
}

bool NetworkInformation::isMetered()
{
if (auto *qNetInfo = QNetworkInformation::instance()) {
return qNetInfo->isMetered();
}

return false;
}

bool NetworkInformation::supports(Features features) const
{
if (auto *qNetInfo = QNetworkInformation::instance()) {
return qNetInfo->supports(features);
}

return false;
}
47 changes: 47 additions & 0 deletions src/gui/networkinformation.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* Copyright (C) by Erik Verbruggen <erik@verbruggen.consulting>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/

#pragma once

#include "gui/owncloudguilib.h"

#include <QNetworkInformation>

namespace OCC {

class OWNCLOUDGUI_EXPORT NetworkInformation : public QObject
{
Q_OBJECT

public:
static void initialize();
static NetworkInformation *instance();

bool isMetered();

using Feature = QNetworkInformation::Feature;
using Features = QNetworkInformation::Features;
using Reachability = QNetworkInformation::Reachability;

bool supports(Features features) const;

Q_SIGNALS:
void isMeteredChanged(bool isMetered);
void reachabilityChanged(NetworkInformation::Reachability reachability);

private:
static NetworkInformation *_instance;
};

}
14 changes: 6 additions & 8 deletions src/gui/networksettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
*/

#include "networksettings.h"
#include "networkinformation.h"
#include "ui_networksettings.h"

#include "accountmanager.h"
Expand All @@ -22,7 +23,6 @@
#include "theme.h"

#include <QList>
#include <QNetworkInformation>
#include <QNetworkProxy>
#include <QString>
#include <QtGui/QtEvents>
Expand Down Expand Up @@ -183,13 +183,11 @@ void NetworkSettings::loadBWLimitSettings()

void NetworkSettings::loadMeteredSettings()
{
if (QNetworkInformation *qNetInfo = QNetworkInformation::instance()) {
if (Utility::isWindows() // The backend implements the metered feature, but does not report it as supported.
// See https://bugreports.qt.io/browse/QTBUG-118741
|| qNetInfo->supports(QNetworkInformation::Feature::Metered)) {
_ui->pauseSyncWhenMeteredCheckbox->setChecked(ConfigFile().pauseSyncWhenMetered());
return;
}
if (Utility::isWindows() // The backend implements the metered feature, but does not report it as supported.
// See https://bugreports.qt.io/browse/QTBUG-118741
|| NetworkInformation::instance()->supports(NetworkInformation::Feature::Metered)) {
_ui->pauseSyncWhenMeteredCheckbox->setChecked(ConfigFile().pauseSyncWhenMetered());
return;
}

_ui->pauseSyncWhenMeteredCheckbox->setVisible(false);
Expand Down
Loading

0 comments on commit 6936f77

Please sign in to comment.