Implement multiple connection configs

This commit is contained in:
Martchus 2016-09-03 20:14:52 +02:00
parent cb251fd123
commit 1b51a582cb
25 changed files with 994 additions and 378 deletions

View File

@ -90,29 +90,36 @@ set(DOC_FILES
) )
set(REQUIRED_ICONS set(REQUIRED_ICONS
network-card dialog-cancel
window-close dialog-ok
dialog-ok-apply
edit-copy edit-copy
edit-paste edit-paste
preferences-other
view-barcode
folder-open
media-playback-start
text-plain
help-about
media-playback-pause
view-refresh
folder folder
network-server folder-open
folder-sync folder-sync
help-about
internet-web-browser internet-web-browser
list-add
list-remove
media-playback-pause
media-playback-start
network-card
network-connect network-connect
system-run network-server
system-search
preferences-desktop preferences-desktop
preferences-desktop-notification
preferences-desktop-icons preferences-desktop-icons
preferences-desktop-locale preferences-desktop-locale
preferences-desktop-notification
preferences-other
qtcreator
system-run
system-search
system-file-manager
text-plain
view-barcode
view-refresh
window-close
) )
# find c++utilities # find c++utilities

View File

@ -25,10 +25,11 @@ Qt 5-based tray application for [Syncthing](https://github.com/syncthing/syncthi
* Provides quick access to the official web UI * Provides quick access to the official web UI
* Utilizes either Qt WebKit or Qt WebEngine * Utilizes either Qt WebKit or Qt WebEngine
* Can be built without web view support as well (then the web UI is opened in the regular browser) * Can be built without web view support as well (then the web UI is opened in the regular browser)
* Allows quickly switching between multiple Syncthing instances
* Still under development; the following features are planned * Still under development; the following features are planned
* Connect to multiple instances of Syncthing at a time
* Show currently processed items * Show currently processed items
* Show recently processed items * Show recently processed items
* Improve notification handling
## Screenshots ## Screenshots
### Under Openbox/Tint2 ### Under Openbox/Tint2

View File

@ -64,12 +64,12 @@ int main(int argc, char *argv[])
TrayIcon trayIcon; TrayIcon trayIcon;
trayIcon.show(); trayIcon.show();
if(Settings::firstLaunch()) { if(Settings::firstLaunch()) {
trayIcon.trayMenu().widget()->showSettingsDialog();
QMessageBox msgBox; QMessageBox msgBox;
msgBox.setIcon(QMessageBox::Information); msgBox.setIcon(QMessageBox::Information);
msgBox.setText(QCoreApplication::translate("main", "You must configure how to connect to Syncthing when using Syncthing Tray the first time.")); msgBox.setText(QCoreApplication::translate("main", "You must configure how to connect to Syncthing when using Syncthing Tray the first time."));
msgBox.setInformativeText(QCoreApplication::translate("main", "Note that the settings dialog allows importing URL, credentials and API-key from the local Syncthing configuration.")); msgBox.setInformativeText(QCoreApplication::translate("main", "Note that the settings dialog allows importing URL, credentials and API-key from the local Syncthing configuration."));
msgBox.exec(); msgBox.exec();
trayIcon.trayMenu().widget()->showSettingsDialog();
} }
res = application.exec(); res = application.exec();
} else { } else {

View File

@ -7,7 +7,11 @@
#include <QApplication> #include <QApplication>
#include <QSettings> #include <QSettings>
#include <QFrame> #include <QFrame>
#include <QSslCertificate>
#include <QSslError>
#include <QMessageBox>
using namespace std;
using namespace Media; using namespace Media;
namespace Settings { namespace Settings {
@ -19,29 +23,15 @@ bool &firstLaunch()
} }
// connection // connection
QString &syncthingUrl() ConnectionSettings &primaryConnectionSettings()
{ {
static QString v; static ConnectionSettings v;
return v; return v;
} }
bool &authEnabled()
std::vector<ConnectionSettings> &secondaryConnectionSettings()
{ {
static bool v = false; static vector<ConnectionSettings> v;
return v;
}
QString &userName()
{
static QString v;
return v;
}
QString &password()
{
static QString v;
return v;
}
QByteArray &apiKey()
{
static QByteArray v;
return v; return v;
} }
@ -141,17 +131,45 @@ void restore()
QSettings settings(QSettings::IniFormat, QSettings::UserScope, QApplication::organizationName(), QApplication::applicationName()); QSettings settings(QSettings::IniFormat, QSettings::UserScope, QApplication::organizationName(), QApplication::applicationName());
settings.beginGroup(QStringLiteral("tray")); settings.beginGroup(QStringLiteral("tray"));
firstLaunch() = !settings.contains(QStringLiteral("syncthingUrl"));
syncthingUrl() = settings.value(QStringLiteral("syncthingUrl"), QStringLiteral("http://localhost:8080/")).toString(); const int connectionCount = settings.beginReadArray(QStringLiteral("connections"));
authEnabled() = settings.value(QStringLiteral("authEnabled"), false).toBool(); if(connectionCount > 0) {
userName() = settings.value(QStringLiteral("userName")).toString(); secondaryConnectionSettings().clear();
password() = settings.value(QStringLiteral("password")).toString(); secondaryConnectionSettings().reserve(static_cast<size_t>(connectionCount));
apiKey() = settings.value(QStringLiteral("apiKey")).toByteArray(); for(int i = 0; i < connectionCount; ++i) {
notifyOnDisconnect() = settings.value(QStringLiteral("notifyOnDisconnect"), true).toBool(); ConnectionSettings *connectionSettings;
notifyOnInternalErrors() = settings.value(QStringLiteral("notifyOnErrors"), true).toBool(); if(i == 0) {
notifyOnSyncComplete() = settings.value(QStringLiteral("notifyOnSyncComplete"), true).toBool(); connectionSettings = &primaryConnectionSettings();
showSyncthingNotifications() = settings.value(QStringLiteral("showSyncthingNotifications"), true).toBool(); } else {
showTraffic() = settings.value(QStringLiteral("showTraffic"), true).toBool(); secondaryConnectionSettings().emplace_back();
connectionSettings = &secondaryConnectionSettings().back();
}
settings.setArrayIndex(i);
connectionSettings->label = settings.value(QStringLiteral("label")).toString();
if(connectionSettings->label.isEmpty()) {
connectionSettings->label = (i == 0 ? QStringLiteral("Primary instance") : QStringLiteral("Secondary instance %1").arg(i));
}
connectionSettings->syncthingUrl = settings.value(QStringLiteral("syncthingUrl"), connectionSettings->syncthingUrl).toString();
connectionSettings->authEnabled = settings.value(QStringLiteral("authEnabled"), connectionSettings->authEnabled).toBool();
connectionSettings->userName = settings.value(QStringLiteral("userName")).toString();
connectionSettings->password = settings.value(QStringLiteral("password")).toString();
connectionSettings->apiKey = settings.value(QStringLiteral("apiKey")).toByteArray();
connectionSettings->httpsCertPath = settings.value(QStringLiteral("httpsCertPath")).toString();
if(!connectionSettings->loadHttpsCert()) {
QMessageBox::critical(nullptr, QCoreApplication::applicationName(), QCoreApplication::translate("Settings::restore", "Unable to load certificate \"%1\" when restoring settings.").arg(connectionSettings->httpsCertPath));
}
}
} else {
firstLaunch() = true;
primaryConnectionSettings().label = QStringLiteral("Primary instance");
}
settings.endArray();
notifyOnDisconnect() = settings.value(QStringLiteral("notifyOnDisconnect"), notifyOnDisconnect()).toBool();
notifyOnInternalErrors() = settings.value(QStringLiteral("notifyOnErrors"), notifyOnInternalErrors()).toBool();
notifyOnSyncComplete() = settings.value(QStringLiteral("notifyOnSyncComplete"), notifyOnSyncComplete()).toBool();
showSyncthingNotifications() = settings.value(QStringLiteral("showSyncthingNotifications"), showSyncthingNotifications()).toBool();
showTraffic() = settings.value(QStringLiteral("showTraffic"), showTraffic()).toBool();
trayMenuSize() = settings.value(QStringLiteral("trayMenuSize"), trayMenuSize()).toSize(); trayMenuSize() = settings.value(QStringLiteral("trayMenuSize"), trayMenuSize()).toSize();
frameStyle() = settings.value(QStringLiteral("frameStyle"), frameStyle()).toInt(); frameStyle() = settings.value(QStringLiteral("frameStyle"), frameStyle()).toInt();
settings.endGroup(); settings.endGroup();
@ -179,11 +197,21 @@ void save()
QSettings settings(QSettings::IniFormat, QSettings::UserScope, QApplication::organizationName(), QApplication::applicationName()); QSettings settings(QSettings::IniFormat, QSettings::UserScope, QApplication::organizationName(), QApplication::applicationName());
settings.beginGroup(QStringLiteral("tray")); settings.beginGroup(QStringLiteral("tray"));
settings.setValue(QStringLiteral("syncthingUrl"), syncthingUrl()); const int connectionCount = static_cast<int>(1 + secondaryConnectionSettings().size());
settings.setValue(QStringLiteral("authEnabled"), authEnabled()); settings.beginWriteArray(QStringLiteral("connections"), connectionCount);
settings.setValue(QStringLiteral("userName"), userName()); for(int i = 0; i < connectionCount; ++i) {
settings.setValue(QStringLiteral("password"), password()); const ConnectionSettings *connectionSettings = (i == 0 ? &primaryConnectionSettings() : &secondaryConnectionSettings()[static_cast<size_t>(i - 1)]);
settings.setValue(QStringLiteral("apiKey"), apiKey()); settings.setArrayIndex(i);
settings.setValue(QStringLiteral("label"), connectionSettings->label);
settings.setValue(QStringLiteral("syncthingUrl"), connectionSettings->syncthingUrl);
settings.setValue(QStringLiteral("authEnabled"), connectionSettings->authEnabled);
settings.setValue(QStringLiteral("userName"), connectionSettings->userName);
settings.setValue(QStringLiteral("password"), connectionSettings->password);
settings.setValue(QStringLiteral("apiKey"), connectionSettings->apiKey);
settings.setValue(QStringLiteral("httpsCertPath"), connectionSettings->httpsCertPath);
}
settings.endArray();
settings.setValue(QStringLiteral("notifyOnDisconnect"), notifyOnDisconnect()); settings.setValue(QStringLiteral("notifyOnDisconnect"), notifyOnDisconnect());
settings.setValue(QStringLiteral("notifyOnErrors"), notifyOnInternalErrors()); settings.setValue(QStringLiteral("notifyOnErrors"), notifyOnInternalErrors());
settings.setValue(QStringLiteral("notifyOnSyncComplete"), notifyOnSyncComplete()); settings.setValue(QStringLiteral("notifyOnSyncComplete"), notifyOnSyncComplete());
@ -211,4 +239,21 @@ void save()
qtSettings().save(settings); qtSettings().save(settings);
} }
bool ConnectionSettings::loadHttpsCert()
{
if(!httpsCertPath.isEmpty()) {
const QList<QSslCertificate> cert = QSslCertificate::fromPath(httpsCertPath);
if(cert.isEmpty()) {
return false;
}
expectedSslErrors.clear();
expectedSslErrors.reserve(4);
expectedSslErrors << QSslError(QSslError::UnableToGetLocalIssuerCertificate, cert.at(0));
expectedSslErrors << QSslError(QSslError::UnableToVerifyFirstCertificate, cert.at(0));
expectedSslErrors << QSslError(QSslError::SelfSignedCertificate, cert.at(0));
expectedSslErrors << QSslError(QSslError::HostNameMismatch, cert.at(0));
}
return true;
}
} }

View File

