Only reconnect when relevant settings changed
This commit is contained in:
parent
d66bedf988
commit
7755e97c5f
|
@ -138,6 +138,18 @@ void SyncthingConnection::connect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Applies the specified configuration and tries to reconnect via reconnect() if properties requiring reconnect
|
||||||
|
* to take effect have changed.
|
||||||
|
* \remarks The expected SSL errors of the specified configuration are updated accordingly.
|
||||||
|
*/
|
||||||
|
void SyncthingConnection::connect(SyncthingConnectionSettings &connectionSettings)
|
||||||
|
{
|
||||||
|
if(applySettings(connectionSettings)) {
|
||||||
|
reconnect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Disconnects. Does nothing if not connected.
|
* \brief Disconnects. Does nothing if not connected.
|
||||||
*/
|
*/
|
||||||
|
@ -620,8 +632,9 @@ QMetaObject::Connection SyncthingConnection::requestLog(std::function<void (cons
|
||||||
* - Loading the certificate is only possible if the connection object is configured
|
* - Loading the certificate is only possible if the connection object is configured
|
||||||
* to connect to the locally running Syncthing instance. Otherwise this method will
|
* to connect to the locally running Syncthing instance. Otherwise this method will
|
||||||
* only do the cleanup of previous certificates but not emit any errors.
|
* only do the cleanup of previous certificates but not emit any errors.
|
||||||
|
* \returns Returns whether a certificate could be loaded.
|
||||||
*/
|
*/
|
||||||
void SyncthingConnection::loadSelfSignedCertificate()
|
bool SyncthingConnection::loadSelfSignedCertificate()
|
||||||
{
|
{
|
||||||
// ensure current exceptions for self-signed certificates are cleared
|
// ensure current exceptions for self-signed certificates are cleared
|
||||||
m_expectedSslErrors.clear();
|
m_expectedSslErrors.clear();
|
||||||
|
@ -629,31 +642,33 @@ void SyncthingConnection::loadSelfSignedCertificate()
|
||||||
// not required when not using secure connection
|
// not required when not using secure connection
|
||||||
const QUrl syncthingUrl(m_syncthingUrl);
|
const QUrl syncthingUrl(m_syncthingUrl);
|
||||||
if(!syncthingUrl.scheme().endsWith(QChar('s'))) {
|
if(!syncthingUrl.scheme().endsWith(QChar('s'))) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// only possible if the Syncthing instance is running on the local machine
|
// only possible if the Syncthing instance is running on the local machine
|
||||||
if(!isLocal(syncthingUrl)) {
|
if(!isLocal(syncthingUrl)) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// find cert
|
// find cert
|
||||||
const QString certPath = !m_configDir.isEmpty() ? (m_configDir + QStringLiteral("/https-cert.pem")) : SyncthingConfig::locateHttpsCertificate();
|
const QString certPath = !m_configDir.isEmpty() ? (m_configDir + QStringLiteral("/https-cert.pem")) : SyncthingConfig::locateHttpsCertificate();
|
||||||
if(certPath.isEmpty()) {
|
if(certPath.isEmpty()) {
|
||||||
emit error(tr("Unable to locate certificate used by Syncthing GUI."), SyncthingErrorCategory::OverallConnection);
|
emit error(tr("Unable to locate certificate used by Syncthing GUI."), SyncthingErrorCategory::OverallConnection);
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
// add exception
|
// add exception
|
||||||
const QList<QSslCertificate> cert = QSslCertificate::fromPath(certPath);
|
const QList<QSslCertificate> certs = QSslCertificate::fromPath(certPath);
|
||||||
if(cert.isEmpty()) {
|
if(certs.isEmpty()) {
|
||||||
emit error(tr("Unable to load certificate used by Syncthing GUI."), SyncthingErrorCategory::OverallConnection);
|
emit error(tr("Unable to load certificate used by Syncthing GUI."), SyncthingErrorCategory::OverallConnection);
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
const QSslCertificate &cert = certs.at(0);
|
||||||
m_expectedSslErrors.reserve(4);
|
m_expectedSslErrors.reserve(4);
|
||||||
m_expectedSslErrors << QSslError(QSslError::UnableToGetLocalIssuerCertificate, cert.at(0));
|
m_expectedSslErrors << QSslError(QSslError::UnableToGetLocalIssuerCertificate, cert)
|
||||||
m_expectedSslErrors << QSslError(QSslError::UnableToVerifyFirstCertificate, cert.at(0));
|
<< QSslError(QSslError::UnableToVerifyFirstCertificate, cert)
|
||||||
m_expectedSslErrors << QSslError(QSslError::SelfSignedCertificate, cert.at(0));
|
<< QSslError(QSslError::SelfSignedCertificate, cert)
|
||||||
m_expectedSslErrors << QSslError(QSslError::HostNameMismatch, cert.at(0));
|
<< QSslError(QSslError::HostNameMismatch, cert);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -661,26 +676,46 @@ void SyncthingConnection::loadSelfSignedCertificate()
|
||||||
* \remarks
|
* \remarks
|
||||||
* - The expected SSL errors of the specified configuration are updated accordingly.
|
* - The expected SSL errors of the specified configuration are updated accordingly.
|
||||||
* - The configuration is not used instantly. It will be used on the next reconnect.
|
* - The configuration is not used instantly. It will be used on the next reconnect.
|
||||||
|
* \returns Returns whether at least one property requiring a reconnect to take effect has changed.
|
||||||
* \sa reconnect()
|
* \sa reconnect()
|
||||||
*/
|
*/
|
||||||
void SyncthingConnection::applySettings(SyncthingConnectionSettings &connectionSettings)
|
bool SyncthingConnection::applySettings(SyncthingConnectionSettings &connectionSettings)
|
||||||
{
|
{
|
||||||
setSyncthingUrl(connectionSettings.syncthingUrl);
|
bool reconnectRequired = false;
|
||||||
setApiKey(connectionSettings.apiKey);
|
if(syncthingUrl() != connectionSettings.syncthingUrl) {
|
||||||
if(connectionSettings.authEnabled) {
|
setSyncthingUrl(connectionSettings.syncthingUrl);
|
||||||
setCredentials(connectionSettings.userName, connectionSettings.password);
|
reconnectRequired = true;
|
||||||
} else {
|
|
||||||
setCredentials(QString(), QString());
|
|
||||||
}
|
}
|
||||||
|
if(apiKey() != connectionSettings.apiKey) {
|
||||||
|
setApiKey(connectionSettings.apiKey);
|
||||||
|
reconnectRequired = true;
|
||||||
|
}
|
||||||
|
if((connectionSettings.authEnabled && (user() != connectionSettings.userName || password() != connectionSettings.password))
|
||||||
|
|| (!connectionSettings.authEnabled && (!user().isEmpty() || !password().isEmpty()))) {
|
||||||
|
if(connectionSettings.authEnabled) {
|
||||||
|
setCredentials(connectionSettings.userName, connectionSettings.password);
|
||||||
|
} else {
|
||||||
|
setCredentials(QString(), QString());
|
||||||
|
}
|
||||||
|
reconnectRequired = true;
|
||||||
|
}
|
||||||
|
if(connectionSettings.expectedSslErrors.isEmpty()) {
|
||||||
|
const bool previouslyHadExpectedSslErrors = !expectedSslErrors().isEmpty();
|
||||||
|
const bool ok = loadSelfSignedCertificate();
|
||||||
|
connectionSettings.expectedSslErrors = expectedSslErrors();
|
||||||
|
if(ok || (previouslyHadExpectedSslErrors && !ok)) {
|
||||||
|
reconnectRequired = true;
|
||||||
|
}
|
||||||
|
} else if(expectedSslErrors() != connectionSettings.expectedSslErrors) {
|
||||||
|
m_expectedSslErrors = connectionSettings.expectedSslErrors;
|
||||||
|
reconnectRequired = true;
|
||||||
|
}
|
||||||
|
|
||||||
setTrafficPollInterval(connectionSettings.trafficPollInterval);
|
setTrafficPollInterval(connectionSettings.trafficPollInterval);
|
||||||
setDevStatsPollInterval(connectionSettings.devStatsPollInterval);
|
setDevStatsPollInterval(connectionSettings.devStatsPollInterval);
|
||||||
setAutoReconnectInterval(connectionSettings.reconnectInterval);
|
setAutoReconnectInterval(connectionSettings.reconnectInterval);
|
||||||
if(connectionSettings.expectedSslErrors.isEmpty()) {
|
|
||||||
loadSelfSignedCertificate();
|
return reconnectRequired;
|
||||||
connectionSettings.expectedSslErrors = expectedSslErrors();
|
|
||||||
} else {
|
|
||||||
m_expectedSslErrors = connectionSettings.expectedSslErrors;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
|
@ -111,9 +111,10 @@ public:
|
||||||
const std::vector<SyncthingDir *> &completedDirs() const;
|
const std::vector<SyncthingDir *> &completedDirs() const;
|
||||||
|
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
void loadSelfSignedCertificate();
|
bool loadSelfSignedCertificate();
|
||||||
void applySettings(SyncthingConnectionSettings &connectionSettings);
|
bool applySettings(SyncthingConnectionSettings &connectionSettings);
|
||||||
void connect();
|
void connect();
|
||||||
|
void connect(SyncthingConnectionSettings &connectionSettings);
|
||||||
void disconnect();
|
void disconnect();
|
||||||
void reconnect();
|
void reconnect();
|
||||||
void reconnect(SyncthingConnectionSettings &connectionSettings);
|
void reconnect(SyncthingConnectionSettings &connectionSettings);
|
||||||
|
|
|
@ -61,7 +61,7 @@ TrayIcon::TrayIcon(QObject *parent) :
|
||||||
// setup notifications
|
// setup notifications
|
||||||
m_disconnectedNotification.setMessage(tr("Disconnected from Syncthing"));
|
m_disconnectedNotification.setMessage(tr("Disconnected from Syncthing"));
|
||||||
m_disconnectedNotification.setActions(QStringList(tr("Try to reconnect")));
|
m_disconnectedNotification.setActions(QStringList(tr("Try to reconnect")));
|
||||||
connect(&m_disconnectedNotification, &DBusNotification::actionInvoked, &(m_trayMenu.widget()->connection()), &SyncthingConnection::connect);
|
connect(&m_disconnectedNotification, &DBusNotification::actionInvoked, &(m_trayMenu.widget()->connection()), static_cast<void(SyncthingConnection::*)(void)>(&SyncthingConnection::connect));
|
||||||
m_syncthingNotification.setActions(QStringList({QStringLiteral("show"), tr("Show"), QStringLiteral("dismiss"), tr("Dismiss")}));
|
m_syncthingNotification.setActions(QStringList({QStringLiteral("show"), tr("Show"), QStringLiteral("dismiss"), tr("Dismiss")}));
|
||||||
connect(&m_syncthingNotification, &DBusNotification::actionInvoked, this, &TrayIcon::handleSyncthingNotificationAction);
|
connect(&m_syncthingNotification, &DBusNotification::actionInvoked, this, &TrayIcon::handleSyncthingNotificationAction);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -375,7 +375,7 @@ void TrayWidget::applySettings()
|
||||||
instance->m_connectionsMenu->actions().at(0)->setChecked(true);
|
instance->m_connectionsMenu->actions().at(0)->setChecked(true);
|
||||||
}
|
}
|
||||||
instance->m_ui->connectionsPushButton->setText(instance->m_selectedConnection->label);
|
instance->m_ui->connectionsPushButton->setText(instance->m_selectedConnection->label);
|
||||||
instance->m_connection.reconnect(*instance->m_selectedConnection);
|
instance->m_connection.connect(*instance->m_selectedConnection);
|
||||||
|
|
||||||
// web view
|
// web view
|
||||||
#ifndef SYNCTHINGTRAY_NO_WEBVIEW
|
#ifndef SYNCTHINGTRAY_NO_WEBVIEW
|
||||||
|
|
|
@ -57,6 +57,26 @@ WebPage::WebPage(WebViewDialog *dlg, WEB_VIEW_PROVIDER *view) :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool WebPage::isSamePage(const QUrl &url1, const QUrl &url2)
|
||||||
|
{
|
||||||
|
if(url1.scheme() == url2.scheme()
|
||||||
|
&& url1.host() == url2.host()
|
||||||
|
&& url1.port() == url2.port()) {
|
||||||
|
QString path1 = url1.path();
|
||||||
|
while(path1.endsWith(QChar('/'))) {
|
||||||
|
path1.resize(path1.size() - 1);
|
||||||
|
}
|
||||||
|
QString path2 = url2.path();
|
||||||
|
while(path2.endsWith(QChar('/'))) {
|
||||||
|
path2.resize(path2.size() - 1);
|
||||||
|
}
|
||||||
|
if(path1 == path2) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
WEB_PAGE_PROVIDER *WebPage::createWindow(WEB_PAGE_PROVIDER::WebWindowType type)
|
WEB_PAGE_PROVIDER *WebPage::createWindow(WEB_PAGE_PROVIDER::WebWindowType type)
|
||||||
{
|
{
|
||||||
Q_UNUSED(type)
|
Q_UNUSED(type)
|
||||||
|
@ -128,20 +148,8 @@ bool WebPage::handleNavigationRequest(const QUrl ¤tUrl, const QUrl &target
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// only allow navigation on the same page
|
// only allow navigation on the same page
|
||||||
if(currentUrl.scheme() == targetUrl.scheme()
|
if(isSamePage(currentUrl, targetUrl)) {
|
||||||
&& currentUrl.host() == targetUrl.host()
|
return true;
|
||||||
&& currentUrl.port() == targetUrl.port()) {
|
|
||||||
QString currentPath = currentUrl.path();
|
|
||||||
while(currentPath.endsWith(QChar('/'))) {
|
|
||||||
currentPath.resize(currentPath.size() - 1);
|
|
||||||
}
|
|
||||||
QString targetPath = targetUrl.path();
|
|
||||||
while(targetPath.endsWith(QChar('/'))) {
|
|
||||||
targetPath.resize(targetPath.size() - 1);
|
|
||||||
}
|
|
||||||
if(currentPath == targetPath) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// otherwise open URL in external browser
|
// otherwise open URL in external browser
|
||||||
QDesktopServices::openUrl(targetUrl);
|
QDesktopServices::openUrl(targetUrl);
|
||||||
|
|
|
@ -26,6 +26,8 @@ class WebPage : public WEB_PAGE_PROVIDER
|
||||||
public:
|
public:
|
||||||
WebPage(WebViewDialog *dlg = nullptr, WEB_VIEW_PROVIDER *view = nullptr);
|
WebPage(WebViewDialog *dlg = nullptr, WEB_VIEW_PROVIDER *view = nullptr);
|
||||||
|
|
||||||
|
static bool isSamePage(const QUrl &url1, const QUrl &url2);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
WEB_PAGE_PROVIDER *createWindow(WebWindowType type);
|
WEB_PAGE_PROVIDER *createWindow(WebWindowType type);
|
||||||
#ifdef SYNCTHINGTRAY_USE_WEBENGINE
|
#ifdef SYNCTHINGTRAY_USE_WEBENGINE
|
||||||
|
@ -45,7 +47,7 @@ private slots:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool handleNavigationRequest(const QUrl ¤tUrl, const QUrl &url);
|
static bool handleNavigationRequest(const QUrl ¤tUrl, const QUrl &url);
|
||||||
|
|
||||||
WebViewDialog *m_dlg;
|
WebViewDialog *m_dlg;
|
||||||
WEB_VIEW_PROVIDER *m_view;
|
WEB_VIEW_PROVIDER *m_view;
|
||||||
|
|
|
@ -54,7 +54,9 @@ QtGui::WebViewDialog::~WebViewDialog()
|
||||||
void QtGui::WebViewDialog::applySettings(const Data::SyncthingConnectionSettings &connectionSettings)
|
void QtGui::WebViewDialog::applySettings(const Data::SyncthingConnectionSettings &connectionSettings)
|
||||||
{
|
{
|
||||||
m_settings = connectionSettings;
|
m_settings = connectionSettings;
|
||||||
m_view->setUrl(connectionSettings.syncthingUrl);
|
if(!WebPage::isSamePage(m_view->url(), connectionSettings.syncthingUrl)) {
|
||||||
|
m_view->setUrl(connectionSettings.syncthingUrl);
|
||||||
|
}
|
||||||
m_view->setZoomFactor(Settings::values().webView.zoomFactor);
|
m_view->setZoomFactor(Settings::values().webView.zoomFactor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue