Refesh traffic, general refactoring

This commit is contained in:
Martchus 2016-08-30 20:01:07 +02:00
parent 9b49c68013
commit 4737268e20
21 changed files with 697 additions and 441 deletions

View File

@ -28,7 +28,9 @@ set(SRC_FILES
set(WIDGETS_HEADER_FILES
application/settings.h
gui/tray.h
gui/trayicon.h
gui/traywidget.h
gui/traymenu.h
gui/settingsdialog.h
gui/webpage.h
gui/webviewdialog.h
@ -41,7 +43,9 @@ set(WIDGETS_HEADER_FILES
set(WIDGETS_SRC_FILES
application/main.cpp
application/settings.cpp
gui/tray.cpp
gui/trayicon.cpp
gui/traywidget.cpp
gui/traymenu.cpp
gui/settingsdialog.cpp
gui/webpage.cpp
gui/webviewdialog.cpp
@ -56,7 +60,7 @@ set(WIDGETS_UI_FILES
gui/connectionoptionpage.ui
gui/notificationsoptionpage.ui
gui/appearanceoptionpage.ui
gui/launcheroptionpage.ui
gui/autostartoptionpage.ui
gui/webviewoptionpage.ui
)

View File

@ -1,5 +1,6 @@
#include "./settings.h"
#include "../gui/tray.h"
#include "../gui/trayicon.h"
#include "../gui/traywidget.h"
#include "resources/config.h"
@ -9,6 +10,7 @@
#include <qtutilities/resources/qtconfigarguments.h>
#include <qtutilities/resources/resources.h>
#include <qtutilities/resources/importplugin.h>
#include <qtutilities/settingsdialog/qtsettings.h>
#include <QApplication>
@ -28,6 +30,9 @@ int main(int argc, char *argv[])
HelpArgument helpArg(parser);
// Qt configuration arguments
QT_CONFIG_ARGUMENTS qtConfigArgs;
Argument windowedArg("windowed", 'w', "shows the UI in a regular window");
windowedArg.setCombinable(true);
qtConfigArgs.qtWidgetsGuiArg().addSubArgument(&windowedArg);
parser.setMainArguments({&qtConfigArgs.qtWidgetsGuiArg(), &helpArg});
try {
parser.parseArgs(argc, argv);
@ -42,10 +47,16 @@ int main(int argc, char *argv[])
int res;
#ifndef QT_NO_SYSTEMTRAYICON
if(QSystemTrayIcon::isSystemTrayAvailable()) {
application.setQuitOnLastWindowClosed(false);
TrayIcon trayIcon;
trayIcon.show();
res = application.exec();
if(windowedArg.isPresent()) {
TrayWidget trayWidget;
trayWidget.show();
res = application.exec();
} else {
application.setQuitOnLastWindowClosed(false);
TrayIcon trayIcon;
trayIcon.show();
res = application.exec();
}
} else {
QMessageBox::critical(nullptr, QApplication::applicationName(), QApplication::translate("main", "The system tray is (currently) not available."));
res = -1;

View File

@ -1,5 +1,7 @@
#include "./syncthingconnection.h"
#include <c++utilities/conversion/conversionexception.h>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QUrlQuery>
@ -10,10 +12,13 @@
#include <QPixmap>
#include <QAuthenticator>
#include <QStringBuilder>
#include <QTimer>
#include <utility>
using namespace std;
using namespace ChronoUtilities;
using namespace ConversionUtilities;
namespace Data {
@ -75,6 +80,8 @@ SyncthingConnection::SyncthingConnection(const QString &syncthingUrl, const QByt
m_lastEventId(0),
m_totalIncomingTraffic(0),
m_totalOutgoingTraffic(0),
m_totalIncomingRate(0),
m_totalOutgoingRate(0),
m_configReply(nullptr),
m_statusReply(nullptr),
m_eventsReply(nullptr),
@ -542,9 +549,20 @@ void SyncthingConnection::readConnections()
if(jsonError.error == QJsonParseError::NoError) {
const QJsonObject replyObj(replyDoc.object());
const QJsonObject totalObj(replyObj.value(QStringLiteral("total")).toObject());
m_totalIncomingTraffic = totalObj.value(QStringLiteral("inBytesTotal")).toInt(0);
m_totalOutgoingTraffic = totalObj.value(QStringLiteral("outBytesTotal")).toInt(0);
emit trafficChanged(m_totalIncomingTraffic, m_totalOutgoingTraffic);
// read traffic
const int totalIncomingTraffic = totalObj.value(QStringLiteral("inBytesTotal")).toInt(0);
const int totalOutgoingTraffic = totalObj.value(QStringLiteral("outBytesTotal")).toInt(0);
double transferTime;
if(!m_lastConnectionsUpdate.isNull() && ((transferTime = (DateTime::gmtNow() - m_lastConnectionsUpdate).totalSeconds()) != 0.0)) {
m_totalIncomingRate = (totalIncomingTraffic - m_totalIncomingTraffic) * 0.008 / transferTime,
m_totalOutgoingRate = (totalOutgoingTraffic - m_totalOutgoingTraffic) * 0.008 / transferTime;
} else {
m_totalIncomingRate = m_totalOutgoingRate = 0.0;
}
emit trafficChanged(m_totalIncomingTraffic = totalIncomingTraffic, m_totalOutgoingTraffic = totalOutgoingTraffic);
// read connection status
const QJsonObject connectionsObj(replyObj.value(QStringLiteral("connections")).toObject());
int index = 0;
for(SyncthingDev &dev : m_devs) {
@ -576,7 +594,13 @@ void SyncthingConnection::readConnections()
}
++index;
}
m_lastConnectionsUpdate = QDateTime::currentDateTime();
m_lastConnectionsUpdate = DateTime::gmtNow();
// since there seems no event for this data, just request every 2 seconds, FIXME: make interval configurable
if(m_keepPolling) {
QTimer::singleShot(2000, Qt::VeryCoarseTimer, this, SLOT(requestConnections()));
}
} else {
emit error(tr("Unable to parse connections: ") + jsonError.errorString());
}
@ -609,7 +633,12 @@ void SyncthingConnection::readEvents()
for(const QJsonValue &eventVal : replyArray) {
const QJsonObject event = eventVal.toObject();
m_lastEventId = event.value(QStringLiteral("id")).toInt(m_lastEventId);
const QDateTime eventTime(QDateTime::fromString(event.value(QStringLiteral("time")).toString(), Qt::ISODate));
DateTime eventTime;
try {
eventTime = DateTime::fromIsoString(event.value(QStringLiteral("time")).toString().toLocal8Bit().data()).first;
} catch(const ConversionException &) {
// ignore conversion error
}
const QString eventType(event.value(QStringLiteral("type")).toString());
const QJsonObject eventData(event.value(QStringLiteral("data")).toObject());
if(eventType == QLatin1String("Starting")) {
@ -731,7 +760,7 @@ void SyncthingConnection::readDirEvent(const QString &eventType, const QJsonObje
dirInfo->localFiles = summary.value(QStringLiteral("localFiles")).toInt();
dirInfo->neededByted = summary.value(QStringLiteral("needByted")).toInt();
dirInfo->neededFiles = summary.value(QStringLiteral("needFiles")).toInt();
//dirInfo->assignStatus(summary.value(QStringLiteral("state")).toString());
// FIXME: dirInfo->assignStatus(summary.value(QStringLiteral("state")).toString());
emit dirStatusChanged(*dirInfo, index);
}
} else if(eventType == QLatin1String("FolderCompletion")) {
@ -743,6 +772,16 @@ void SyncthingConnection::readDirEvent(const QString &eventType, const QJsonObje
// just show the smallest percentage for now
dirInfo->progressPercentage = percentage;
}
} else if(eventType == QLatin1String("FolderScanProgress")) {
// FIXME: for some reason current is always 0
int current = eventData.value(QStringLiteral("current")).toInt(0);
int total = eventData.value(QStringLiteral("total")).toInt(0);
int rate = eventData.value(QStringLiteral("rate")).toInt(0);
if(current > 0 && total > 0) {
dirInfo->progressPercentage = current * 100 / total;
dirInfo->progressRate = rate;
dirInfo->status = DirStatus::Scanning; // ensure state is scanning
}
}
}
}
@ -751,9 +790,9 @@ void SyncthingConnection::readDirEvent(const QString &eventType, const QJsonObje
/*!
* \brief Reads results of requestEvents().
*/
void SyncthingConnection::readDeviceEvent(const QDateTime &eventTime, const QString &eventType, const QJsonObject &eventData)
void SyncthingConnection::readDeviceEvent(DateTime eventTime, const QString &eventType, const QJsonObject &eventData)
{
if(eventTime.isValid() && m_lastConnectionsUpdate.isValid() && eventTime < m_lastConnectionsUpdate) {
if(eventTime.isNull() && m_lastConnectionsUpdate.isNull() && eventTime < m_lastConnectionsUpdate) {
return; // ignore device events happened before the last connections update
}
const QString dev(eventData.value(QStringLiteral("device")).toString());
@ -773,6 +812,7 @@ void SyncthingConnection::readDeviceEvent(const QDateTime &eventTime, const QStr
status = DevStatus::Rejected;
} else if(eventType == QLatin1String("DeviceResumed")) {
paused = false;
status = DevStatus::Disconnected; // FIXME: correct to assume device which has just been resumed is still disconnected?
} else if(eventType == QLatin1String("DeviceDiscovered")) {
// we know about this device already, set status anyways because it might still be unknown
status = DevStatus::Disconnected;

View File

@ -1,8 +1,9 @@
#ifndef SYNCTHINGCONNECTION_H
#define SYNCTHINGCONNECTION_H
#include <c++utilities/chrono/datetime.h>
#include <QObject>
#include <QDateTime>
#include <functional>
#include <vector>
@ -60,6 +61,7 @@ struct SyncthingDir
int minDiskFreePercentage = 0;
DirStatus status = DirStatus::Unknown;
int progressPercentage = 0;
int progressRate = 0;
std::vector<DirErrors> errors;
int globalBytes = 0, globalDeleted = 0, globalFiles = 0;
int localBytes = 0, localDeleted = 0, localFiles = 0;
@ -76,7 +78,7 @@ enum class DevStatus
Idle,
Synchronizing,
OutOfSync,
Rejected,
Rejected
};
struct SyncthingDev
@ -88,6 +90,7 @@ struct SyncthingDev
QString certName;
DevStatus status;
int progressPercentage = 0;
int progressRate = 0;
bool introducer = false;
bool paused = false;
int totalIncomingTraffic = 0;
@ -132,6 +135,8 @@ public:
const QString &myId() const;
int totalIncomingTraffic() const;
int totalOutgoingTraffic() const;
double totalIncomingRate() const;
double totalOutgoingRate() const;
const std::vector<SyncthingDir> &dirInfo() const;
const std::vector<SyncthingDev> &devInfo() const;
void requestQrCode(const QString &text, std::function<void (const QPixmap &)> callback);
@ -234,7 +239,7 @@ private Q_SLOTS:
void readStatusChangedEvent(const QJsonObject &eventData);
void readDownloadProgressEvent(const QJsonObject &eventData);
void readDirEvent(const QString &eventType, const QJsonObject &eventData);
void readDeviceEvent(const QDateTime &eventTime, const QString &eventType, const QJsonObject &eventData);
void readDeviceEvent(ChronoUtilities::DateTime eventTime, const QString &eventType, const QJsonObject &eventData);
void readRescan();
void readPauseResume();
@ -260,6 +265,8 @@ private:
QString m_myId;
int m_totalIncomingTraffic;
int m_totalOutgoingTraffic;
double m_totalIncomingRate;
double m_totalOutgoingRate;
QNetworkReply *m_configReply;
QNetworkReply *m_statusReply;
QNetworkReply *m_connectionsReply;
@ -269,7 +276,7 @@ private:
bool m_hasStatus;
std::vector<SyncthingDir> m_dirs;
std::vector<SyncthingDev> m_devs;
QDateTime m_lastConnectionsUpdate;
ChronoUtilities::DateTime m_lastConnectionsUpdate;
};
/*!
@ -361,7 +368,7 @@ inline const QString &SyncthingConnection::myId() const
}
/*!
* \brief Returns the total incoming traffic.
* \brief Returns the total incoming traffic in byte.
*/
inline int SyncthingConnection::totalIncomingTraffic() const
{
@ -369,13 +376,29 @@ inline int SyncthingConnection::totalIncomingTraffic() const
}
/*!
* \brief Returns the total outgoing traffic.
* \brief Returns the total outgoing traffic in byte.
*/
inline int SyncthingConnection::totalOutgoingTraffic() const
{
return m_totalOutgoingTraffic;
}
/*!
* \brief Returns the total incoming transfer rate in kbit/s.
*/
inline double SyncthingConnection::totalIncomingRate() const
{
return m_totalIncomingRate;
}
/*!
* \brief Returns the total outgoing transfer rate in kbit/s.
*/
inline double SyncthingConnection::totalOutgoingRate() const
{
return m_totalOutgoingRate;
}
/*!
* \brief Returns all available directory info.
* \remarks The returned object container object is persistent. However, the contained

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>QtGui::AutostartOptionPage</class>
<widget class="QWidget" name="QtGui::AutostartOptionPage">
<property name="windowTitle">
<string>Autostart</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Not implemented yet&lt;/span&gt;&lt;/p&gt;&lt;p&gt;This will allow launching the tray when the desktop environment starts and to launch Syncthing when the tray is started.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -41,7 +41,12 @@ void DevView::showContextMenu()
{
if(selectionModel() && selectionModel()->selectedRows(0).size() == 1) {
QMenu menu;
connect(menu.addAction(QIcon::fromTheme(QStringLiteral("edit-copy"), QIcon(QStringLiteral(":/icons/hicolor/scalable/actions/edit-copy.svg"))), tr("Copy")), &QAction::triggered, this, &DevView::copySelectedItem);
if(selectionModel()->selectedRows(0).at(0).parent().isValid()) {
connect(menu.addAction(QIcon::fromTheme(QStringLiteral("edit-copy"), QIcon(QStringLiteral(":/icons/hicolor/scalable/actions/edit-copy.svg"))), tr("Copy value")), &QAction::triggered, this, &DevView::copySelectedItem);
} else {
connect(menu.addAction(QIcon::fromTheme(QStringLiteral("edit-copy"), QIcon(QStringLiteral(":/icons/hicolor/scalable/actions/edit-copy.svg"))), tr("Copy name")), &QAction::triggered, this, &DevView::copySelectedItem);
connect(menu.addAction(QIcon::fromTheme(QStringLiteral("edit-copy"), QIcon(QStringLiteral(":/icons/hicolor/scalable/actions/edit-copy.svg"))), tr("Copy ID")), &QAction::triggered, this, &DevView::copySelectedItemId);
}
menu.exec(QCursor::pos());
}
}
@ -64,4 +69,21 @@ void DevView::copySelectedItem()
}
}
void DevView::copySelectedItemId()
{
if(selectionModel() && selectionModel()->selectedRows(0).size() == 1) {
const QModelIndex selectedIndex = selectionModel()->selectedRows(0).at(0);
QString text;
if(selectedIndex.parent().isValid()) {
// dev attribute: should be handled by copySelectedItemId()
} else {
// dev name/id
text = model()->data(model()->index(0, 1, selectedIndex)).toString();
}
if(!text.isEmpty()) {
QGuiApplication::clipboard()->setText(text);
}
}
}
}

View File

@ -20,6 +20,7 @@ protected:
private Q_SLOTS:
void showContextMenu();
void copySelectedItem();
void copySelectedItemId();
};

View File

@ -41,7 +41,12 @@ void DirView::showContextMenu()
{
if(selectionModel() && selectionModel()->selectedRows(0).size() == 1) {
QMenu menu;
connect(menu.addAction(QIcon::fromTheme(QStringLiteral("edit-copy"), QIcon(QStringLiteral(":/icons/hicolor/scalable/actions/edit-copy.svg"))), tr("Copy")), &QAction::triggered, this, &DirView::copySelectedItem);
if(selectionModel()->selectedRows(0).at(0).parent().isValid()) {
connect(menu.addAction(QIcon::fromTheme(QStringLiteral("edit-copy"), QIcon(QStringLiteral(":/icons/hicolor/scalable/actions/edit-copy.svg"))), tr("Copy value")), &QAction::triggered, this, &DirView::copySelectedItem);
} else {
connect(menu.addAction(QIcon::fromTheme(QStringLiteral("edit-copy"), QIcon(QStringLiteral(":/icons/hicolor/scalable/actions/edit-copy.svg"))), tr("Copy label/ID")), &QAction::triggered, this, &DirView::copySelectedItem);
connect(menu.addAction(QIcon::fromTheme(QStringLiteral("edit-copy"), QIcon(QStringLiteral(":/icons/hicolor/scalable/actions/edit-copy.svg"))), tr("Copy path")), &QAction::triggered, this, &DirView::copySelectedItemPath);
}
menu.exec(QCursor::pos());
}
}
@ -64,4 +69,21 @@ void DirView::copySelectedItem()
}
}
void DirView::copySelectedItemPath()
{
if(selectionModel() && selectionModel()->selectedRows(0).size() == 1) {
const QModelIndex selectedIndex = selectionModel()->selectedRows(0).at(0);
QString text;
if(selectedIndex.parent().isValid()) {
// dev attribute: should be handled by copySelectedItem() only
} else {
// dev path
text = model()->data(model()->index(1, 1, selectedIndex)).toString();
}
if(!text.isEmpty()) {
QGuiApplication::clipboard()->setText(text);
}
}
}
}

View File

@ -21,6 +21,7 @@ protected:
private Q_SLOTS:
void showContextMenu();
void copySelectedItem();
void copySelectedItemPath();
};

View File

@ -1,28 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>QtGui::LauncherOptionPage</class>
<widget class="QWidget" name="QtGui::LauncherOptionPage">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>229</width>
<height>164</height>
</rect>
</property>
<property name="windowTitle">
<string>Launcher</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Not implemented yet.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;This will allow launching Syncthing when the tray is started.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -6,7 +6,7 @@
#include "ui_connectionoptionpage.h"
#include "ui_notificationsoptionpage.h"
#include "ui_appearanceoptionpage.h"
#include "ui_launcheroptionpage.h"
#include "ui_autostartoptionpage.h"
#include "ui_webviewoptionpage.h"
#include <tagparser/mediafileinfo.h>
@ -138,21 +138,21 @@ void AppearanceOptionPage::reset()
}
// LauncherOptionPage
LauncherOptionPage::LauncherOptionPage(QWidget *parentWidget) :
LauncherOptionPageBase(parentWidget)
AutostartOptionPage::AutostartOptionPage(QWidget *parentWidget) :
AutostartOptionPageBase(parentWidget)
{}
LauncherOptionPage::~LauncherOptionPage()
AutostartOptionPage::~AutostartOptionPage()
{}
bool LauncherOptionPage::apply()
bool AutostartOptionPage::apply()
{
if(hasBeenShown()) {
}
return true;
}
void LauncherOptionPage::reset()
void AutostartOptionPage::reset()
{
if(hasBeenShown()) {
}
@ -211,7 +211,7 @@ SettingsDialog::SettingsDialog(Data::SyncthingConnection *connection, QWidget *p
category->setDisplayName(tr("Tray"));
category->assignPages(QList<Dialogs::OptionPage *>()
<< new ConnectionOptionPage(connection) << new NotificationsOptionPage
<< new AppearanceOptionPage << new LauncherOptionPage);
<< new AppearanceOptionPage << new AutostartOptionPage);
category->setIcon(QIcon(QStringLiteral(":/icons/hicolor/scalable/app/syncthingtray.svg")));
categories << category;

View File

@ -32,7 +32,7 @@ DECLARE_UI_FILE_BASED_OPTION_PAGE(NotificationsOptionPage)
DECLARE_UI_FILE_BASED_OPTION_PAGE(AppearanceOptionPage)
DECLARE_UI_FILE_BASED_OPTION_PAGE(LauncherOptionPage)
DECLARE_UI_FILE_BASED_OPTION_PAGE(AutostartOptionPage)
#if defined(SYNCTHINGTRAY_USE_WEBENGINE) || defined(SYNCTHINGTRAY_USE_WEBKIT)
DECLARE_UI_FILE_BASED_OPTION_PAGE(WebViewOptionPage)

144
gui/trayicon.cpp Normal file
View File

@ -0,0 +1,144 @@
#include "./trayicon.h"
#include "./traywidget.h"
#include "../application/settings.h"
#include "../data/syncthingconnection.h"
#include <qtutilities/misc/dialogutils.h>
#include <QCoreApplication>
#include <QSvgRenderer>
#include <QPainter>
#include <QPixmap>
using namespace Dialogs;
using namespace Data;
namespace QtGui {
/*!
* \brief Instantiates a new tray icon.
*/
TrayIcon::TrayIcon(QObject *parent) :
QSystemTrayIcon(parent),
m_size(QSize(128, 128)),
m_statusIconDisconnected(QIcon(renderSvgImage(QStringLiteral(":/icons/hicolor/scalable/status/syncthing-disconnected.svg")))),
m_statusIconDefault(QIcon(renderSvgImage(QStringLiteral(":/icons/hicolor/scalable/status/syncthing-default.svg")))),
m_statusIconNotify(QIcon(renderSvgImage(QStringLiteral(":/icons/hicolor/scalable/status/syncthing-notify.svg")))),
m_statusIconPause(QIcon(renderSvgImage(QStringLiteral(":/icons/hicolor/scalable/status/syncthing-pause.svg")))),
m_statusIconSync(QIcon(renderSvgImage(QStringLiteral(":/icons/hicolor/scalable/status/syncthing-sync.svg")))),
m_status(SyncthingStatus::Disconnected)
{
// 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("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("help-about"), QIcon(QStringLiteral(":/icons/hicolor/scalable/apps/help-about.svg"))), tr("About")), &QAction::triggered, m_trayMenu.widget(), &TrayWidget::showAboutDialog);
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);
setContextMenu(&m_contextMenu);
// set initial status
updateStatusIconAndText(SyncthingStatus::Disconnected);
// connect signals and slots
SyncthingConnection *connection = &(m_trayMenu.widget()->connection());
connect(this, &TrayIcon::activated, this, &TrayIcon::handleActivated);
connect(connection, &SyncthingConnection::error, this, &TrayIcon::showSyncthingError);
connect(connection, &SyncthingConnection::newNotification, this, &TrayIcon::showSyncthingNotification);
connect(connection, &SyncthingConnection::statusChanged, this, &TrayIcon::updateStatusIconAndText);
}
void TrayIcon::handleActivated(QSystemTrayIcon::ActivationReason reason)
{
switch(reason) {
case QSystemTrayIcon::Context:
// can't catch that event on Plasma 5 anyways
break;
case QSystemTrayIcon::Trigger:
// either show web UI or context menu
if(false) {
m_trayMenu.widget()->showWebUi();
} else {
m_trayMenu.resize(m_trayMenu.sizeHint());
// when showing the menu manually
// move the menu to the closest of the currently available screen
// this implies that the tray icon is located near the edge of the screen; otherwise this behavior makes no sense
cornerWidget(&m_trayMenu);
m_trayMenu.show();
}
break;
default:
;
}
}
void TrayIcon::showSyncthingError(const QString &errorMsg)
{
if(Settings::notifyOnErrors()) {
showMessage(tr("Syncthing error"), errorMsg, QSystemTrayIcon::Critical);
}
}
void TrayIcon::showSyncthingNotification(const QString &message)
{
if(Settings::showSyncthingNotifications()) {
showMessage(tr("Syncthing notification"), message, QSystemTrayIcon::Information);
}
}
void TrayIcon::updateStatusIconAndText(SyncthingStatus status)
{
switch(status) {
case SyncthingStatus::Disconnected:
setIcon(m_statusIconDisconnected);
setToolTip(tr("Not connected to Syncthing"));
if(Settings::notifyOnDisconnect()) {
showMessage(QCoreApplication::applicationName(), tr("Disconnected from Syncthing"), QSystemTrayIcon::Warning);
}
break;
case SyncthingStatus::Default:
setIcon(m_statusIconDefault);
setToolTip(tr("Syncthing is running"));
break;
case SyncthingStatus::NotificationsAvailable:
setIcon(m_statusIconNotify);
setToolTip(tr("Notifications available"));
break;
case SyncthingStatus::Paused:
setIcon(m_statusIconPause);
setToolTip(tr("At least one device is paused"));
break;
case SyncthingStatus::Synchronizing:
setIcon(m_statusIconSync);
setToolTip(tr("Synchronization is ongoing"));
break;
}
switch(status) {
case SyncthingStatus::Disconnected:
case SyncthingStatus::Synchronizing:
break;
default:
if(m_status == SyncthingStatus::Synchronizing && Settings::notifyOnSyncComplete()) {
showMessage(QCoreApplication::applicationName(), tr("Synchronization complete"), QSystemTrayIcon::Information);
}
}
m_status = status;
}
/*!
* \brief Renders an SVG image to a QPixmap.
* \remarks If instantiating QIcon directly from SVG image the icon is not displayed under Plasma 5. It would work
* with Tint2, tough.
*/
QPixmap TrayIcon::renderSvgImage(const QString &path)
{
QSvgRenderer renderer(path);
QPixmap pm(m_size);
pm.fill(QColor(Qt::transparent));
QPainter painter(&pm);
renderer.render(&painter, pm.rect());
return pm;
}
}

48
gui/trayicon.h Normal file
View File

@ -0,0 +1,48 @@
#ifndef TRAY_ICON_H
#define TRAY_ICON_H
#include "./traymenu.h"
#include <c++utilities/application/global.h>
#include <QSystemTrayIcon>
#include <QIcon>
QT_FORWARD_DECLARE_CLASS(QPixmap)
namespace Data {
enum class SyncthingStatus;
}
namespace QtGui {
class TrayIcon : public QSystemTrayIcon
{
Q_OBJECT
public:
TrayIcon(QObject *parent = nullptr);
private slots:
void handleActivated(QSystemTrayIcon::ActivationReason reason);
void showSyncthingError(const QString &errorMsg);
void showSyncthingNotification(const QString &message);
void updateStatusIconAndText(Data::SyncthingStatus status);
private:
QPixmap renderSvgImage(const QString &path);
const QSize m_size;
const QIcon m_statusIconDisconnected;
const QIcon m_statusIconDefault;
const QIcon m_statusIconNotify;
const QIcon m_statusIconPause;
const QIcon m_statusIconSync;
TrayMenu m_trayMenu;
QMenu m_contextMenu;
Data::SyncthingStatus m_status;
};
}
#endif // TRAY_ICON_H

23
gui/traymenu.cpp Normal file
View File

@ -0,0 +1,23 @@
#include "./traymenu.h"
#include "./traywidget.h"
#include <QHBoxLayout>
namespace QtGui {
TrayMenu::TrayMenu(QWidget *parent) :
QMenu(parent)
{
auto *menuLayout = new QHBoxLayout;
menuLayout->setMargin(0), menuLayout->setSpacing(0);
menuLayout->addWidget(m_trayWidget = new TrayWidget(this));
setLayout(menuLayout);
setPlatformMenu(nullptr);
}
QSize TrayMenu::sizeHint() const
{
return QSize(350, 300);
}
}

31
gui/traymenu.h Normal file
View File

@ -0,0 +1,31 @@
#ifndef TRAY_MENU_H
#define TRAY_MENU_H
#include <QMenu>
namespace QtGui {
class TrayWidget;
class TrayMenu : public QMenu
{
Q_OBJECT
public:
TrayMenu(QWidget *parent = nullptr);
QSize sizeHint() const;
TrayWidget *widget();
private:
TrayWidget *m_trayWidget;
};
inline TrayWidget *TrayMenu::widget()
{
return m_trayWidget;
}
}
#endif // TRAY_MENU_H

View File

@ -1,17 +1,15 @@
#include "./tray.h"
#include "./traywidget.h"
#include "./traymenu.h"
#include "./settingsdialog.h"
#include "./webviewdialog.h"
#include "./dirbuttonsitemdelegate.h"
#include "../application/settings.h"
#include "resources/config.h"
#include "ui_traywidget.h"
#include <qtutilities/resources/qtconfigarguments.h>
#include <qtutilities/resources/resources.h>
#include <qtutilities/resources/importplugin.h>
#include <qtutilities/settingsdialog/qtsettings.h>
#include <qtutilities/aboutdialog/aboutdialog.h>
#include <qtutilities/misc/dialogutils.h>
@ -19,17 +17,10 @@
#include <c++utilities/conversion/stringconversion.h>
#include <QApplication>
#include <QSvgRenderer>
#include <QPainter>
#include <QPixmap>
#include <QMenu>
#include <QCoreApplication>
#include <QDesktopServices>
#include <QMainWindow>
#include <QMessageBox>
#include <QLabel>
#include <QClipboard>
#include <QUrl>
#include <QDir>
#include <QTextBrowser>
#include <QStringBuilder>
@ -98,7 +89,7 @@ TrayWidget::TrayWidget(TrayMenu *parent) :
// connect signals and slots
connect(m_ui->statusPushButton, &QPushButton::clicked, this, &TrayWidget::changeStatus);
connect(m_ui->closePushButton, &QPushButton::clicked, &QApplication::quit);
connect(m_ui->closePushButton, &QPushButton::clicked, &QCoreApplication::quit);
connect(m_ui->aboutPushButton, &QPushButton::clicked, this, &TrayWidget::showAboutDialog);
connect(m_ui->webUiPushButton, &QPushButton::clicked, this, &TrayWidget::showWebUi);
connect(m_ui->settingsPushButton, &QPushButton::clicked, this, &TrayWidget::showSettingsDialog);
@ -266,6 +257,9 @@ void TrayWidget::applySettings()
}
m_connection.reconnect();
m_ui->trafficFrame->setVisible(Settings::showTraffic());
if(Settings::showTraffic()) {
updateTraffic();
}
}
void TrayWidget::openDir(const QModelIndex &dirIndex)
@ -314,10 +308,26 @@ void TrayWidget::changeStatus()
}
}
void TrayWidget::updateTraffic(int totalIncomingTraffic, int totalOutgoingTraffic)
void TrayWidget::updateTraffic()
{
m_ui->inTrafficLabel->setText(totalIncomingTraffic >= 0 ? QString::fromUtf8(dataSizeToString(totalIncomingTraffic).data()) : tr("unknown"));
m_ui->outTrafficLabel->setText(totalOutgoingTraffic >= 0 ? QString::fromUtf8(dataSizeToString(totalOutgoingTraffic).data()) : tr("unknown"));
if(m_ui->trafficFrame->isHidden()) {
return;
}
if(m_connection.totalIncomingRate() != 0.0) {
m_ui->inTrafficLabel->setText(m_connection.totalIncomingTraffic() >= 0
? QStringLiteral("%1 (%2)").arg(QString::fromUtf8(bitrateToString(m_connection.totalIncomingRate(), true).data()), QString::fromUtf8(dataSizeToString(m_connection.totalIncomingTraffic()).data()))
: QString::fromUtf8(bitrateToString(m_connection.totalIncomingRate(), true).data()));
} else {
m_ui->inTrafficLabel->setText(m_connection.totalIncomingTraffic() >= 0 ? QString::fromUtf8(dataSizeToString(m_connection.totalIncomingTraffic()).data()) : tr("unknown"));
}
if(m_connection.totalOutgoingRate() != 0.0) {
m_ui->outTrafficLabel->setText(m_connection.totalIncomingTraffic() >= 0
? QStringLiteral("%1 (%2)").arg(QString::fromUtf8(bitrateToString(m_connection.totalOutgoingRate(), true).data()), QString::fromUtf8(dataSizeToString(m_connection.totalOutgoingTraffic()).data()))
: QString::fromUtf8(bitrateToString(m_connection.totalOutgoingRate(), true).data()));
} else {
m_ui->outTrafficLabel->setText(m_connection.totalOutgoingTraffic() >= 0 ? QString::fromUtf8(dataSizeToString(m_connection.totalOutgoingTraffic()).data()) : tr("unknown"));
}
}
void TrayWidget::handleWebViewDeleted()
@ -325,144 +335,4 @@ void TrayWidget::handleWebViewDeleted()
m_webViewDlg = nullptr;
}
TrayMenu::TrayMenu(QWidget *parent) :
QMenu(parent)
{
auto *menuLayout = new QHBoxLayout;
menuLayout->setMargin(0), menuLayout->setSpacing(0);
menuLayout->addWidget(m_trayWidget = new TrayWidget(this));
setLayout(menuLayout);
setPlatformMenu(nullptr);
}
QSize TrayMenu::sizeHint() const
{
return QSize(350, 300);
}
/*!
* \brief Instantiates a new tray icon.
*/
TrayIcon::TrayIcon(QObject *parent) :
QSystemTrayIcon(parent),
m_size(QSize(128, 128)),
m_statusIconDisconnected(QIcon(renderSvgImage(QStringLiteral(":/icons/hicolor/scalable/status/syncthing-disconnected.svg")))),
m_statusIconDefault(QIcon(renderSvgImage(QStringLiteral(":/icons/hicolor/scalable/status/syncthing-default.svg")))),
m_statusIconNotify(QIcon(renderSvgImage(QStringLiteral(":/icons/hicolor/scalable/status/syncthing-notify.svg")))),
m_statusIconPause(QIcon(renderSvgImage(QStringLiteral(":/icons/hicolor/scalable/status/syncthing-pause.svg")))),
m_statusIconSync(QIcon(renderSvgImage(QStringLiteral(":/icons/hicolor/scalable/status/syncthing-sync.svg")))),
m_status(SyncthingStatus::Disconnected)
{
// 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("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("help-about"), QIcon(QStringLiteral(":/icons/hicolor/scalable/apps/help-about.svg"))), tr("About")), &QAction::triggered, m_trayMenu.widget(), &TrayWidget::showAboutDialog);
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);
setContextMenu(&m_contextMenu);
// set initial status
updateStatusIconAndText(SyncthingStatus::Disconnected);
// connect signals and slots
SyncthingConnection *connection = &(m_trayMenu.widget()->connection());
connect(this, &TrayIcon::activated, this, &TrayIcon::handleActivated);
connect(connection, &SyncthingConnection::error, this, &TrayIcon::showSyncthingError);
connect(connection, &SyncthingConnection::newNotification, this, &TrayIcon::showSyncthingNotification);
connect(connection, &SyncthingConnection::statusChanged, this, &TrayIcon::updateStatusIconAndText);
}
void TrayIcon::handleActivated(QSystemTrayIcon::ActivationReason reason)
{
switch(reason) {
case QSystemTrayIcon::Context:
// can't catch that event on Plasma 5 anyways
break;
case QSystemTrayIcon::Trigger:
// either show web UI or context menu
if(false) {
m_trayMenu.widget()->showWebUi();
} else {
m_trayMenu.resize(m_trayMenu.sizeHint());
// when showing the menu manually
// move the menu to the closest of the currently available screen
// this implies that the tray icon is located near the edge of the screen; otherwise this behavior makes no sense
cornerWidget(&m_trayMenu);
m_trayMenu.show();
}
break;
default:
;
}
}
void TrayIcon::showSyncthingError(const QString &errorMsg)
{
if(Settings::notifyOnErrors()) {
showMessage(tr("Syncthing error"), errorMsg, QSystemTrayIcon::Critical);
}
}
void TrayIcon::showSyncthingNotification(const QString &message)
{
if(Settings::showSyncthingNotifications()) {
showMessage(tr("Syncthing notification"), message, QSystemTrayIcon::Information);
}
}
void TrayIcon::updateStatusIconAndText(SyncthingStatus status)
{
switch(status) {
case SyncthingStatus::Disconnected:
setIcon(m_statusIconDisconnected);
setToolTip(tr("Not connected to Syncthing"));
if(Settings::notifyOnDisconnect()) {
showMessage(QCoreApplication::applicationName(), tr("Disconnected from Syncthing"), QSystemTrayIcon::Warning);
}
break;
case SyncthingStatus::Default:
setIcon(m_statusIconDefault);
setToolTip(tr("Syncthing is running"));
break;
case SyncthingStatus::NotificationsAvailable:
setIcon(m_statusIconNotify);
setToolTip(tr("Notifications available"));
break;
case SyncthingStatus::Paused:
setIcon(m_statusIconPause);
setToolTip(tr("At least one device is paused"));
break;
case SyncthingStatus::Synchronizing:
setIcon(m_statusIconSync);
setToolTip(tr("Synchronization is ongoing"));
break;
}
switch(status) {
case SyncthingStatus::Disconnected:
case SyncthingStatus::Synchronizing:
break;
default:
if(m_status == SyncthingStatus::Synchronizing && Settings::notifyOnSyncComplete()) {
showMessage(QCoreApplication::applicationName(), tr("Synchronization complete"), QSystemTrayIcon::Information);
}
}
m_status = status;
}
/*!
* \brief Renders an SVG image to a QPixmap.
* \remarks If instantiating QIcon directly from SVG image the icon is not displayed under Plasma 5. It would work
* with Tint2, tough.
*/
QPixmap TrayIcon::renderSvgImage(const QString &path)
{
QSvgRenderer renderer(path);
QPixmap pm(m_size);
pm.fill(QColor(Qt::transparent));
QPainter painter(&pm);
renderer.render(&painter, pm.rect());
return pm;
}
}

View File

@ -1,23 +1,20 @@
#ifndef TRAY_H
#define TRAY_H
#ifndef TRAY_WIDGET_H
#define TRAY_WIDGET_H
#include "./webviewprovider.h"
#include "../data/syncthingconnection.h"
#include "../data/syncthingdirectorymodel.h"
#include "../data/syncthingdevicemodel.h"
#include <QWidget>
#include <QSystemTrayIcon>
#include <QMenu>
#include <memory>
QT_FORWARD_DECLARE_CLASS(QString)
QT_FORWARD_DECLARE_CLASS(QPixmap)
namespace ApplicationUtilities {
class QtConfigArguments;
}
namespace Dialogs {
class AboutDialog;
}
@ -27,6 +24,7 @@ namespace QtGui {
class WebViewDialog;
class SettingsDialog;
class TrayMenu;
namespace Ui {
class TrayWidget;
}
@ -55,7 +53,7 @@ private slots:
void scanDir(const QModelIndex &dirIndex);
void pauseResumeDev(const QModelIndex &devIndex);
void changeStatus();
void updateTraffic(int totalIncomingTraffic, int totalOutgoingTraffic);
void updateTraffic();
void handleWebViewDeleted();
private:
@ -76,52 +74,6 @@ inline Data::SyncthingConnection &TrayWidget::connection()
return m_connection;
}
class TrayMenu : public QMenu
{
Q_OBJECT
public:
TrayMenu(QWidget *parent = nullptr);
QSize sizeHint() const;
TrayWidget *widget();
private:
TrayWidget *m_trayWidget;
};
inline TrayWidget *TrayMenu::widget()
{
return m_trayWidget;
}
class TrayIcon : public QSystemTrayIcon
{
Q_OBJECT
public:
TrayIcon(QObject *parent = nullptr);
private slots:
void handleActivated(QSystemTrayIcon::ActivationReason reason);
void showSyncthingError(const QString &errorMsg);
void showSyncthingNotification(const QString &message);
void updateStatusIconAndText(Data::SyncthingStatus status);
private:
QPixmap renderSvgImage(const QString &path);
const QSize m_size;
const QIcon m_statusIconDisconnected;
const QIcon m_statusIconDefault;
const QIcon m_statusIconNotify;
const QIcon m_statusIconPause;
const QIcon m_statusIconSync;
TrayMenu m_trayMenu;
QMenu m_contextMenu;
Data::SyncthingStatus m_status;
};
}
#endif // TRAY_H
#endif // TRAY_WIDGET_H

View File

@ -11,7 +11,11 @@
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
<string>Syncthing Tray</string>
</property>
<property name="windowIcon">
<iconset resource="../resources/icons.qrc">
<normaloff>:/icons/hicolor/scalable/app/syncthingtray.svg</normaloff>:/icons/hicolor/scalable/app/syncthingtray.svg</iconset>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
@ -219,6 +223,9 @@
</item>
<item row="0" column="1">
<widget class="QLabel" name="inTrafficLabel">
<property name="toolTip">
<string>Incoming traffic</string>
</property>
<property name="text">
<string>unknown</string>
</property>
@ -236,6 +243,9 @@
</item>
<item row="1" column="1">
<widget class="QLabel" name="outTrafficLabel">
<property name="toolTip">
<string>Outgoing traffic</string>
</property>
<property name="text">
<string>unknown</string>
</property>
@ -335,6 +345,8 @@
<header>./gui/devview.h</header>
</customwidget>
</customwidgets>
<resources/>
<resources>
<include location="../resources/icons.qrc"/>
</resources>
<connections/>
</ui>

View File

@ -4,89 +4,89 @@
<context>
<name>Data::SyncthingConnection</name>
<message>
<location filename="../data/syncthingconnection.cpp" line="101"/>
<location filename="../data/syncthingconnection.cpp" line="108"/>
<source>disconnected</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../data/syncthingconnection.cpp" line="103"/>
<location filename="../data/syncthingconnection.cpp" line="110"/>
<source>connected</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../data/syncthingconnection.cpp" line="105"/>
<location filename="../data/syncthingconnection.cpp" line="112"/>
<source>connected, notifications available</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../data/syncthingconnection.cpp" line="107"/>
<location filename="../data/syncthingconnection.cpp" line="114"/>
<source>connected, paused</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../data/syncthingconnection.cpp" line="109"/>
<location filename="../data/syncthingconnection.cpp" line="116"/>
<source>connected, synchronizing</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../data/syncthingconnection.cpp" line="111"/>
<location filename="../data/syncthingconnection.cpp" line="118"/>
<source>unknown</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../data/syncthingconnection.cpp" line="386"/>
<location filename="../data/syncthingconnection.cpp" line="393"/>
<source>Unable to parse Syncthing log: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../data/syncthingconnection.cpp" line="390"/>
<location filename="../data/syncthingconnection.cpp" line="397"/>
<source>Unable to request system log: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../data/syncthingconnection.cpp" line="418"/>
<location filename="../data/syncthingconnection.cpp" line="518"/>
<location filename="../data/syncthingconnection.cpp" line="425"/>
<location filename="../data/syncthingconnection.cpp" line="525"/>
<source>Unable to parse Syncthing config: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../data/syncthingconnection.cpp" line="423"/>
<location filename="../data/syncthingconnection.cpp" line="523"/>
<location filename="../data/syncthingconnection.cpp" line="430"/>
<location filename="../data/syncthingconnection.cpp" line="530"/>
<source>Unable to request Syncthing config: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../data/syncthingconnection.cpp" line="580"/>
<location filename="../data/syncthingconnection.cpp" line="605"/>
<source>Unable to parse connections: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../data/syncthingconnection.cpp" line="585"/>
<location filename="../data/syncthingconnection.cpp" line="610"/>
<source>Unable to request connections: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../data/syncthingconnection.cpp" line="626"/>
<location filename="../data/syncthingconnection.cpp" line="657"/>
<source>Unable to parse Syncthing events: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../data/syncthingconnection.cpp" line="648"/>
<location filename="../data/syncthingconnection.cpp" line="679"/>
<source>Unable to request Syncthing events: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../data/syncthingconnection.cpp" line="799"/>
<location filename="../data/syncthingconnection.cpp" line="844"/>
<source>Unable to request rescan: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../data/syncthingconnection.cpp" line="814"/>
<location filename="../data/syncthingconnection.cpp" line="859"/>
<source>Unable to request pause/resume: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../data/syncthingconnection.cpp" line="354"/>
<location filename="../data/syncthingconnection.cpp" line="361"/>
<source>Unable to request QR-Code: </source>
<translation type="unfinished"></translation>
</message>
@ -282,6 +282,19 @@
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QtGui::AutostartOptionPage</name>
<message>
<location filename="../gui/autostartoptionpage.ui" line="6"/>
<source>Autostart</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/autostartoptionpage.ui" line="12"/>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Not implemented yet&lt;/span&gt;&lt;/p&gt;&lt;p&gt;This will allow launching the tray when the desktop environment starts and to launch Syncthing when the tray is started.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QtGui::ConnectionOptionPage</name>
<message>
@ -333,29 +346,36 @@
<context>
<name>QtGui::DevView</name>
<message>
<location filename="../gui/devview.cpp" line="44"/>
<source>Copy</source>
<location filename="../gui/devview.cpp" line="45"/>
<source>Copy value</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/devview.cpp" line="47"/>
<source>Copy name</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/devview.cpp" line="48"/>
<source>Copy ID</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QtGui::DirView</name>
<message>
<location filename="../gui/dirview.cpp" line="44"/>
<source>Copy</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QtGui::LauncherOptionPage</name>
<message>
<location filename="../gui/launcheroptionpage.ui" line="14"/>
<source>Launcher</source>
<location filename="../gui/dirview.cpp" line="45"/>
<source>Copy value</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/launcheroptionpage.ui" line="20"/>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Not implemented yet.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;This will allow launching Syncthing when the tray is started.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<location filename="../gui/dirview.cpp" line="47"/>
<source>Copy label/ID</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/dirview.cpp" line="48"/>
<source>Copy path</source>
<translation type="unfinished"></translation>
</message>
</context>
@ -403,67 +423,67 @@
<context>
<name>QtGui::TrayIcon</name>
<message>
<location filename="../gui/tray.cpp" line="357"/>
<location filename="../gui/trayicon.cpp" line="33"/>
<source>Web UI</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tray.cpp" line="358"/>
<location filename="../gui/trayicon.cpp" line="34"/>
<source>Settings</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tray.cpp" line="359"/>
<location filename="../gui/trayicon.cpp" line="35"/>
<source>About</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tray.cpp" line="361"/>
<location filename="../gui/trayicon.cpp" line="37"/>
<source>Close</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tray.cpp" line="402"/>
<location filename="../gui/trayicon.cpp" line="78"/>
<source>Syncthing error</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tray.cpp" line="409"/>
<location filename="../gui/trayicon.cpp" line="85"/>
<source>Syncthing notification</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tray.cpp" line="418"/>
<location filename="../gui/trayicon.cpp" line="94"/>
<source>Not connected to Syncthing</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tray.cpp" line="420"/>
<location filename="../gui/trayicon.cpp" line="96"/>
<source>Disconnected from Syncthing</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tray.cpp" line="425"/>
<location filename="../gui/trayicon.cpp" line="101"/>
<source>Syncthing is running</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tray.cpp" line="429"/>
<location filename="../gui/trayicon.cpp" line="105"/>
<source>Notifications available</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tray.cpp" line="433"/>
<location filename="../gui/trayicon.cpp" line="109"/>
<source>At least one device is paused</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tray.cpp" line="437"/>
<location filename="../gui/trayicon.cpp" line="113"/>
<source>Synchronization is ongoing</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tray.cpp" line="446"/>
<location filename="../gui/trayicon.cpp" line="122"/>
<source>Synchronization complete</source>
<translation type="unfinished"></translation>
</message>
@ -471,146 +491,156 @@
<context>
<name>QtGui::TrayWidget</name>
<message>
<location filename="../gui/traywidget.ui" line="14"/>
<source>Form</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/traywidget.ui" line="62"/>
<location filename="../gui/traywidget.ui" line="66"/>
<source>Close</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/traywidget.ui" line="103"/>
<location filename="../gui/tray.cpp" line="239"/>
<location filename="../gui/traywidget.ui" line="107"/>
<location filename="../gui/traywidget.cpp" line="230"/>
<source>Connect</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/traywidget.ui" line="191"/>
<location filename="../gui/traywidget.ui" line="195"/>
<source>Traffic</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/traywidget.ui" line="216"/>
<location filename="../gui/traywidget.ui" line="220"/>
<source>In</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/traywidget.ui" line="223"/>
<location filename="../gui/traywidget.ui" line="240"/>
<location filename="../gui/tray.cpp" line="319"/>
<location filename="../gui/tray.cpp" line="320"/>
<source>unknown</source>
<location filename="../gui/traywidget.ui" line="227"/>
<source>Incoming traffic</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/traywidget.ui" line="247"/>
<source>Outgoing traffic</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/traywidget.ui" line="230"/>
<location filename="../gui/traywidget.ui" line="250"/>
<location filename="../gui/traywidget.cpp" line="321"/>
<location filename="../gui/traywidget.cpp" line="328"/>
<source>unknown</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/traywidget.ui" line="14"/>
<source>Syncthing Tray</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/traywidget.ui" line="237"/>
<source>Out</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/traywidget.ui" line="270"/>
<location filename="../gui/traywidget.ui" line="280"/>
<source>Directories</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/traywidget.ui" line="299"/>
<location filename="../gui/traywidget.ui" line="309"/>
<source>Devices</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/traywidget.ui" line="76"/>
<location filename="../gui/traywidget.ui" line="80"/>
<source>About</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/traywidget.ui" line="130"/>
<location filename="../gui/traywidget.ui" line="134"/>
<source>Settings</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/traywidget.ui" line="144"/>
<location filename="../gui/traywidget.ui" line="148"/>
<source>Web UI</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tray.cpp" line="79"/>
<location filename="../gui/traywidget.cpp" line="70"/>
<source>View own device ID</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tray.cpp" line="121"/>
<location filename="../gui/traywidget.cpp" line="112"/>
<source>Settings - Syncthing tray</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tray.cpp" line="140"/>
<location filename="../gui/traywidget.cpp" line="131"/>
<source>Tray application for Syncthing</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tray.cpp" line="90"/>
<location filename="../gui/traywidget.cpp" line="81"/>
<source>Rescan all directories</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tray.cpp" line="84"/>
<location filename="../gui/traywidget.cpp" line="75"/>
<source>Show Syncthing log</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tray.cpp" line="141"/>
<location filename="../gui/traywidget.cpp" line="132"/>
<source>About - Syncthing Tray</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tray.cpp" line="179"/>
<location filename="../gui/traywidget.cpp" line="170"/>
<source>Own device ID - Syncthing Tray</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tray.cpp" line="189"/>
<location filename="../gui/traywidget.cpp" line="180"/>
<source>device ID is unknown</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tray.cpp" line="197"/>
<location filename="../gui/traywidget.cpp" line="188"/>
<source>Copy to clipboard</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tray.cpp" line="213"/>
<location filename="../gui/traywidget.cpp" line="204"/>
<source>Log - Syncthing</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tray.cpp" line="240"/>
<location filename="../gui/traywidget.cpp" line="231"/>
<source>Not connected to Syncthing, click to connect</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tray.cpp" line="246"/>
<location filename="../gui/traywidget.cpp" line="237"/>
<source>Pause</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tray.cpp" line="247"/>
<location filename="../gui/traywidget.cpp" line="238"/>
<source>Syncthing is running, click to pause all devices</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tray.cpp" line="252"/>
<location filename="../gui/traywidget.cpp" line="243"/>
<source>At least one device is paused, click to resume</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tray.cpp" line="251"/>
<location filename="../gui/traywidget.cpp" line="242"/>
<source>Continue</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tray.cpp" line="277"/>
<location filename="../gui/traywidget.cpp" line="271"/>
<source>The directly &lt;i&gt;%1&lt;/i&gt; does not exist on the local machine.</source>
<translation type="unfinished"></translation>
</message>
@ -666,12 +696,12 @@ The Web UI will be opened in the default web browser instead.</source>
<context>
<name>main</name>
<message>
<location filename="../application/main.cpp" line="50"/>
<location filename="../application/main.cpp" line="61"/>
<source>The system tray is (currently) not available.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../application/main.cpp" line="54"/>
<location filename="../application/main.cpp" line="65"/>
<source>The Qt libraries have not been built with tray icon support.</source>
<translation type="unfinished"></translation>
</message>