@ -3,10 +3,12 @@
#include <c++utilities/conversion/types.h> #include <c++utilities/conversion/types.h>
#include <QtGlobal> #include <QString>
#include <QByteArray>
#include <QSslError>
#include <vector>
QT_FORWARD_DECLARE_CLASS(QByteArray)
QT_FORWARD_DECLARE_CLASS(QString)
QT_FORWARD_DECLARE_CLASS(QSize) QT_FORWARD_DECLARE_CLASS(QSize)
namespace Media { namespace Media {
@ -23,11 +25,19 @@ namespace Settings {
bool &firstLaunch(); bool &firstLaunch();
// connection // connection
QString &syncthingUrl(); struct ConnectionSettings {
bool &authEnabled(); QString label;
QString &userName(); QString syncthingUrl;
QString &password(); bool authEnabled = false;
QByteArray &apiKey(); QString userName;
QString password;
QByteArray apiKey;
QString httpsCertPath;
QList<QSslError> expectedSslErrors;
bool loadHttpsCert();
};
ConnectionSettings &primaryConnectionSettings();
std::vector<ConnectionSettings> &secondaryConnectionSettings();
// notifications // notifications
bool &notifyOnDisconnect(); bool &notifyOnDisconnect();

View File

@ -8,7 +8,7 @@ namespace Data {
/*! /*!
* \struct SyncthingConfig * \struct SyncthingConfig
* \brief The SyncthingConfig struct holds the configuration of Syncthing itself read from config.xml in the Syncthing home directory. * \brief The SyncthingConfig struct holds the configuration of the local Syncthing instance read from config.xml in the Syncthing home directory.
* \remarks Only a few fields are required since most of the Syncthing config can be accessed via SyncthingConnection class. * \remarks Only a few fields are required since most of the Syncthing config can be accessed via SyncthingConnection class.
*/ */

View File

@ -1,6 +1,8 @@
#include "./syncthingconnection.h" #include "./syncthingconnection.h"
#include "./syncthingconfig.h" #include "./syncthingconfig.h"
#include "../application/settings.h"
#include <c++utilities/conversion/conversionexception.h> #include <c++utilities/conversion/conversionexception.h>
#include <QNetworkAccessManager> #include <QNetworkAccessManager>
@ -102,8 +104,6 @@ bool SyncthingDir::assignStatus(DirStatus newStatus, DateTime time)
* \brief The SyncthingConnection class allows Qt applications to access Syncthing. * \brief The SyncthingConnection class allows Qt applications to access Syncthing.
*/ */
QList<QSslError> SyncthingConnection::m_expectedCertificateErrors;
/*! /*!
* \brief Constructs a new instance ready to connect. To establish the connection, call connect(). * \brief Constructs a new instance ready to connect. To establish the connection, call connect().
*/ */
@ -165,6 +165,10 @@ void SyncthingConnection::connect()
{ {
if(!isConnected()) { if(!isConnected()) {
m_reconnecting = m_hasConfig = m_hasStatus = false; m_reconnecting = m_hasConfig = m_hasStatus = false;
if(m_apiKey.isEmpty() || m_syncthingUrl.isEmpty()) {
emit error(tr("Connection configuration is insufficient."));
return;
}
requestConfig(); requestConfig();
requestStatus(); requestStatus();
m_keepPolling = true; m_keepPolling = true;
@ -182,6 +186,7 @@ void SyncthingConnection::disconnect()
/*! /*!
* \brief Disconnects if connected, then (re-)connects asynchronously. * \brief Disconnects if connected, then (re-)connects asynchronously.
* \remarks Clears the currently cached configuration.
*/ */
void SyncthingConnection::reconnect() void SyncthingConnection::reconnect()
{ {
@ -190,10 +195,63 @@ void SyncthingConnection::reconnect()
m_hasConfig = m_hasStatus = false; m_hasConfig = m_hasStatus = false;
abortAllRequests(); abortAllRequests();
} else { } else {
connect(); continueReconnect();
} }
} }
/*!
* \brief Applies the specifies configuration and tries to reconnect via reconnect().
* \remarks The expected SSL errors of the specified configuration are updated accordingly.
*/
void SyncthingConnection::reconnect(Settings::ConnectionSettings &connectionSettings)
{
setSyncthingUrl(connectionSettings.syncthingUrl);
setApiKey(connectionSettings.apiKey);
if(connectionSettings.authEnabled) {
setCredentials(connectionSettings.userName, connectionSettings.password);
} else {
setCredentials(QString(), QString());
}
loadSelfSignedCertificate();
if(connectionSettings.expectedSslErrors.isEmpty()) {
connectionSettings.expectedSslErrors = expectedSslErrors();
}
reconnect();
}
/*!
* \brief Internally called to reconnect; ensures currently cached config is cleared.
*/
void SyncthingConnection::continueReconnect()
{
emit newConfig(QJsonObject()); // configuration will be invalidated
m_status = SyncthingStatus::Disconnected;
m_keepPolling = true;
m_reconnecting = false;
m_lastEventId = 0;
m_configDir.clear();
m_myId.clear();
m_totalIncomingTraffic = 0;
m_totalOutgoingTraffic = 0;
m_totalIncomingRate = 0.0;
m_totalOutgoingRate = 0.0;
m_unreadNotifications = false;
m_hasConfig = false;
m_hasStatus = false;
m_dirs.clear();
m_devs.clear();
m_lastConnectionsUpdate = DateTime();
m_lastFileTime = DateTime();
m_lastFileName.clear();
m_lastFileDeleted = false;
if(m_apiKey.isEmpty() || m_syncthingUrl.isEmpty()) {
emit error(tr("Connection configuration is insufficient."));
return;
}
requestConfig();
requestStatus();
}
void SyncthingConnection::pause(const QString &dev) void SyncthingConnection::pause(const QString &dev)
{ {
QUrlQuery query; QUrlQuery query;
@ -273,7 +331,7 @@ QNetworkRequest SyncthingConnection::prepareRequest(const QString &path, const Q
QNetworkReply *SyncthingConnection::requestData(const QString &path, const QUrlQuery &query, bool rest) QNetworkReply *SyncthingConnection::requestData(const QString &path, const QUrlQuery &query, bool rest)
{ {
auto *reply = networkAccessManager().get(prepareRequest(path, query, rest)); auto *reply = networkAccessManager().get(prepareRequest(path, query, rest));
reply->ignoreSslErrors(m_expectedCertificateErrors); reply->ignoreSslErrors(m_expectedSslErrors);
return reply; return reply;
} }
@ -283,7 +341,7 @@ QNetworkReply *SyncthingConnection::requestData(const QString &path, const QUrlQ
QNetworkReply *SyncthingConnection::postData(const QString &path, const QUrlQuery &query, const QByteArray &data) QNetworkReply *SyncthingConnection::postData(const QString &path, const QUrlQuery &query, const QByteArray &data)
{ {
auto *reply = networkAccessManager().post(prepareRequest(path, query), data); auto *reply = networkAccessManager().post(prepareRequest(path, query), data);
reply->ignoreSslErrors(m_expectedCertificateErrors); reply->ignoreSslErrors(m_expectedSslErrors);
return reply; return reply;
} }
@ -470,14 +528,15 @@ QMetaObject::Connection SyncthingConnection::requestLog(std::function<void (cons
*/ */
void SyncthingConnection::loadSelfSignedCertificate() void SyncthingConnection::loadSelfSignedCertificate()
{ {
// ensure current exceptions for self-signed certificates are cleared
m_expectedSslErrors.clear();
// only possible if the Syncthing instance is running on the local machine // only possible if the Syncthing instance is running on the local machine
const QString host(QUrl(syncthingUrl()).host()); const QString host(QUrl(syncthingUrl()).host());
if(host.compare(QLatin1String("localhost"), Qt::CaseInsensitive) != 0 && !QHostAddress().isLoopback()) { if(host.compare(QLatin1String("localhost"), Qt::CaseInsensitive) != 0 && !QHostAddress(host).isLoopback()) {
return; return;
} }
// ensure current exceptions for self-signed certificates are cleared
m_expectedCertificateErrors.clear();
// 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()) {
@ -490,10 +549,11 @@ void SyncthingConnection::loadSelfSignedCertificate()
emit error(tr("Unable to load certificate used by Syncthing GUI.")); emit error(tr("Unable to load certificate used by Syncthing GUI."));
return; return;
} }
m_expectedCertificateErrors << QSslError(QSslError::UnableToGetLocalIssuerCertificate, cert.at(0)); m_expectedSslErrors.reserve(4);
m_expectedCertificateErrors << QSslError(QSslError::UnableToVerifyFirstCertificate, cert.at(0)); m_expectedSslErrors << QSslError(QSslError::UnableToGetLocalIssuerCertificate, cert.at(0));
m_expectedCertificateErrors << QSslError(QSslError::SelfSignedCertificate, cert.at(0)); m_expectedSslErrors << QSslError(QSslError::UnableToVerifyFirstCertificate, cert.at(0));
m_expectedCertificateErrors << QSslError(QSslError::HostNameMismatch, cert.at(0)); m_expectedSslErrors << QSslError(QSslError::SelfSignedCertificate, cert.at(0));
m_expectedSslErrors << QSslError(QSslError::HostNameMismatch, cert.at(0));
} }
/*! /*!
@ -868,11 +928,7 @@ void SyncthingConnection::readEvents()
// intended disconnect, not an error // intended disconnect, not an error
if(m_reconnecting) { if(m_reconnecting) {
// if reconnection flag is set, instantly etstablish a new connection ... // if reconnection flag is set, instantly etstablish a new connection ...
m_reconnecting = false; continueReconnect();
requestConfig();
requestStatus();
m_lastEventId = 0;
m_keepPolling = true;
} else { } else {
// ... otherwise keep disconnected // ... otherwise keep disconnected
setStatus(SyncthingStatus::Disconnected); setStatus(SyncthingStatus::Disconnected);

View File

@ -17,6 +17,10 @@ QT_FORWARD_DECLARE_CLASS(QUrlQuery)
QT_FORWARD_DECLARE_CLASS(QJsonObject) QT_FORWARD_DECLARE_CLASS(QJsonObject)
QT_FORWARD_DECLARE_CLASS(QJsonArray) QT_FORWARD_DECLARE_CLASS(QJsonArray)
namespace Settings {
struct ConnectionSettings;
}
namespace Data { namespace Data {
QNetworkAccessManager &networkAccessManager(); QNetworkAccessManager &networkAccessManager();
@ -151,13 +155,14 @@ public:
const std::vector<SyncthingDev> &devInfo() const; const std::vector<SyncthingDev> &devInfo() const;
QMetaObject::Connection requestQrCode(const QString &text, std::function<void (const QPixmap &)> callback); QMetaObject::Connection requestQrCode(const QString &text, std::function<void (const QPixmap &)> callback);
QMetaObject::Connection requestLog(std::function<void (const std::vector<SyncthingLogEntry> &)> callback); QMetaObject::Connection requestLog(std::function<void (const std::vector<SyncthingLogEntry> &)> callback);
static const QList<QSslError> &expectedCertificateErrors(); const QList<QSslError> &expectedSslErrors();
public Q_SLOTS: public Q_SLOTS:
void loadSelfSignedCertificate(); void loadSelfSignedCertificate();
void connect(); void connect();
void disconnect(); void disconnect();
void reconnect(); void reconnect();
void reconnect(Settings::ConnectionSettings &connectionSettings);
void pause(const QString &dev); void pause(const QString &dev);
void pauseAllDevs(); void pauseAllDevs();
void resume(const QString &dev); void resume(const QString &dev);
@ -263,6 +268,7 @@ private Q_SLOTS:
void readPauseResume(); void readPauseResume();
void readRestart(); void readRestart();
void continueReconnect();
void setStatus(SyncthingStatus status); void setStatus(SyncthingStatus status);
private: private:
@ -300,7 +306,7 @@ private:
ChronoUtilities::DateTime m_lastFileTime; ChronoUtilities::DateTime m_lastFileTime;
QString m_lastFileName; QString m_lastFileName;
bool m_lastFileDeleted; bool m_lastFileDeleted;
static QList<QSslError> m_expectedCertificateErrors; QList<QSslError> m_expectedSslErrors;
}; };
/*! /*!
@ -447,9 +453,9 @@ inline const std::vector<SyncthingDev> &SyncthingConnection::devInfo() const
* \brief Returns a list of all expected certificate errors. * \brief Returns a list of all expected certificate errors.
* \remarks This list is shared by all instances and updated via loadSelfSignedCertificate(). * \remarks This list is shared by all instances and updated via loadSelfSignedCertificate().
*/ */
inline const QList<QSslError> &SyncthingConnection::expectedCertificateErrors() inline const QList<QSslError> &SyncthingConnection::expectedSslErrors()
{ {
return m_expectedCertificateErrors; return m_expectedSslErrors;
} }
} }

View File

@ -47,6 +47,12 @@
</item> </item>
<item> <item>
<widget class="QLabel" name="platformNoteLabel"> <widget class="QLabel" name="platformNoteLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="wordWrap"> <property name="wordWrap">
<bool>true</bool> <bool>true</bool>
</property> </property>

View File

@ -2,6 +2,14 @@
<ui version="4.0"> <ui version="4.0">
<class>QtGui::ConnectionOptionPage</class> <class>QtGui::ConnectionOptionPage</class>
<widget class="QWidget" name="QtGui::ConnectionOptionPage"> <widget class="QWidget" name="QtGui::ConnectionOptionPage">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>502</width>
<height>368</height>
</rect>
</property>
<property name="windowTitle"> <property name="windowTitle">
<string>Connection</string> <string>Connection</string>
</property> </property>
@ -10,30 +18,114 @@
<normaloff>.</normaloff>.</iconset> <normaloff>.</normaloff>.</iconset>
</property> </property>
<layout class="QFormLayout" name="formLayout"> <layout class="QFormLayout" name="formLayout">
<property name="horizontalSpacing">
<number>6</number>
</property>
<item row="0" column="0"> <item row="0" column="0">
<widget class="QLabel" name="instanceLabel">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Config label</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QFrame" name="selectionFrame">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="spacing">
<number>4</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QComboBox" name="selectionComboBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="editable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="addPushButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Add secondary instance</string>
</property>
<property name="icon">
<iconset theme="list-add">
<normaloff>.</normaloff>.</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="removePushButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Remove currently selected secondary instance</string>
</property>
<property name="icon">
<iconset theme="list-remove">
<normaloff>.</normaloff>.</iconset>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="urlLabel"> <widget class="QLabel" name="urlLabel">
<property name="text"> <property name="text">
<string>Syncthing URL</string> <string>Syncthing URL</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="1"> <item row="3" column="1">
<widget class="Widgets::ClearLineEdit" name="urlLineEdit"/> <widget class="Widgets::ClearLineEdit" name="urlLineEdit"/>
</item> </item>
<item row="1" column="0"> <item row="4" column="0">
<widget class="QLabel" name="authLabel"> <widget class="QLabel" name="authLabel">
<property name="text"> <property name="text">
<string>Authentication</string> <string>Authentication</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="1"> <item row="4" column="1">
<widget class="QCheckBox" name="authCheckBox"/> <widget class="QCheckBox" name="authCheckBox"/>
</item> </item>
<item row="2" column="0"> <item row="5" column="0">
<widget class="QLabel" name="userNameLabel"> <widget class="QLabel" name="userNameLabel">
<property name="enabled"> <property name="enabled">
<bool>false</bool> <bool>false</bool>
@ -43,7 +135,14 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="0"> <item row="5" column="1">
<widget class="Widgets::ClearLineEdit" name="userNameLineEdit">
<property name="enabled">
<bool>false</bool>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="passwordLabel"> <widget class="QLabel" name="passwordLabel">
<property name="enabled"> <property name="enabled">
<bool>false</bool> <bool>false</bool>
@ -53,14 +152,7 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="1"> <item row="6" column="1">
<widget class="Widgets::ClearLineEdit" name="userNameLineEdit">
<property name="enabled">
<bool>false</bool>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLineEdit" name="passwordLineEdit"> <widget class="QLineEdit" name="passwordLineEdit">
<property name="enabled"> <property name="enabled">
<bool>false</bool> <bool>false</bool>
@ -70,42 +162,17 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="11" column="1"> <item row="8" column="0">
<widget class="QLabel" name="statusLabel">
<property name="text">
<string>disconnected</string>
</property>
</widget>
</item>
<item row="11" column="0">
<widget class="QLabel" name="statusTextLabel">
<property name="text">
<string>Status</string>
</property>
</widget>
</item>
<item row="12" column="1">
<widget class="QPushButton" name="connectPushButton">
<property name="text">
<string>Apply connection settings and try to reconnect</string>
</property>
<property name="icon">
<iconset theme="view-refresh">
<normaloff>.</normaloff>.</iconset>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="Widgets::ClearLineEdit" name="apiKeyLineEdit"/>
</item>
<item row="5" column="0">
<widget class="QLabel" name="apiKeyLabel"> <widget class="QLabel" name="apiKeyLabel">
<property name="text"> <property name="text">
<string>API key</string> <string>API key</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="7" column="1"> <item row="8" column="1">
<widget class="Widgets::ClearLineEdit" name="apiKeyLineEdit"/>
</item>
<item row="11" column="1">
<widget class="QPushButton" name="insertFromConfigFilePushButton"> <widget class="QPushButton" name="insertFromConfigFilePushButton">
<property name="styleSheet"> <property name="styleSheet">
<string notr="true">font-weight: bold;</string> <string notr="true">font-weight: bold;</string>
@ -119,8 +186,8 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="10" column="1"> <item row="12" column="1">
<widget class="Line" name="line"> <widget class="Line" name="line2">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"> <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch> <horstretch>0</horstretch>
@ -132,6 +199,83 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="13" column="0">
<widget class="QLabel" name="statusTextLabel">
<property name="text">
<string>Status</string>
</property>
</widget>
</item>
<item row="13" column="1">
<widget class="QLabel" name="statusLabel">
<property name="text">
<string>disconnected</string>
</property>
</widget>
</item>
<item row="14" column="1">
<widget class="QPushButton" name="connectPushButton">
<property name="text">
<string>Apply connection settings and try to reconnect with the currently selected config</string>
</property>
<property name="icon">
<iconset theme="view-refresh">
<normaloff>.</normaloff>.</iconset>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="Line" name="line1">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="instanceNoteLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>42</height>
</size>
</property>
<property name="text">
<string>It is possible to save multiple configurations. This allows switching quickly between multiple Syncthing instances using the arrow in the right corner of the tray menu. The config label is an arbitrary name to identify a configuration and must not match the name of the corresponding Syncthing device.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="9" column="0">
<widget class="QLabel" name="certificateLabel">
<property name="text">
<string>HTTPS certificate</string>
</property>
</widget>
</item>
<item row="9" column="1">
<widget class="Widgets::PathSelection" name="certPathSelection" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
<customwidgets> <customwidgets>
@ -140,6 +284,12 @@
<extends>QLineEdit</extends> <extends>QLineEdit</extends>
<header location="global">qtutilities/widgets/clearlineedit.h</header> <header location="global">qtutilities/widgets/clearlineedit.h</header>
</customwidget> </customwidget>
<customwidget>
<class>Widgets::PathSelection</class>
<extends>QWidget</extends>
<header location="global">qtutilities/widgets/pathselection.h</header>
<container>1</container>
</customwidget>
</customwidgets> </customwidgets>
<resources/> <resources/>
<connections> <connections>

View File

@ -6,7 +6,7 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>457</width> <width>517</width>
<height>345</height> <height>345</height>
</rect> </rect>
</property> </property>
@ -36,6 +36,15 @@
<property name="leftMargin"> <property name="leftMargin">
<number>30</number> <number>30</number>
</property> </property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item row="0" column="0"> <item row="0" column="0">
<widget class="QLabel" name="syncthingPathLabel"> <widget class="QLabel" name="syncthingPathLabel">
<property name="text"> <property name="text">

View File

@ -1,6 +1,5 @@
#include "./settingsdialog.h" #include "./settingsdialog.h"
#include "../application/settings.h"
#include "../data/syncthingconnection.h" #include "../data/syncthingconnection.h"
#include "../data/syncthingconfig.h" #include "../data/syncthingconfig.h"
#include "../data/syncthingprocess.h" #include "../data/syncthingprocess.h"
@ -14,9 +13,6 @@
#include "resources/config.h" #include "resources/config.h"
#include <tagparser/mediafileinfo.h>
#include <tagparser/backuphelper.h>
#include <qtutilities/settingsdialog/optioncategory.h> #include <qtutilities/settingsdialog/optioncategory.h>
#include <qtutilities/settingsdialog/optioncategorymodel.h> #include <qtutilities/settingsdialog/optioncategorymodel.h>
#include <qtutilities/settingsdialog/qtsettings.h> #include <qtutilities/settingsdialog/qtsettings.h>
@ -45,7 +41,8 @@ namespace QtGui {
// ConnectionOptionPage // ConnectionOptionPage
ConnectionOptionPage::ConnectionOptionPage(Data::SyncthingConnection *connection, QWidget *parentWidget) : ConnectionOptionPage::ConnectionOptionPage(Data::SyncthingConnection *connection, QWidget *parentWidget) :
ConnectionOptionPageBase(parentWidget), ConnectionOptionPageBase(parentWidget),
m_connection(connection) m_connection(connection),
m_currentIndex(0)
{} {}
ConnectionOptionPage::~ConnectionOptionPage() ConnectionOptionPage::~ConnectionOptionPage()
@ -55,9 +52,15 @@ QWidget *ConnectionOptionPage::setupWidget()
{ {
auto *w = ConnectionOptionPageBase::setupWidget(); auto *w = ConnectionOptionPageBase::setupWidget();
updateConnectionStatus(); updateConnectionStatus();
ui()->certPathSelection->provideCustomFileMode(QFileDialog::ExistingFile);
ui()->certPathSelection->lineEdit()->setPlaceholderText(QCoreApplication::translate("QtGui::ConnectionOptionPage", "Auto-detected for local instance"));
QObject::connect(m_connection, &SyncthingConnection::statusChanged, bind(&ConnectionOptionPage::updateConnectionStatus, this)); QObject::connect(m_connection, &SyncthingConnection::statusChanged, bind(&ConnectionOptionPage::updateConnectionStatus, this));
QObject::connect(ui()->connectPushButton, &QPushButton::clicked, bind(&ConnectionOptionPage::applyAndReconnect, this)); QObject::connect(ui()->connectPushButton, &QPushButton::clicked, bind(&ConnectionOptionPage::applyAndReconnect, this));
QObject::connect(ui()->insertFromConfigFilePushButton, &QPushButton::clicked, bind(&ConnectionOptionPage::insertFromConfigFile, this)); QObject::connect(ui()->insertFromConfigFilePushButton, &QPushButton::clicked, bind(&ConnectionOptionPage::insertFromConfigFile, this));
QObject::connect(ui()->selectionComboBox, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged), bind(&ConnectionOptionPage::showConnectionSettings, this, _1));
QObject::connect(ui()->selectionComboBox, static_cast<void(QComboBox::*)(const QString &)>(&QComboBox::editTextChanged), bind(&ConnectionOptionPage::saveCurrentConnectionName, this, _1));
QObject::connect(ui()->addPushButton, &QPushButton::clicked, bind(&ConnectionOptionPage::addConnectionSettings, this));
QObject::connect(ui()->removePushButton, &QPushButton::clicked, bind(&ConnectionOptionPage::removeConnectionSettings, this));
return w; return w;
} }
@ -102,41 +105,114 @@ void ConnectionOptionPage::updateConnectionStatus()
} }
} }
bool ConnectionOptionPage::apply() bool ConnectionOptionPage::showConnectionSettings(int index)
{ {
if(hasBeenShown()) { bool ok = true;
syncthingUrl() = ui()->urlLineEdit->text(); if(index != m_currentIndex) {
authEnabled() = ui()->authCheckBox->isChecked(); if((ok = cacheCurrentSettings(false))) {
userName() = ui()->userNameLineEdit->text(); const ConnectionSettings &connectionSettings = (index == 0 ? m_primarySettings : m_secondarySettings[static_cast<size_t>(index - 1)]);
password() = ui()->passwordLineEdit->text(); ui()->urlLineEdit->setText(connectionSettings.syncthingUrl);
apiKey() = ui()->apiKeyLineEdit->text().toUtf8(); ui()->authCheckBox->setChecked(connectionSettings.authEnabled);
ui()->userNameLineEdit->setText(connectionSettings.userName);
ui()->passwordLineEdit->setText(connectionSettings.password);
ui()->apiKeyLineEdit->setText(connectionSettings.apiKey);
ui()->certPathSelection->lineEdit()->setText(connectionSettings.httpsCertPath);
m_currentIndex = index;
} else {
ui()->selectionComboBox->setCurrentIndex(m_currentIndex);
}
} }
return true; ui()->removePushButton->setEnabled(index);
return ok;
}
bool ConnectionOptionPage::cacheCurrentSettings(bool applying)
{
bool ok = true;
if(m_currentIndex >= 0) {
ConnectionSettings &connectionSettings = (m_currentIndex == 0 ? m_primarySettings : m_secondarySettings[static_cast<size_t>(m_currentIndex - 1)]);
connectionSettings.syncthingUrl = ui()->urlLineEdit->text();
connectionSettings.authEnabled = ui()->authCheckBox->isChecked();
connectionSettings.userName = ui()->userNameLineEdit->text();
connectionSettings.password = ui()->passwordLineEdit->text();
connectionSettings.apiKey = ui()->apiKeyLineEdit->text().toUtf8();
connectionSettings.expectedSslErrors.clear();
connectionSettings.httpsCertPath = ui()->certPathSelection->lineEdit()->text();
if(!connectionSettings.loadHttpsCert()) {
const QString errorMessage = QCoreApplication::translate("QtGui::ConnectionOptionPage", "Unable to load specified certificate \"%1\".").arg(connectionSettings.httpsCertPath);
if(!applying) {
QMessageBox::critical(widget(), QCoreApplication::applicationName(), errorMessage);
} else {
errors() << errorMessage;
}
ok = false;
}
}
return ok;
}
void ConnectionOptionPage::saveCurrentConnectionName(const QString &name)
{
const int index = ui()->selectionComboBox->currentIndex();
if(index == m_currentIndex && index >= 0) {
(index == 0 ? m_primarySettings : m_secondarySettings[static_cast<size_t>(index - 1)]).label = name;
ui()->selectionComboBox->setItemText(index, name);
}
}
void ConnectionOptionPage::addConnectionSettings()
{
m_secondarySettings.emplace_back();
m_secondarySettings.back().label = QCoreApplication::translate("QtGui::ConnectionOptionPage", "Instance %1").arg(ui()->selectionComboBox->count() + 1);
ui()->selectionComboBox->addItem(m_secondarySettings.back().label);
ui()->selectionComboBox->setCurrentIndex(ui()->selectionComboBox->count() - 1);
}
void ConnectionOptionPage::removeConnectionSettings()
{
int index = ui()->selectionComboBox->currentIndex();
if(index > 0) {
m_secondarySettings.erase(m_secondarySettings.begin() + (index - 1));
m_currentIndex = -1;
ui()->selectionComboBox->removeItem(index);
}
}
bool ConnectionOptionPage::apply()
{
bool ok = true;
if(hasBeenShown()) {
ok = cacheCurrentSettings(true);
Settings::primaryConnectionSettings() = m_primarySettings;
Settings::secondaryConnectionSettings() = m_secondarySettings;
}
return ok;
} }
void ConnectionOptionPage::reset() void ConnectionOptionPage::reset()
{ {
if(hasBeenShown()) { if(hasBeenShown()) {
ui()->urlLineEdit->setText(syncthingUrl()); m_primarySettings = primaryConnectionSettings();
ui()->authCheckBox->setChecked(authEnabled()); m_secondarySettings = secondaryConnectionSettings();
ui()->userNameLineEdit->setText(userName()); m_currentIndex = -1;
ui()->passwordLineEdit->setText(password());
ui()->apiKeyLineEdit->setText(apiKey()); QStringList itemTexts;
itemTexts.reserve(1 + static_cast<int>(m_secondarySettings.size()));
itemTexts << m_primarySettings.label;
for(const ConnectionSettings &settings : m_secondarySettings) {
itemTexts << settings.label;
}
ui()->selectionComboBox->clear();
ui()->selectionComboBox->addItems(itemTexts);
ui()->selectionComboBox->setCurrentIndex(0);
} }
} }
void ConnectionOptionPage::applyAndReconnect() void ConnectionOptionPage::applyAndReconnect()
{ {
apply(); apply();
m_connection->setSyncthingUrl(Settings::syncthingUrl()); m_connection->reconnect(primaryConnectionSettings());
m_connection->setApiKey(Settings::apiKey());
if(Settings::authEnabled()) {
m_connection->setCredentials(Settings::userName(), Settings::password());
} else {
m_connection->setCredentials(QString(), QString());
}
m_connection->reconnect();
} }
// NotificationsOptionPage // NotificationsOptionPage
@ -312,7 +388,7 @@ bool setAutostartEnabled(bool enabled)
#elif defined(PLATFORM_WINDOWS) #elif defined(PLATFORM_WINDOWS)
QSettings settings(QStringLiteral("HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run"), QSettings::NativeFormat); QSettings settings(QStringLiteral("HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run"), QSettings::NativeFormat);
if(enabled) { if(enabled) {
settings.setValue(QStringLiteral(PROJECT_NAME), QCoreApplication::applicationFilePath().replace(QChar('/'), QChar("\\"))); settings.setValue(QStringLiteral(PROJECT_NAME), QCoreApplication::applicationFilePath().replace(QChar('/'), QChar('\\')));
} else { } else {
settings.remove(QStringLiteral(PROJECT_NAME)); settings.remove(QStringLiteral(PROJECT_NAME));
} }
@ -515,7 +591,8 @@ SettingsDialog::SettingsDialog(Data::SyncthingConnection *connection, QWidget *p
categoryModel()->setCategories(categories); categoryModel()->setCategories(categories);
setMinimumSize(800, 450); setMinimumSize(800, 550);
setWindowTitle(tr("Settings") + QStringLiteral(" - " APP_NAME));
setWindowIcon(QIcon::fromTheme(QStringLiteral("preferences-other"), QIcon(QStringLiteral(":/icons/hicolor/scalable/apps/preferences-other.svg")))); setWindowIcon(QIcon::fromTheme(QStringLiteral("preferences-other"), QIcon(QStringLiteral(":/icons/hicolor/scalable/apps/preferences-other.svg"))));
// some settings could be applied without restarting the application, good idea? // some settings could be applied without restarting the application, good idea?

View File

@ -1,6 +1,8 @@
#ifndef SETTINGS_DIALOG_H #ifndef SETTINGS_DIALOG_H
#define SETTINGS_DIALOG_H #define SETTINGS_DIALOG_H
#include "../application/settings.h"
#include <qtutilities/settingsdialog/settingsdialog.h> #include <qtutilities/settingsdialog/settingsdialog.h>
#include <qtutilities/settingsdialog/optionpage.h> #include <qtutilities/settingsdialog/optionpage.h>
#include <qtutilities/settingsdialog/qtsettings.h> #include <qtutilities/settingsdialog/qtsettings.h>
@ -8,11 +10,6 @@
#include <QWidget> #include <QWidget>
#include <QProcess> #include <QProcess>
namespace Settings {
class KnownFieldModel;
class TargetLevelModel;
}
namespace Data { namespace Data {
class SyncthingConnection; class SyncthingConnection;
} }
@ -27,7 +24,15 @@ private:
void insertFromConfigFile(); void insertFromConfigFile();
void updateConnectionStatus(); void updateConnectionStatus();
void applyAndReconnect(); void applyAndReconnect();
bool showConnectionSettings(int index);
bool cacheCurrentSettings(bool applying);
void saveCurrentConnectionName(const QString &name);
void addConnectionSettings();
void removeConnectionSettings();
Data::SyncthingConnection *m_connection; Data::SyncthingConnection *m_connection;
Settings::ConnectionSettings m_primarySettings;
std::vector<Settings::ConnectionSettings> m_secondarySettings;
int m_currentIndex;
END_DECLARE_OPTION_PAGE END_DECLARE_OPTION_PAGE
DECLARE_UI_FILE_BASED_OPTION_PAGE(NotificationsOptionPage) DECLARE_UI_FILE_BASED_OPTION_PAGE(NotificationsOptionPage)

View File

@ -33,6 +33,7 @@ TrayIcon::TrayIcon(QObject *parent) :
// set context menu // set context menu
connect(m_contextMenu.addAction(QIcon::fromTheme(QStringLiteral("internet-web-browser"), QIcon(QStringLiteral(":/icons/hicolor/scalable/apps/internet-web-browser.svg"))), tr("Web UI")), &QAction::triggered, m_trayMenu.widget(), &TrayWidget::showWebUi); connect(m_contextMenu.addAction(QIcon::fromTheme(QStringLiteral("internet-web-browser"), QIcon(QStringLiteral(":/icons/hicolor/scalable/apps/internet-web-browser.svg"))), tr("Web UI")), &QAction::triggered, m_trayMenu.widget(), &TrayWidget::showWebUi);
connect(m_contextMenu.addAction(QIcon::fromTheme(QStringLiteral("preferences-other"), QIcon(QStringLiteral(":/icons/hicolor/scalable/apps/preferences-other.svg"))), tr("Settings")), &QAction::triggered, m_trayMenu.widget(), &TrayWidget::showSettingsDialog); connect(m_contextMenu.addAction(QIcon::fromTheme(QStringLiteral("preferences-other"), QIcon(QStringLiteral(":/icons/hicolor/scalable/apps/preferences-other.svg"))), tr("Settings")), &QAction::triggered, m_trayMenu.widget(), &TrayWidget::showSettingsDialog);
m_contextMenu.addMenu(m_trayMenu.widget()->connectionsMenu());
connect(m_contextMenu.addAction(QIcon::fromTheme(QStringLiteral("help-about"), QIcon(QStringLiteral(":/icons/hicolor/scalable/apps/help-about.svg"))), tr("About")), &QAction::triggered, m_trayMenu.widget(), &TrayWidget::showAboutDialog); connect(m_contextMenu.addAction(QIcon::fromTheme(QStringLiteral("help-about"), QIcon(QStringLiteral(":/icons/hicolor/scalable/apps/help-about.svg"))), tr("About")), &QAction::triggered, m_trayMenu.widget(), &TrayWidget::showAboutDialog);
m_contextMenu.addSeparator(); m_contextMenu.addSeparator();
connect(m_contextMenu.addAction(QIcon::fromTheme(QStringLiteral("window-close"), QIcon(QStringLiteral(":/icons/hicolor/scalable/actions/window-close.svg"))), tr("Close")), &QAction::triggered, &QCoreApplication::quit); connect(m_contextMenu.addAction(QIcon::fromTheme(QStringLiteral("window-close"), QIcon(QStringLiteral(":/icons/hicolor/scalable/actions/window-close.svg"))), tr("Close")), &QAction::triggered, &QCoreApplication::quit);

View File

@ -49,7 +49,8 @@ TrayWidget::TrayWidget(TrayMenu *parent) :
m_webViewDlg(nullptr), m_webViewDlg(nullptr),
#endif #endif
m_dirModel(m_connection), m_dirModel(m_connection),
m_devModel(m_connection) m_devModel(m_connection),
m_selectedConnection(nullptr)
{ {
m_ui->setupUi(this); m_ui->setupUi(this);
@ -87,6 +88,11 @@ TrayWidget::TrayWidget(TrayMenu *parent) :
cornerFrameLayout->addWidget(scanAllButton); cornerFrameLayout->addWidget(scanAllButton);
m_ui->tabWidget->setCornerWidget(m_cornerFrame, Qt::BottomRightCorner); m_ui->tabWidget->setCornerWidget(m_cornerFrame, Qt::BottomRightCorner);
// setup connection menu
m_connectionsActionGroup = new QActionGroup(m_connectionsMenu = new QMenu(tr("Connection"), this));
m_connectionsMenu->setIcon(QIcon::fromTheme(QStringLiteral("network-connect"), QIcon(QStringLiteral(":/icons/hicolor/scalable/actions/network-connect.svg"))));
connect(m_ui->connectionsPushButton, &QPushButton::clicked, this, &TrayWidget::showConnectionsMenu);
// apply settings, this also establishes the connection to Syncthing // apply settings, this also establishes the connection to Syncthing
applySettings(); applySettings();
@ -106,6 +112,7 @@ TrayWidget::TrayWidget(TrayMenu *parent) :
connect(m_ui->devsTreeView, &DevView::pauseResumeDev, this, &TrayWidget::pauseResumeDev); connect(m_ui->devsTreeView, &DevView::pauseResumeDev, this, &TrayWidget::pauseResumeDev);
connect(scanAllButton, &QPushButton::clicked, &m_connection, &SyncthingConnection::rescanAllDirs); connect(scanAllButton, &QPushButton::clicked, &m_connection, &SyncthingConnection::rescanAllDirs);
connect(viewIdButton, &QPushButton::clicked, this, &TrayWidget::showOwnDeviceId); connect(viewIdButton, &QPushButton::clicked, this, &TrayWidget::showOwnDeviceId);
connect(m_connectionsActionGroup, &QActionGroup::triggered, this, &TrayWidget::handleConnectionSelected);
} }
TrayWidget::~TrayWidget() TrayWidget::~TrayWidget()
@ -115,13 +122,7 @@ void TrayWidget::showSettingsDialog()
{ {
if(!m_settingsDlg) { if(!m_settingsDlg) {
m_settingsDlg = new SettingsDialog(&m_connection, this); m_settingsDlg = new SettingsDialog(&m_connection, this);
m_settingsDlg->setWindowTitle(tr("Settings") + QStringLiteral(" - " APP_NAME));
connect(m_settingsDlg, &SettingsDialog::applied, this, &TrayWidget::applySettings); connect(m_settingsDlg, &SettingsDialog::applied, this, &TrayWidget::applySettings);
#ifndef SYNCTHINGTRAY_NO_WEBVIEW
if(m_webViewDlg) {
connect(m_settingsDlg, &SettingsDialog::applied, m_webViewDlg, &WebViewDialog::applySettings);
}
#endif
} }
m_settingsDlg->show(); m_settingsDlg->show();
centerWidget(m_settingsDlg); centerWidget(m_settingsDlg);
@ -151,15 +152,15 @@ void TrayWidget::showWebUi()
#ifndef SYNCTHINGTRAY_NO_WEBVIEW #ifndef SYNCTHINGTRAY_NO_WEBVIEW
if(Settings::webViewDisabled()) { if(Settings::webViewDisabled()) {
#endif #endif
QDesktopServices::openUrl(Settings::syncthingUrl()); QDesktopServices::openUrl(m_connection.syncthingUrl());
#ifndef SYNCTHINGTRAY_NO_WEBVIEW #ifndef SYNCTHINGTRAY_NO_WEBVIEW
} else { } else {
if(!m_webViewDlg) { if(!m_webViewDlg) {
m_webViewDlg = new WebViewDialog(this); m_webViewDlg = new WebViewDialog(this);
connect(m_webViewDlg, &WebViewDialog::destroyed, this, &TrayWidget::handleWebViewDeleted); if(m_selectedConnection) {
if(m_settingsDlg) { m_webViewDlg->applySettings(*m_selectedConnection);
connect(m_settingsDlg, &SettingsDialog::applied, m_webViewDlg, &WebViewDialog::applySettings);
} }
connect(m_webViewDlg, &WebViewDialog::destroyed, this, &TrayWidget::handleWebViewDeleted);
} }
m_webViewDlg->show(); m_webViewDlg->show();
if(m_menu) { if(m_menu) {
@ -263,16 +264,44 @@ void TrayWidget::updateStatusButton(SyncthingStatus status)
void TrayWidget::applySettings() void TrayWidget::applySettings()
{ {
m_connection.setSyncthingUrl(Settings::syncthingUrl()); // update connections menu
m_connection.setApiKey(Settings::apiKey()); int connectionIndex = 0;
if(Settings::authEnabled()) { const int connectionCount = static_cast<int>(1 + Settings::secondaryConnectionSettings().size());
m_connection.setCredentials(Settings::userName(), Settings::password()); const QList<QAction *> connectionActions = m_connectionsActionGroup->actions();
} else { m_selectedConnection = nullptr;
m_connection.setCredentials(QString(), QString()); for(; connectionIndex < connectionCount; ++connectionIndex) {
Settings::ConnectionSettings &connectionSettings = (connectionIndex == 0 ? Settings::primaryConnectionSettings() : Settings::secondaryConnectionSettings()[static_cast<size_t>(connectionIndex - 1)]);
if(connectionIndex < connectionActions.size()) {
QAction *action = connectionActions.at(connectionIndex);
action->setText(connectionSettings.label);
if(action->isChecked()) {
m_selectedConnection = &connectionSettings;
}
} else {
QAction *action = m_connectionsMenu->addAction(connectionSettings.label);
action->setCheckable(true);
m_connectionsActionGroup->addAction(action);
}
} }
m_connection.loadSelfSignedCertificate(); for(; connectionIndex < connectionActions.size(); ++connectionIndex) {
m_connection.reconnect(); m_connectionsActionGroup->removeAction(connectionActions.at(connectionIndex));
m_ui->trafficFrame->setVisible(Settings::showTraffic()); }
if(!m_selectedConnection) {
m_selectedConnection = &Settings::primaryConnectionSettings();
m_connectionsMenu->actions().at(0)->setChecked(true);
}
m_connection.reconnect(*m_selectedConnection);
// web view
#ifndef SYNCTHINGTRAY_NO_WEBVIEW
if(m_webViewDlg) {
m_webViewDlg->applySettings(*m_selectedConnection);
}
#endif
// update visual appearance
m_ui->trafficFormWidget->setVisible(Settings::showTraffic());
if(Settings::showTraffic()) { if(Settings::showTraffic()) {
updateTraffic(); updateTraffic();
} }
@ -354,14 +383,37 @@ void TrayWidget::updateTraffic()
} }
#ifndef SYNCTHINGTRAY_NO_WEBVIEW
void TrayWidget::handleWebViewDeleted() void TrayWidget::handleWebViewDeleted()
{ {
m_webViewDlg = nullptr; m_webViewDlg = nullptr;
} }
#endif
void TrayWidget::handleNewNotification(const QString &msg) void TrayWidget::handleNewNotification(const QString &msg)
{ {
// FIXME // FIXME
} }
void TrayWidget::handleConnectionSelected(QAction *connectionAction)
{
int index = m_connectionsMenu->actions().indexOf(connectionAction);
if(index >= 0) {
m_selectedConnection = (index == 0)
? &Settings::primaryConnectionSettings()
: &Settings::secondaryConnectionSettings()[static_cast<size_t>(index - 1)];
m_connection.reconnect(*m_selectedConnection);
#ifndef SYNCTHINGTRAY_NO_WEBVIEW
if(m_webViewDlg) {
m_webViewDlg->applySettings(*m_selectedConnection);
}
#endif
}
}
void TrayWidget::showConnectionsMenu()
{
m_connectionsMenu->exec(QCursor::pos());
}
} }

View File

@ -7,12 +7,15 @@
#include "../data/syncthingdirectorymodel.h" #include "../data/syncthingdirectorymodel.h"
#include "../data/syncthingdevicemodel.h" #include "../data/syncthingdevicemodel.h"
#include "../data/syncthingprocess.h" #include "../data/syncthingprocess.h"
#include "../application/settings.h"
#include <QWidget> #include <QWidget>
#include <memory> #include <memory>
QT_FORWARD_DECLARE_CLASS(QFrame) QT_FORWARD_DECLARE_CLASS(QFrame)
QT_FORWARD_DECLARE_CLASS(QMenu)
QT_FORWARD_DECLARE_CLASS(QActionGroup)
namespace ApplicationUtilities { namespace ApplicationUtilities {
class QtConfigArguments; class QtConfigArguments;
@ -41,6 +44,7 @@ public:
~TrayWidget(); ~TrayWidget();
Data::SyncthingConnection &connection(); Data::SyncthingConnection &connection();
QMenu *connectionsMenu();
public slots: public slots:
void showSettingsDialog(); void showSettingsDialog();
@ -57,8 +61,12 @@ private slots:
void pauseResumeDev(const QModelIndex &devIndex); void pauseResumeDev(const QModelIndex &devIndex);
void changeStatus(); void changeStatus();
void updateTraffic(); void updateTraffic();
#ifndef SYNCTHINGTRAY_NO_WEBVIEW
void handleWebViewDeleted(); void handleWebViewDeleted();
#endif
void handleNewNotification(const QString &msg); void handleNewNotification(const QString &msg);
void handleConnectionSelected(QAction *connectionAction);
void showConnectionsMenu();
private: private:
TrayMenu *m_menu; TrayMenu *m_menu;
@ -72,6 +80,9 @@ private:
Data::SyncthingConnection m_connection; Data::SyncthingConnection m_connection;
Data::SyncthingDirectoryModel m_dirModel; Data::SyncthingDirectoryModel m_dirModel;
Data::SyncthingDeviceModel m_devModel; Data::SyncthingDeviceModel m_devModel;
QMenu *m_connectionsMenu;
QActionGroup *m_connectionsActionGroup;
Settings::ConnectionSettings *m_selectedConnection;
}; };
inline Data::SyncthingConnection &TrayWidget::connection() inline Data::SyncthingConnection &TrayWidget::connection()
@ -79,6 +90,11 @@ inline Data::SyncthingConnection &TrayWidget::connection()
return m_connection; return m_connection;
} }
inline QMenu *TrayWidget::connectionsMenu()
{
return m_connectionsMenu;
}
} }
#endif // TRAY_WIDGET_H #endif // TRAY_WIDGET_H

View File

@ -178,7 +178,7 @@
<number>0</number> <number>0</number>
</property> </property>
<property name="rightMargin"> <property name="rightMargin">
<number>3</number> <number>0</number>
</property> </property>
<property name="bottomMargin"> <property name="bottomMargin">
<number>0</number> <number>0</number>
@ -254,6 +254,22 @@
</layout> </layout>
</widget> </widget>
</item> </item>
<item>
<widget class="QPushButton" name="connectionsPushButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="icon">
<iconset theme="network-connect"/>
</property>
<property name="flat">
<bool>true</bool>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>

View File

@ -1,5 +1,6 @@
#ifndef SYNCTHINGTRAY_NO_WEBVIEW #ifndef SYNCTHINGTRAY_NO_WEBVIEW
#include "./webpage.h" #include "./webpage.h"
#include "./webviewdialog.h"
#include "../application/settings.h" #include "../application/settings.h"
#include "../data/syncthingconnection.h" #include "../data/syncthingconnection.h"
@ -25,8 +26,9 @@ using namespace Data;
namespace QtGui { namespace QtGui {
WebPage::WebPage(WEB_VIEW_PROVIDER *view) : WebPage::WebPage(WebViewDialog *dlg, WEB_VIEW_PROVIDER *view) :
WEB_PAGE_PROVIDER(view), WEB_PAGE_PROVIDER(view),
m_dlg(dlg),
m_view(view) m_view(view)
{ {
#ifdef SYNCTHINGTRAY_USE_WEBENGINE #ifdef SYNCTHINGTRAY_USE_WEBENGINE
@ -52,6 +54,7 @@ WebPage::WebPage(WEB_VIEW_PROVIDER *view) :
WEB_PAGE_PROVIDER *WebPage::createWindow(WEB_PAGE_PROVIDER::WebWindowType type) WEB_PAGE_PROVIDER *WebPage::createWindow(WEB_PAGE_PROVIDER::WebWindowType type)
{ {
Q_UNUSED(type)
return new WebPage; return new WebPage;
} }
@ -92,17 +95,18 @@ void WebPage::supplyCredentials(QNetworkReply *reply, QAuthenticator *authentica
void WebPage::supplyCredentials(QAuthenticator *authenticator) void WebPage::supplyCredentials(QAuthenticator *authenticator)
{ {
if(Settings::authEnabled()) { if(m_dlg && m_dlg->settings().authEnabled) {
authenticator->setUser(Settings::userName()); authenticator->setUser(m_dlg->settings().userName);
authenticator->setPassword(Settings::password()); authenticator->setPassword(m_dlg->settings().password);
} }
} }
#ifdef SYNCTHINGTRAY_USE_WEBKIT #ifdef SYNCTHINGTRAY_USE_WEBKIT
void WebPage::handleSslErrors(QNetworkReply *reply, const QList<QSslError> &errors) void WebPage::handleSslErrors(QNetworkReply *reply, const QList<QSslError> &errors)
{ {
if(reply->request().url().host() == m_view->url().host()) { Q_UNUSED(errors)
reply->ignoreSslErrors(SyncthingConnection::expectedCertificateErrors()); if(m_dlg && reply->request().url().host() == m_view->url().host()) {
reply->ignoreSslErrors(m_dlg->settings().expectedSslErrors);
} }
} }
#endif #endif

View File

@ -17,11 +17,13 @@ QT_FORWARD_DECLARE_CLASS(QSslError)
namespace QtGui { namespace QtGui {
class WebViewDialog;
class WebPage : public WEB_PAGE_PROVIDER class WebPage : public WEB_PAGE_PROVIDER
{ {
Q_OBJECT Q_OBJECT
public: public:
WebPage(WEB_VIEW_PROVIDER *view = nullptr); WebPage(WebViewDialog *dlg = nullptr, WEB_VIEW_PROVIDER *view = nullptr);
protected: protected:
WEB_PAGE_PROVIDER *createWindow(WebWindowType type); WEB_PAGE_PROVIDER *createWindow(WebWindowType type);
@ -39,6 +41,7 @@ private slots:
#endif #endif
private: private:
WebViewDialog *m_dlg;
WEB_VIEW_PROVIDER *m_view; WEB_VIEW_PROVIDER *m_view;
}; };

View File

@ -26,10 +26,8 @@ WebViewDialog::WebViewDialog(QWidget *parent) :
setWindowIcon(QIcon(QStringLiteral(":/icons/hicolor/scalable/app/syncthingtray.svg"))); setWindowIcon(QIcon(QStringLiteral(":/icons/hicolor/scalable/app/syncthingtray.svg")));
setCentralWidget(m_view); setCentralWidget(m_view);
m_view->setPage(new WebPage(m_view)); m_view->setPage(new WebPage(this, m_view));
connect(m_view, &WEB_VIEW_PROVIDER::titleChanged, this, &WebViewDialog::setWindowTitle);
applySettings();
if(Settings::webViewGeometry().isEmpty()) { if(Settings::webViewGeometry().isEmpty()) {
resize(1200, 800); resize(1200, 800);
@ -44,9 +42,10 @@ QtGui::WebViewDialog::~WebViewDialog()
Settings::webViewGeometry() = saveGeometry(); Settings::webViewGeometry() = saveGeometry();
} }
void QtGui::WebViewDialog::applySettings() void QtGui::WebViewDialog::applySettings(const Settings::ConnectionSettings &connectionSettings)
{ {
m_view->setUrl(Settings::syncthingUrl()); m_settings = connectionSettings;
m_view->setUrl(connectionSettings.syncthingUrl);
m_view->setZoomFactor(Settings::webViewZoomFactor()); m_view->setZoomFactor(Settings::webViewZoomFactor());
} }

View File

@ -4,10 +4,16 @@
#include "./webviewprovider.h" #include "./webviewprovider.h"
#include "../application/settings.h"
#include <QMainWindow> #include <QMainWindow>
QT_FORWARD_DECLARE_CLASS(WEB_VIEW_PROVIDER) QT_FORWARD_DECLARE_CLASS(WEB_VIEW_PROVIDER)
namespace Settings {
struct ConnectionSettings;
}
namespace QtGui { namespace QtGui {
class WebViewDialog : public QMainWindow class WebViewDialog : public QMainWindow
@ -18,15 +24,22 @@ public:
~WebViewDialog(); ~WebViewDialog();
public slots: public slots:
void applySettings(); void applySettings(const Settings::ConnectionSettings &connectionSettings);
const Settings::ConnectionSettings &settings() const;
protected: protected:
void closeEvent(QCloseEvent *event); void closeEvent(QCloseEvent *event);
private: private:
WEB_VIEW_PROVIDER *m_view; WEB_VIEW_PROVIDER *m_view;
Settings::ConnectionSettings m_settings;
}; };
inline const Settings::ConnectionSettings &WebViewDialog::settings() const
{
return m_settings;
}
} }
#endif // SYNCTHINGTRAY_NO_WEBVIEW #endif // SYNCTHINGTRAY_NO_WEBVIEW

View File

@ -26,5 +26,6 @@
<file>icons/hicolor/scalable/places/folder.svg</file> <file>icons/hicolor/scalable/places/folder.svg</file>
<file>icons/hicolor/scalable/places/network-workgroup.svg</file> <file>icons/hicolor/scalable/places/network-workgroup.svg</file>
<file>icons/hicolor/scalable/apps/system-run.svg</file> <file>icons/hicolor/scalable/apps/system-run.svg</file>
<file>icons/hicolor/scalable/actions/network-connect.svg</file>
</qresource> </qresource>
</RCC> </RCC>

View File

@ -0,0 +1,13 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
<defs id="defs3051">
<style type="text/css" id="current-color-scheme">
.ColorScheme-Text {
color:#4d4d4d;
}
</style>
</defs>
<path style="fill:currentColor;fill-opacity:1;stroke:none"
d="M 13.300781 2 L 10.650391 4.6503906 L 9.5859375 3.5859375 L 3.5859375 9.5859375 L 4.6503906 10.650391 L 2 13.300781 L 2.6992188 14 L 5.3496094 11.349609 L 6.4140625 12.414062 L 12.414062 6.4140625 L 11.349609 5.3496094 L 14 2.6992188 L 13.300781 2 z "
class="ColorScheme-Text"
/>
</svg>

After

Width:  |  Height:  |  Size: 586 B

View File

@ -34,94 +34,100 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="459"/> <location filename="../data/syncthingconnection.cpp" line="169"/>
<location filename="../data/syncthingconnection.cpp" line="248"/>
<source>Connection configuration is insufficient.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../data/syncthingconnection.cpp" line="517"/>
<source>Unable to parse Syncthing log: </source> <source>Unable to parse Syncthing log: </source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="463"/> <location filename="../data/syncthingconnection.cpp" line="521"/>
<source>Unable to request system log: </source> <source>Unable to request system log: </source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="484"/> <location filename="../data/syncthingconnection.cpp" line="543"/>
<source>Unable to locate certificate used by Syncthing GUI.</source> <source>Unable to locate certificate used by Syncthing GUI.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="490"/> <location filename="../data/syncthingconnection.cpp" line="549"/>
<source>Unable to load certificate used by Syncthing GUI.</source> <source>Unable to load certificate used by Syncthing GUI.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="522"/> <location filename="../data/syncthingconnection.cpp" line="582"/>
<location filename="../data/syncthingconnection.cpp" line="622"/> <location filename="../data/syncthingconnection.cpp" line="682"/>
<source>Unable to parse Syncthing config: </source> <source>Unable to parse Syncthing config: </source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="527"/> <location filename="../data/syncthingconnection.cpp" line="587"/>
<location filename="../data/syncthingconnection.cpp" line="627"/> <location filename="../data/syncthingconnection.cpp" line="687"/>
<source>Unable to request Syncthing config: </source> <source>Unable to request Syncthing config: </source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="702"/> <location filename="../data/syncthingconnection.cpp" line="762"/>
<source>Unable to parse connections: </source> <source>Unable to parse connections: </source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="707"/> <location filename="../data/syncthingconnection.cpp" line="767"/>
<source>Unable to request connections: </source> <source>Unable to request connections: </source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="762"/> <location filename="../data/syncthingconnection.cpp" line="822"/>
<source>Unable to parse directory statistics: </source> <source>Unable to parse directory statistics: </source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="767"/> <location filename="../data/syncthingconnection.cpp" line="827"/>
<source>Unable to request directory statistics: </source> <source>Unable to request directory statistics: </source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="804"/> <location filename="../data/syncthingconnection.cpp" line="864"/>
<source>Unable to parse device statistics: </source> <source>Unable to parse device statistics: </source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="809"/> <location filename="../data/syncthingconnection.cpp" line="869"/>
<source>Unable to request device statistics: </source> <source>Unable to request device statistics: </source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="860"/> <location filename="../data/syncthingconnection.cpp" line="920"/>
<source>Unable to parse Syncthing events: </source> <source>Unable to parse Syncthing events: </source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="882"/> <location filename="../data/syncthingconnection.cpp" line="938"/>
<source>Unable to request Syncthing events: </source> <source>Unable to request Syncthing events: </source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="1094"/> <location filename="../data/syncthingconnection.cpp" line="1150"/>
<source>Unable to request rescan: </source> <source>Unable to request rescan: </source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="1109"/> <location filename="../data/syncthingconnection.cpp" line="1165"/>
<source>Unable to request pause/resume: </source> <source>Unable to request pause/resume: </source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="1124"/> <location filename="../data/syncthingconnection.cpp" line="1180"/>
<source>Unable to request restart: </source> <source>Unable to request restart: </source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="427"/> <location filename="../data/syncthingconnection.cpp" line="485"/>
<source>Unable to request QR-Code: </source> <source>Unable to request QR-Code: </source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -444,22 +450,22 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/settingsdialog.cpp" line="238"/> <location filename="../gui/settingsdialog.cpp" line="314"/>
<source>This is achieved by adding a *.desktop file under &lt;i&gt;~/.config/autostart&lt;/i&gt; so the setting only affects the current user.</source> <source>This is achieved by adding a *.desktop file under &lt;i&gt;~/.config/autostart&lt;/i&gt; so the setting only affects the current user.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/settingsdialog.cpp" line="240"/> <location filename="../gui/settingsdialog.cpp" line="316"/>
<source>This is achieved by adding a registry key under &lt;i&gt;HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Run&lt;/i&gt; so the setting only affects the current user. Note that the startup entry is invalidated when moving &lt;i&gt;syncthingtray.exe&lt;/i&gt;.</source> <source>This is achieved by adding a registry key under &lt;i&gt;HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Run&lt;/i&gt; so the setting only affects the current user. Note that the startup entry is invalidated when moving &lt;i&gt;syncthingtray.exe&lt;/i&gt;.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/settingsdialog.cpp" line="242"/> <location filename="../gui/settingsdialog.cpp" line="318"/>
<source>This feature has not been implemented for your platform (yet).</source> <source>This feature has not been implemented for your platform (yet).</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/settingsdialog.cpp" line="329"/> <location filename="../gui/settingsdialog.cpp" line="405"/>
<source>unable to modify startup entry</source> <source>unable to modify startup entry</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -467,65 +473,105 @@
<context> <context>
<name>QtGui::ConnectionOptionPage</name> <name>QtGui::ConnectionOptionPage</name>
<message> <message>
<location filename="../gui/connectionoptionpage.ui" line="6"/> <location filename="../gui/connectionoptionpage.ui" line="14"/>
<source>Connection</source> <source>Connection</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/connectionoptionpage.ui" line="19"/> <location filename="../gui/connectionoptionpage.ui" line="30"/>
<source>Config label</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/connectionoptionpage.ui" line="80"/>
<source>Add secondary instance</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/connectionoptionpage.ui" line="97"/>
<source>Remove currently selected secondary instance</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/connectionoptionpage.ui" line="111"/>
<source>Syncthing URL</source> <source>Syncthing URL</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/connectionoptionpage.ui" line="29"/> <location filename="../gui/connectionoptionpage.ui" line="121"/>
<source>Authentication</source> <source>Authentication</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/connectionoptionpage.ui" line="42"/> <location filename="../gui/connectionoptionpage.ui" line="134"/>
<source>User</source> <source>User</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/connectionoptionpage.ui" line="76"/> <location filename="../gui/connectionoptionpage.ui" line="212"/>
<source>disconnected</source> <source>disconnected</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/connectionoptionpage.ui" line="83"/> <location filename="../gui/connectionoptionpage.ui" line="219"/>
<source>Apply connection settings and try to reconnect with the currently selected config</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/connectionoptionpage.ui" line="255"/>
<source>It is possible to save multiple configurations. This allows switching quickly between multiple Syncthing instances using the arrow in the right corner of the tray menu. The config label is an arbitrary name to identify a configuration and must not match the name of the corresponding Syncthing device.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/connectionoptionpage.ui" line="265"/>
<source>HTTPS certificate</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/connectionoptionpage.ui" line="205"/>
<source>Status</source> <source>Status</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/connectionoptionpage.ui" line="90"/> <location filename="../gui/connectionoptionpage.ui" line="168"/>
<source>Apply connection settings and try to reconnect</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/connectionoptionpage.ui" line="104"/>
<source>API key</source> <source>API key</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/connectionoptionpage.ui" line="114"/> <location filename="../gui/connectionoptionpage.ui" line="181"/>
<source>Insert values from local Syncthing configuration</source> <source>Insert values from local Syncthing configuration</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/connectionoptionpage.ui" line="52"/> <location filename="../gui/connectionoptionpage.ui" line="151"/>
<source>Password</source> <source>Password</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/settingsdialog.cpp" line="70"/> <location filename="../gui/settingsdialog.cpp" line="56"/>
<source>Auto-detected for local instance</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/settingsdialog.cpp" line="73"/>
<source>Select Syncthing config file</source> <source>Select Syncthing config file</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/settingsdialog.cpp" line="77"/> <location filename="../gui/settingsdialog.cpp" line="80"/>
<source>Unable to parse the Syncthing config file.</source> <source>Unable to parse the Syncthing config file.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<location filename="../gui/settingsdialog.cpp" line="143"/>
<source>Unable to load specified certificate &quot;%1&quot;.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/settingsdialog.cpp" line="167"/>
<source>Instance %1</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>QtGui::DevView</name> <name>QtGui::DevView</name>
@ -576,48 +622,48 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/launcheroptionpage.ui" line="42"/> <location filename="../gui/launcheroptionpage.ui" line="51"/>
<source>Syncthing executable</source> <source>Syncthing executable</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/launcheroptionpage.ui" line="52"/> <location filename="../gui/launcheroptionpage.ui" line="61"/>
<source>Arguments</source> <source>Arguments</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/launcheroptionpage.ui" line="86"/> <location filename="../gui/launcheroptionpage.ui" line="95"/>
<source>Syncthing log (stdout/stderr)</source> <source>Syncthing log (interleaved stdout/stderr)</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/launcheroptionpage.ui" line="102"/> <location filename="../gui/launcheroptionpage.ui" line="111"/>
<source>Apply and launch now</source> <source>Apply and launch now</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/launcheroptionpage.ui" line="119"/> <location filename="../gui/launcheroptionpage.ui" line="128"/>
<source>Stop launched instance</source> <source>Stop launched instance</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/launcheroptionpage.ui" line="138"/> <location filename="../gui/launcheroptionpage.ui" line="147"/>
<source>No log messages available yet</source> <source>No log messages available yet</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/launcheroptionpage.ui" line="145"/> <location filename="../gui/launcheroptionpage.ui" line="154"/>
<source>Ensure latest log is visible</source> <source>Ensure latest log is visible</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/settingsdialog.cpp" line="409"/> <location filename="../gui/settingsdialog.cpp" line="485"/>
<source>Syncthing existed with exit code %1 <source>Syncthing existed with exit code %1
</source> </source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/settingsdialog.cpp" line="412"/> <location filename="../gui/settingsdialog.cpp" line="488"/>
<source>Syncthing crashed with exit code %1 <source>Syncthing crashed with exit code %1
</source> </source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
@ -659,17 +705,22 @@
<context> <context>
<name>QtGui::SettingsDialog</name> <name>QtGui::SettingsDialog</name>
<message> <message>
<location filename="../gui/settingsdialog.cpp" line="497"/> <location filename="../gui/settingsdialog.cpp" line="573"/>
<source>Tray</source> <source>Tray</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/settingsdialog.cpp" line="509"/> <location filename="../gui/settingsdialog.cpp" line="585"/>
<source>Startup</source> <source>Startup</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/settingsdialog.cpp" line="503"/> <location filename="../gui/settingsdialog.cpp" line="595"/>
<source>Settings</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/settingsdialog.cpp" line="579"/>
<source>Web view</source> <source>Web view</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -687,62 +738,62 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/trayicon.cpp" line="36"/> <location filename="../gui/trayicon.cpp" line="37"/>
<source>About</source> <source>About</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/trayicon.cpp" line="38"/> <location filename="../gui/trayicon.cpp" line="39"/>
<source>Close</source> <source>Close</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/trayicon.cpp" line="77"/> <location filename="../gui/trayicon.cpp" line="78"/>
<source>Error</source> <source>Error</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/trayicon.cpp" line="84"/> <location filename="../gui/trayicon.cpp" line="85"/>
<source>Syncthing notification</source> <source>Syncthing notification</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/trayicon.cpp" line="93"/> <location filename="../gui/trayicon.cpp" line="94"/>
<source>Not connected to Syncthing</source> <source>Not connected to Syncthing</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/trayicon.cpp" line="95"/> <location filename="../gui/trayicon.cpp" line="96"/>
<source>Disconnected from Syncthing</source> <source>Disconnected from Syncthing</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/trayicon.cpp" line="100"/> <location filename="../gui/trayicon.cpp" line="101"/>
<source>Syncthing is idling</source> <source>Syncthing is idling</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/trayicon.cpp" line="104"/> <location filename="../gui/trayicon.cpp" line="105"/>
<source>Syncthing is scanning</source> <source>Syncthing is scanning</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/trayicon.cpp" line="108"/> <location filename="../gui/trayicon.cpp" line="109"/>
<source>Notifications available</source> <source>Notifications available</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/trayicon.cpp" line="112"/> <location filename="../gui/trayicon.cpp" line="113"/>
<source>At least one device is paused</source> <source>At least one device is paused</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/trayicon.cpp" line="116"/> <location filename="../gui/trayicon.cpp" line="117"/>
<source>Synchronization is ongoing</source> <source>Synchronization is ongoing</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/trayicon.cpp" line="125"/> <location filename="../gui/trayicon.cpp" line="126"/>
<source>Synchronization complete</source> <source>Synchronization complete</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -756,7 +807,7 @@
</message> </message>
<message> <message>
<location filename="../gui/traywidget.ui" line="107"/> <location filename="../gui/traywidget.ui" line="107"/>
<location filename="../gui/traywidget.cpp" line="244"/> <location filename="../gui/traywidget.cpp" line="245"/>
<source>Connect</source> <source>Connect</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -783,8 +834,8 @@
<message> <message>
<location filename="../gui/traywidget.ui" line="230"/> <location filename="../gui/traywidget.ui" line="230"/>
<location filename="../gui/traywidget.ui" line="250"/> <location filename="../gui/traywidget.ui" line="250"/>
<location filename="../gui/traywidget.cpp" line="345"/> <location filename="../gui/traywidget.cpp" line="374"/>
<location filename="../gui/traywidget.cpp" line="352"/> <location filename="../gui/traywidget.cpp" line="381"/>
<source>unknown</source> <source>unknown</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -799,24 +850,23 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.ui" line="280"/> <location filename="../gui/traywidget.ui" line="296"/>
<source>Directories</source> <source>Directories</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.ui" line="309"/> <location filename="../gui/traywidget.ui" line="325"/>
<source>Devices</source> <source>Devices</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.ui" line="80"/> <location filename="../gui/traywidget.ui" line="80"/>
<location filename="../gui/traywidget.cpp" line="138"/> <location filename="../gui/traywidget.cpp" line="139"/>
<source>About</source> <source>About</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.ui" line="134"/> <location filename="../gui/traywidget.ui" line="134"/>
<location filename="../gui/traywidget.cpp" line="118"/>
<source>Settings</source> <source>Settings</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -826,72 +876,77 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.cpp" line="67"/> <location filename="../gui/traywidget.cpp" line="68"/>
<source>View own device ID</source> <source>View own device ID</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.cpp" line="84"/> <location filename="../gui/traywidget.cpp" line="85"/>
<source>Rescan all directories</source> <source>Rescan all directories</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.cpp" line="78"/> <location filename="../gui/traywidget.cpp" line="79"/>
<source>Show Syncthing log</source> <source>Show Syncthing log</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.cpp" line="72"/> <location filename="../gui/traywidget.cpp" line="73"/>
<source>Restart Syncthing</source> <source>Restart Syncthing</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.cpp" line="186"/> <location filename="../gui/traywidget.cpp" line="92"/>
<source>Connection</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/traywidget.cpp" line="187"/>
<source>device ID is unknown</source> <source>device ID is unknown</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.cpp" line="194"/> <location filename="../gui/traywidget.cpp" line="195"/>
<source>Copy to clipboard</source> <source>Copy to clipboard</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.cpp" line="245"/> <location filename="../gui/traywidget.cpp" line="246"/>
<source>Not connected to Syncthing, click to connect</source> <source>Not connected to Syncthing, click to connect</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.cpp" line="252"/> <location filename="../gui/traywidget.cpp" line="253"/>
<source>Pause</source> <source>Pause</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.cpp" line="253"/> <location filename="../gui/traywidget.cpp" line="254"/>
<source>Syncthing is running, click to pause all devices</source> <source>Syncthing is running, click to pause all devices</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.cpp" line="258"/> <location filename="../gui/traywidget.cpp" line="259"/>
<source>At least one device is paused, click to resume</source> <source>At least one device is paused, click to resume</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.cpp" line="294"/> <location filename="../gui/traywidget.cpp" line="323"/>
<source>The directory &lt;i&gt;%1&lt;/i&gt; does not exist on the local machine.</source> <source>The directory &lt;i&gt;%1&lt;/i&gt; does not exist on the local machine.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.cpp" line="257"/> <location filename="../gui/traywidget.cpp" line="258"/>
<source>Continue</source> <source>Continue</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.cpp" line="176"/> <location filename="../gui/traywidget.cpp" line="177"/>
<source>Own device ID</source> <source>Own device ID</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.cpp" line="213"/> <location filename="../gui/traywidget.cpp" line="214"/>
<source>Log</source> <source>Log</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -908,7 +963,7 @@
<name>QtGui::WebViewOptionPage</name> <name>QtGui::WebViewOptionPage</name>
<message> <message>
<location filename="../gui/webviewoptionpage.ui" line="14"/> <location filename="../gui/webviewoptionpage.ui" line="14"/>
<location filename="../gui/settingsdialog.cpp" line="459"/> <location filename="../gui/settingsdialog.cpp" line="535"/>
<source>General</source> <source>General</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -938,21 +993,29 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/settingsdialog.cpp" line="461"/> <location filename="../gui/settingsdialog.cpp" line="537"/>
<source>Syncthing Tray has not been built with vieb view support utilizing either Qt WebKit or Qt WebEngine. <source>Syncthing Tray has not been built with vieb view support utilizing either Qt WebKit or Qt WebEngine.
The Web UI will be opened in the default web browser instead.</source> The Web UI will be opened in the default web browser instead.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
</context> </context>
<context>
<name>Settings::restore</name>
<message>
<location filename="../application/settings.cpp" line="159"/>
<source>Unable to load certificate &quot;%1&quot; when restoring settings.</source>
<translation type="unfinished"></translation>
</message>
</context>
<context> <context>
<name>main</name> <name>main</name>
<message> <message>
<location filename="../application/main.cpp" line="70"/> <location filename="../application/main.cpp" line="69"/>
<source>You must configure how to connect to Syncthing when using Syncthing Tray the first time.</source> <source>You must configure how to connect to Syncthing when using Syncthing Tray the first time.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../application/main.cpp" line="71"/> <location filename="../application/main.cpp" line="70"/>
<source>Note that the settings dialog allows importing URL, credentials and API-key from the local Syncthing configuration.</source> <source>Note that the settings dialog allows importing URL, credentials and API-key from the local Syncthing configuration.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>

View File

@ -34,94 +34,100 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="459"/> <location filename="../data/syncthingconnection.cpp" line="169"/>
<location filename="../data/syncthingconnection.cpp" line="248"/>
<source>Connection configuration is insufficient.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../data/syncthingconnection.cpp" line="517"/>
<source>Unable to parse Syncthing log: </source> <source>Unable to parse Syncthing log: </source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="463"/> <location filename="../data/syncthingconnection.cpp" line="521"/>
<source>Unable to request system log: </source> <source>Unable to request system log: </source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="484"/> <location filename="../data/syncthingconnection.cpp" line="543"/>
<source>Unable to locate certificate used by Syncthing GUI.</source> <source>Unable to locate certificate used by Syncthing GUI.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="490"/> <location filename="../data/syncthingconnection.cpp" line="549"/>
<source>Unable to load certificate used by Syncthing GUI.</source> <source>Unable to load certificate used by Syncthing GUI.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="522"/> <location filename="../data/syncthingconnection.cpp" line="582"/>
<location filename="../data/syncthingconnection.cpp" line="622"/> <location filename="../data/syncthingconnection.cpp" line="682"/>
<source>Unable to parse Syncthing config: </source> <source>Unable to parse Syncthing config: </source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="527"/> <location filename="../data/syncthingconnection.cpp" line="587"/>
<location filename="../data/syncthingconnection.cpp" line="627"/> <location filename="../data/syncthingconnection.cpp" line="687"/>
<source>Unable to request Syncthing config: </source> <source>Unable to request Syncthing config: </source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="702"/> <location filename="../data/syncthingconnection.cpp" line="762"/>
<source>Unable to parse connections: </source> <source>Unable to parse connections: </source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="707"/> <location filename="../data/syncthingconnection.cpp" line="767"/>
<source>Unable to request connections: </source> <source>Unable to request connections: </source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="762"/> <location filename="../data/syncthingconnection.cpp" line="822"/>
<source>Unable to parse directory statistics: </source> <source>Unable to parse directory statistics: </source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="767"/> <location filename="../data/syncthingconnection.cpp" line="827"/>
<source>Unable to request directory statistics: </source> <source>Unable to request directory statistics: </source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="804"/> <location filename="../data/syncthingconnection.cpp" line="864"/>
<source>Unable to parse device statistics: </source> <source>Unable to parse device statistics: </source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="809"/> <location filename="../data/syncthingconnection.cpp" line="869"/>
<source>Unable to request device statistics: </source> <source>Unable to request device statistics: </source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="860"/> <location filename="../data/syncthingconnection.cpp" line="920"/>
<source>Unable to parse Syncthing events: </source> <source>Unable to parse Syncthing events: </source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="882"/> <location filename="../data/syncthingconnection.cpp" line="938"/>
<source>Unable to request Syncthing events: </source> <source>Unable to request Syncthing events: </source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="1094"/> <location filename="../data/syncthingconnection.cpp" line="1150"/>
<source>Unable to request rescan: </source> <source>Unable to request rescan: </source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="1109"/> <location filename="../data/syncthingconnection.cpp" line="1165"/>
<source>Unable to request pause/resume: </source> <source>Unable to request pause/resume: </source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="1124"/> <location filename="../data/syncthingconnection.cpp" line="1180"/>
<source>Unable to request restart: </source> <source>Unable to request restart: </source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="427"/> <location filename="../data/syncthingconnection.cpp" line="485"/>
<source>Unable to request QR-Code: </source> <source>Unable to request QR-Code: </source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -444,22 +450,22 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/settingsdialog.cpp" line="238"/> <location filename="../gui/settingsdialog.cpp" line="314"/>
<source>This is achieved by adding a *.desktop file under &lt;i&gt;~/.config/autostart&lt;/i&gt; so the setting only affects the current user.</source> <source>This is achieved by adding a *.desktop file under &lt;i&gt;~/.config/autostart&lt;/i&gt; so the setting only affects the current user.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/settingsdialog.cpp" line="240"/> <location filename="../gui/settingsdialog.cpp" line="316"/>
<source>This is achieved by adding a registry key under &lt;i&gt;HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Run&lt;/i&gt; so the setting only affects the current user. Note that the startup entry is invalidated when moving &lt;i&gt;syncthingtray.exe&lt;/i&gt;.</source> <source>This is achieved by adding a registry key under &lt;i&gt;HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Run&lt;/i&gt; so the setting only affects the current user. Note that the startup entry is invalidated when moving &lt;i&gt;syncthingtray.exe&lt;/i&gt;.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/settingsdialog.cpp" line="242"/> <location filename="../gui/settingsdialog.cpp" line="318"/>
<source>This feature has not been implemented for your platform (yet).</source> <source>This feature has not been implemented for your platform (yet).</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/settingsdialog.cpp" line="329"/> <location filename="../gui/settingsdialog.cpp" line="405"/>
<source>unable to modify startup entry</source> <source>unable to modify startup entry</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -467,65 +473,105 @@
<context> <context>
<name>QtGui::ConnectionOptionPage</name> <name>QtGui::ConnectionOptionPage</name>
<message> <message>
<location filename="../gui/connectionoptionpage.ui" line="6"/> <location filename="../gui/connectionoptionpage.ui" line="14"/>
<source>Connection</source> <source>Connection</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/connectionoptionpage.ui" line="19"/> <location filename="../gui/connectionoptionpage.ui" line="30"/>
<source>Config label</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/connectionoptionpage.ui" line="80"/>
<source>Add secondary instance</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/connectionoptionpage.ui" line="97"/>
<source>Remove currently selected secondary instance</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/connectionoptionpage.ui" line="111"/>
<source>Syncthing URL</source> <source>Syncthing URL</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/connectionoptionpage.ui" line="29"/> <location filename="../gui/connectionoptionpage.ui" line="121"/>
<source>Authentication</source> <source>Authentication</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/connectionoptionpage.ui" line="42"/> <location filename="../gui/connectionoptionpage.ui" line="134"/>
<source>User</source> <source>User</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/connectionoptionpage.ui" line="76"/> <location filename="../gui/connectionoptionpage.ui" line="212"/>
<source>disconnected</source> <source>disconnected</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/connectionoptionpage.ui" line="83"/> <location filename="../gui/connectionoptionpage.ui" line="219"/>
<source>Apply connection settings and try to reconnect with the currently selected config</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/connectionoptionpage.ui" line="255"/>
<source>It is possible to save multiple configurations. This allows switching quickly between multiple Syncthing instances using the arrow in the right corner of the tray menu. The config label is an arbitrary name to identify a configuration and must not match the name of the corresponding Syncthing device.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/connectionoptionpage.ui" line="265"/>
<source>HTTPS certificate</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/connectionoptionpage.ui" line="205"/>
<source>Status</source> <source>Status</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/connectionoptionpage.ui" line="90"/> <location filename="../gui/connectionoptionpage.ui" line="168"/>
<source>Apply connection settings and try to reconnect</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/connectionoptionpage.ui" line="104"/>
<source>API key</source> <source>API key</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/connectionoptionpage.ui" line="114"/> <location filename="../gui/connectionoptionpage.ui" line="181"/>
<source>Insert values from local Syncthing configuration</source> <source>Insert values from local Syncthing configuration</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/connectionoptionpage.ui" line="52"/> <location filename="../gui/connectionoptionpage.ui" line="151"/>
<source>Password</source> <source>Password</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/settingsdialog.cpp" line="70"/> <location filename="../gui/settingsdialog.cpp" line="56"/>
<source>Auto-detected for local instance</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/settingsdialog.cpp" line="73"/>
<source>Select Syncthing config file</source> <source>Select Syncthing config file</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/settingsdialog.cpp" line="77"/> <location filename="../gui/settingsdialog.cpp" line="80"/>
<source>Unable to parse the Syncthing config file.</source> <source>Unable to parse the Syncthing config file.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<location filename="../gui/settingsdialog.cpp" line="143"/>
<source>Unable to load specified certificate &quot;%1&quot;.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/settingsdialog.cpp" line="167"/>
<source>Instance %1</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>QtGui::DevView</name> <name>QtGui::DevView</name>
@ -576,48 +622,48 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/launcheroptionpage.ui" line="42"/> <location filename="../gui/launcheroptionpage.ui" line="51"/>
<source>Syncthing executable</source> <source>Syncthing executable</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/launcheroptionpage.ui" line="52"/> <location filename="../gui/launcheroptionpage.ui" line="61"/>
<source>Arguments</source> <source>Arguments</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/launcheroptionpage.ui" line="86"/> <location filename="../gui/launcheroptionpage.ui" line="95"/>
<source>Syncthing log (stdout/stderr)</source> <source>Syncthing log (interleaved stdout/stderr)</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/launcheroptionpage.ui" line="102"/> <location filename="../gui/launcheroptionpage.ui" line="111"/>
<source>Apply and launch now</source> <source>Apply and launch now</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/launcheroptionpage.ui" line="119"/> <location filename="../gui/launcheroptionpage.ui" line="128"/>
<source>Stop launched instance</source> <source>Stop launched instance</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/launcheroptionpage.ui" line="138"/> <location filename="../gui/launcheroptionpage.ui" line="147"/>
<source>No log messages available yet</source> <source>No log messages available yet</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/launcheroptionpage.ui" line="145"/> <location filename="../gui/launcheroptionpage.ui" line="154"/>
<source>Ensure latest log is visible</source> <source>Ensure latest log is visible</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/settingsdialog.cpp" line="409"/> <location filename="../gui/settingsdialog.cpp" line="485"/>
<source>Syncthing existed with exit code %1 <source>Syncthing existed with exit code %1
</source> </source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/settingsdialog.cpp" line="412"/> <location filename="../gui/settingsdialog.cpp" line="488"/>
<source>Syncthing crashed with exit code %1 <source>Syncthing crashed with exit code %1
</source> </source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
@ -659,17 +705,22 @@
<context> <context>
<name>QtGui::SettingsDialog</name> <name>QtGui::SettingsDialog</name>
<message> <message>
<location filename="../gui/settingsdialog.cpp" line="497"/> <location filename="../gui/settingsdialog.cpp" line="573"/>
<source>Tray</source> <source>Tray</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/settingsdialog.cpp" line="509"/> <location filename="../gui/settingsdialog.cpp" line="585"/>
<source>Startup</source> <source>Startup</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/settingsdialog.cpp" line="503"/> <location filename="../gui/settingsdialog.cpp" line="595"/>
<source>Settings</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/settingsdialog.cpp" line="579"/>
<source>Web view</source> <source>Web view</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -687,62 +738,62 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/trayicon.cpp" line="36"/> <location filename="../gui/trayicon.cpp" line="37"/>
<source>About</source> <source>About</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/trayicon.cpp" line="38"/> <location filename="../gui/trayicon.cpp" line="39"/>
<source>Close</source> <source>Close</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/trayicon.cpp" line="77"/> <location filename="../gui/trayicon.cpp" line="78"/>
<source>Error</source> <source>Error</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/trayicon.cpp" line="84"/> <location filename="../gui/trayicon.cpp" line="85"/>
<source>Syncthing notification</source> <source>Syncthing notification</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/trayicon.cpp" line="93"/> <location filename="../gui/trayicon.cpp" line="94"/>
<source>Not connected to Syncthing</source> <source>Not connected to Syncthing</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/trayicon.cpp" line="95"/> <location filename="../gui/trayicon.cpp" line="96"/>
<source>Disconnected from Syncthing</source> <source>Disconnected from Syncthing</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/trayicon.cpp" line="100"/> <location filename="../gui/trayicon.cpp" line="101"/>
<source>Syncthing is idling</source> <source>Syncthing is idling</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/trayicon.cpp" line="104"/> <location filename="../gui/trayicon.cpp" line="105"/>
<source>Syncthing is scanning</source> <source>Syncthing is scanning</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/trayicon.cpp" line="108"/> <location filename="../gui/trayicon.cpp" line="109"/>
<source>Notifications available</source> <source>Notifications available</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/trayicon.cpp" line="112"/> <location filename="../gui/trayicon.cpp" line="113"/>
<source>At least one device is paused</source> <source>At least one device is paused</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/trayicon.cpp" line="116"/> <location filename="../gui/trayicon.cpp" line="117"/>
<source>Synchronization is ongoing</source> <source>Synchronization is ongoing</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/trayicon.cpp" line="125"/> <location filename="../gui/trayicon.cpp" line="126"/>
<source>Synchronization complete</source> <source>Synchronization complete</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -756,7 +807,7 @@
</message> </message>
<message> <message>
<location filename="../gui/traywidget.ui" line="107"/> <location filename="../gui/traywidget.ui" line="107"/>
<location filename="../gui/traywidget.cpp" line="244"/> <location filename="../gui/traywidget.cpp" line="245"/>
<source>Connect</source> <source>Connect</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -783,8 +834,8 @@
<message> <message>
<location filename="../gui/traywidget.ui" line="230"/> <location filename="../gui/traywidget.ui" line="230"/>
<location filename="../gui/traywidget.ui" line="250"/> <location filename="../gui/traywidget.ui" line="250"/>
<location filename="../gui/traywidget.cpp" line="345"/> <location filename="../gui/traywidget.cpp" line="374"/>
<location filename="../gui/traywidget.cpp" line="352"/> <location filename="../gui/traywidget.cpp" line="381"/>
<source>unknown</source> <source>unknown</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -799,24 +850,23 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.ui" line="280"/> <location filename="../gui/traywidget.ui" line="296"/>
<source>Directories</source> <source>Directories</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.ui" line="309"/> <location filename="../gui/traywidget.ui" line="325"/>
<source>Devices</source> <source>Devices</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.ui" line="80"/> <location filename="../gui/traywidget.ui" line="80"/>
<location filename="../gui/traywidget.cpp" line="138"/> <location filename="../gui/traywidget.cpp" line="139"/>
<source>About</source> <source>About</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.ui" line="134"/> <location filename="../gui/traywidget.ui" line="134"/>
<location filename="../gui/traywidget.cpp" line="118"/>
<source>Settings</source> <source>Settings</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -826,72 +876,77 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.cpp" line="67"/> <location filename="../gui/traywidget.cpp" line="68"/>
<source>View own device ID</source> <source>View own device ID</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.cpp" line="84"/> <location filename="../gui/traywidget.cpp" line="85"/>
<source>Rescan all directories</source> <source>Rescan all directories</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.cpp" line="78"/> <location filename="../gui/traywidget.cpp" line="79"/>
<source>Show Syncthing log</source> <source>Show Syncthing log</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.cpp" line="72"/> <location filename="../gui/traywidget.cpp" line="73"/>
<source>Restart Syncthing</source> <source>Restart Syncthing</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.cpp" line="186"/> <location filename="../gui/traywidget.cpp" line="92"/>
<source>Connection</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/traywidget.cpp" line="187"/>
<source>device ID is unknown</source> <source>device ID is unknown</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.cpp" line="194"/> <location filename="../gui/traywidget.cpp" line="195"/>
<source>Copy to clipboard</source> <source>Copy to clipboard</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.cpp" line="245"/> <location filename="../gui/traywidget.cpp" line="246"/>
<source>Not connected to Syncthing, click to connect</source> <source>Not connected to Syncthing, click to connect</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.cpp" line="252"/> <location filename="../gui/traywidget.cpp" line="253"/>
<source>Pause</source> <source>Pause</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.cpp" line="253"/> <location filename="../gui/traywidget.cpp" line="254"/>
<source>Syncthing is running, click to pause all devices</source> <source>Syncthing is running, click to pause all devices</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.cpp" line="258"/> <location filename="../gui/traywidget.cpp" line="259"/>
<source>At least one device is paused, click to resume</source> <source>At least one device is paused, click to resume</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.cpp" line="294"/> <location filename="../gui/traywidget.cpp" line="323"/>
<source>The directory &lt;i&gt;%1&lt;/i&gt; does not exist on the local machine.</source> <source>The directory &lt;i&gt;%1&lt;/i&gt; does not exist on the local machine.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.cpp" line="257"/> <location filename="../gui/traywidget.cpp" line="258"/>
<source>Continue</source> <source>Continue</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.cpp" line="176"/> <location filename="../gui/traywidget.cpp" line="177"/>
<source>Own device ID</source> <source>Own device ID</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.cpp" line="213"/> <location filename="../gui/traywidget.cpp" line="214"/>
<source>Log</source> <source>Log</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -908,7 +963,7 @@
<name>QtGui::WebViewOptionPage</name> <name>QtGui::WebViewOptionPage</name>
<message> <message>
<location filename="../gui/webviewoptionpage.ui" line="14"/> <location filename="../gui/webviewoptionpage.ui" line="14"/>
<location filename="../gui/settingsdialog.cpp" line="459"/> <location filename="../gui/settingsdialog.cpp" line="535"/>
<source>General</source> <source>General</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -938,21 +993,29 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/settingsdialog.cpp" line="461"/> <location filename="../gui/settingsdialog.cpp" line="537"/>
<source>Syncthing Tray has not been built with vieb view support utilizing either Qt WebKit or Qt WebEngine. <source>Syncthing Tray has not been built with vieb view support utilizing either Qt WebKit or Qt WebEngine.
The Web UI will be opened in the default web browser instead.</source> The Web UI will be opened in the default web browser instead.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
</context> </context>
<context>
<name>Settings::restore</name>
<message>
<location filename="../application/settings.cpp" line="159"/>
<source>Unable to load certificate &quot;%1&quot; when restoring settings.</source>
<translation type="unfinished"></translation>
</message>
</context>
<context> <context>
<name>main</name> <name>main</name>
<message> <message>
<location filename="../application/main.cpp" line="70"/> <location filename="../application/main.cpp" line="69"/>
<source>You must configure how to connect to Syncthing when using Syncthing Tray the first time.</source> <source>You must configure how to connect to Syncthing when using Syncthing Tray the first time.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../application/main.cpp" line="71"/> <location filename="../application/main.cpp" line="70"/>
<source>Note that the settings dialog allows importing URL, credentials and API-key from the local Syncthing configuration.</source> <source>Note that the settings dialog allows importing URL, credentials and API-key from the local Syncthing configuration.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>