View File

@ -4,89 +4,89 @@
<context>
<name>Data::SyncthingConnection</name>
<message>
<location filename="../data/syncthingconnection.cpp" line="101"/>
<location filename="../data/syncthingconnection.cpp" line="108"/>
<source>disconnected</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../data/syncthingconnection.cpp" line="103"/>
<location filename="../data/syncthingconnection.cpp" line="110"/>
<source>connected</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../data/syncthingconnection.cpp" line="105"/>
<location filename="../data/syncthingconnection.cpp" line="112"/>
<source>connected, notifications available</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../data/syncthingconnection.cpp" line="107"/>
<location filename="../data/syncthingconnection.cpp" line="114"/>
<source>connected, paused</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../data/syncthingconnection.cpp" line="109"/>
<location filename="../data/syncthingconnection.cpp" line="116"/>
<source>connected, synchronizing</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../data/syncthingconnection.cpp" line="111"/>
<location filename="../data/syncthingconnection.cpp" line="118"/>
<source>unknown</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../data/syncthingconnection.cpp" line="386"/>
<location filename="../data/syncthingconnection.cpp" line="393"/>
<source>Unable to parse Syncthing log: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../data/syncthingconnection.cpp" line="390"/>
<location filename="../data/syncthingconnection.cpp" line="397"/>
<source>Unable to request system log: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../data/syncthingconnection.cpp" line="418"/>
<location filename="../data/syncthingconnection.cpp" line="518"/>
<location filename="../data/syncthingconnection.cpp" line="425"/>
<location filename="../data/syncthingconnection.cpp" line="525"/>
<source>Unable to parse Syncthing config: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../data/syncthingconnection.cpp" line="423"/>
<location filename="../data/syncthingconnection.cpp" line="523"/>
<location filename="../data/syncthingconnection.cpp" line="430"/>
<location filename="../data/syncthingconnection.cpp" line="530"/>
<source>Unable to request Syncthing config: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../data/syncthingconnection.cpp" line="580"/>
<location filename="../data/syncthingconnection.cpp" line="605"/>
<source>Unable to parse connections: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../data/syncthingconnection.cpp" line="585"/>
<location filename="../data/syncthingconnection.cpp" line="610"/>
<source>Unable to request connections: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../data/syncthingconnection.cpp" line="626"/>
<location filename="../data/syncthingconnection.cpp" line="657"/>
<source>Unable to parse Syncthing events: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../data/syncthingconnection.cpp" line="648"/>
<location filename="../data/syncthingconnection.cpp" line="679"/>
<source>Unable to request Syncthing events: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../data/syncthingconnection.cpp" line="799"/>
<location filename="../data/syncthingconnection.cpp" line="844"/>
<source>Unable to request rescan: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../data/syncthingconnection.cpp" line="814"/>
<location filename="../data/syncthingconnection.cpp" line="859"/>
<source>Unable to request pause/resume: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../data/syncthingconnection.cpp" line="354"/>
<location filename="../data/syncthingconnection.cpp" line="361"/>
<source>Unable to request QR-Code: </source>
<translation type="unfinished"></translation>
</message>
@ -282,6 +282,19 @@
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QtGui::AutostartOptionPage</name>
<message>
<location filename="../gui/autostartoptionpage.ui" line="6"/>
<source>Autostart</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/autostartoptionpage.ui" line="12"/>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Not implemented yet&lt;/span&gt;&lt;/p&gt;&lt;p&gt;This will allow launching the tray when the desktop environment starts and to launch Syncthing when the tray is started.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QtGui::ConnectionOptionPage</name>
<message>
@ -333,29 +346,36 @@
<context>
<name>QtGui::DevView</name>
<message>
<location filename="../gui/devview.cpp" line="44"/>
<source>Copy</source>
<location filename="../gui/devview.cpp" line="45"/>
<source>Copy value</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/devview.cpp" line="47"/>
<source>Copy name</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/devview.cpp" line="48"/>
<source>Copy ID</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QtGui::DirView</name>
<message>
<location filename="../gui/dirview.cpp" line="44"/>
<source>Copy</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QtGui::LauncherOptionPage</name>
<message>
<location filename="../gui/launcheroptionpage.ui" line="14"/>
<source>Launcher</source>
<location filename="../gui/dirview.cpp" line="45"/>
<source>Copy value</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/launcheroptionpage.ui" line="20"/>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Not implemented yet.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;This will allow launching Syncthing when the tray is started.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<location filename="../gui/dirview.cpp" line="47"/>
<source>Copy label/ID</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/dirview.cpp" line="48"/>
<source>Copy path</source>
<translation type="unfinished"></translation>
</message>
</context>
@ -403,67 +423,67 @@
<context>
<name>QtGui::TrayIcon</name>
<message>
<location filename="../gui/tray.cpp" line="357"/>
<location filename="../gui/trayicon.cpp" line="33"/>
<source>Web UI</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tray.cpp" line="358"/>
<location filename="../gui/trayicon.cpp" line="34"/>
<source>Settings</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tray.cpp" line="359"/>
<location filename="../gui/trayicon.cpp" line="35"/>
<source>About</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tray.cpp" line="361"/>
<location filename="../gui/trayicon.cpp" line="37"/>
<source>Close</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tray.cpp" line="402"/>
<location filename="../gui/trayicon.cpp" line="78"/>
<source>Syncthing error</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tray.cpp" line="409"/>
<location filename="../gui/trayicon.cpp" line="85"/>
<source>Syncthing notification</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tray.cpp" line="418"/>
<location filename="../gui/trayicon.cpp" line="94"/>
<source>Not connected to Syncthing</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tray.cpp" line="420"/>
<location filename="../gui/trayicon.cpp" line="96"/>
<source>Disconnected from Syncthing</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tray.cpp" line="425"/>
<location filename="../gui/trayicon.cpp" line="101"/>
<source>Syncthing is running</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tray.cpp" line="429"/>
<location filename="../gui/trayicon.cpp" line="105"/>
<source>Notifications available</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tray.cpp" line="433"/>
<location filename="../gui/trayicon.cpp" line="109"/>
<source>At least one device is paused</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tray.cpp" line="437"/>
<location filename="../gui/trayicon.cpp" line="113"/>
<source>Synchronization is ongoing</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tray.cpp" line="446"/>
<location filename="../gui/trayicon.cpp" line="122"/>
<source>Synchronization complete</source>
<translation type="unfinished"></translation>
</message>
@ -471,146 +491,156 @@
<context>
<name>QtGui::TrayWidget</name>
<message>
<location filename="../gui/traywidget.ui" line="14"/>
<source>Form</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/traywidget.ui" line="62"/>
<location filename="../gui/traywidget.ui" line="66"/>
<source>Close</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/traywidget.ui" line="103"/>
<location filename="../gui/tray.cpp" line="239"/>
<location filename="../gui/traywidget.ui" line="107"/>
<location filename="../gui/traywidget.cpp" line="230"/>
<source>Connect</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/traywidget.ui" line="191"/>
<location filename="../gui/traywidget.ui" line="195"/>
<source>Traffic</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/traywidget.ui" line="216"/>
<location filename="../gui/traywidget.ui" line="220"/>
<source>In</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/traywidget.ui" line="223"/>
<location filename="../gui/traywidget.ui" line="240"/>
<location filename="../gui/tray.cpp" line="319"/>
<location filename="../gui/tray.cpp" line="320"/>
<source>unknown</source>
<location filename="../gui/traywidget.ui" line="227"/>
<source>Incoming traffic</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/traywidget.ui" line="247"/>
<source>Outgoing traffic</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/traywidget.ui" line="230"/>
<location filename="../gui/traywidget.ui" line="250"/>
<location filename="../gui/traywidget.cpp" line="321"/>
<location filename="../gui/traywidget.cpp" line="328"/>
<source>unknown</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/traywidget.ui" line="14"/>
<source>Syncthing Tray</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/traywidget.ui" line="237"/>
<source>Out</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/traywidget.ui" line="270"/>
<location filename="../gui/traywidget.ui" line="280"/>
<source>Directories</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/traywidget.ui" line="299"/>
<location filename="../gui/traywidget.ui" line="309"/>
<source>Devices</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/traywidget.ui" line="76"/>
<location filename="../gui/traywidget.ui" line="80"/>
<source>About</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/traywidget.ui" line="130"/>
<location filename="../gui/traywidget.ui" line="134"/>
<source>Settings</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/traywidget.ui" line="144"/>
<location filename="../gui/traywidget.ui" line="148"/>
<source>Web UI</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tray.cpp" line="79"/>
<location filename="../gui/traywidget.cpp" line="70"/>
<source>View own device ID</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tray.cpp" line="121"/>
<location filename="../gui/traywidget.cpp" line="112"/>
<source>Settings - Syncthing tray</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tray.cpp" line="140"/>
<location filename="../gui/traywidget.cpp" line="131"/>
<source>Tray application for Syncthing</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tray.cpp" line="90"/>
<location filename="../gui/traywidget.cpp" line="81"/>
<source>Rescan all directories</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tray.cpp" line="84"/>
<location filename="../gui/traywidget.cpp" line="75"/>
<source>Show Syncthing log</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tray.cpp" line="141"/>
<location filename="../gui/traywidget.cpp" line="132"/>
<source>About - Syncthing Tray</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tray.cpp" line="179"/>
<location filename="../gui/traywidget.cpp" line="170"/>
<source>Own device ID - Syncthing Tray</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tray.cpp" line="189"/>
<location filename="../gui/traywidget.cpp" line="180"/>
<source>device ID is unknown</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tray.cpp" line="197"/>
<location filename="../gui/traywidget.cpp" line="188"/>
<source>Copy to clipboard</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tray.cpp" line="213"/>
<location filename="../gui/traywidget.cpp" line="204"/>
<source>Log - Syncthing</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tray.cpp" line="240"/>
<location filename="../gui/traywidget.cpp" line="231"/>
<source>Not connected to Syncthing, click to connect</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tray.cpp" line="246"/>
<location filename="../gui/traywidget.cpp" line="237"/>
<source>Pause</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tray.cpp" line="247"/>
<location filename="../gui/traywidget.cpp" line="238"/>
<source>Syncthing is running, click to pause all devices</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tray.cpp" line="252"/>
<location filename="../gui/traywidget.cpp" line="243"/>
<source>At least one device is paused, click to resume</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tray.cpp" line="251"/>
<location filename="../gui/traywidget.cpp" line="242"/>
<source>Continue</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/tray.cpp" line="277"/>
<location filename="../gui/traywidget.cpp" line="271"/>
<source>The directly &lt;i&gt;%1&lt;/i&gt; does not exist on the local machine.</source>
<translation type="unfinished"></translation>
</message>
@ -666,12 +696,12 @@ The Web UI will be opened in the default web browser instead.</source>
<context>
<name>main</name>
<message>
<location filename="../application/main.cpp" line="50"/>
<location filename="../application/main.cpp" line="61"/>
<source>The system tray is (currently) not available.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../application/main.cpp" line="54"/>
<location filename="../application/main.cpp" line="65"/>
<source>The Qt libraries have not been built with tray icon support.</source>
<translation type="unfinished"></translation>
</message>