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

View File

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

View File

@ -1,5 +1,7 @@
#include "./syncthingconnection.h" #include "./syncthingconnection.h"
#include <c++utilities/conversion/conversionexception.h>
#include <QNetworkAccessManager> #include <QNetworkAccessManager>
#include <QNetworkReply> #include <QNetworkReply>
#include <QUrlQuery> #include <QUrlQuery>
@ -10,10 +12,13 @@
#include <QPixmap> #include <QPixmap>
#include <QAuthenticator> #include <QAuthenticator>
#include <QStringBuilder> #include <QStringBuilder>
#include <QTimer>
#include <utility> #include <utility>
using namespace std; using namespace std;
using namespace ChronoUtilities;
using namespace ConversionUtilities;
namespace Data { namespace Data {
@ -75,6 +80,8 @@ SyncthingConnection::SyncthingConnection(const QString &syncthingUrl, const QByt
m_lastEventId(0), m_lastEventId(0),
m_totalIncomingTraffic(0), m_totalIncomingTraffic(0),
m_totalOutgoingTraffic(0), m_totalOutgoingTraffic(0),
m_totalIncomingRate(0),
m_totalOutgoingRate(0),
m_configReply(nullptr), m_configReply(nullptr),
m_statusReply(nullptr), m_statusReply(nullptr),
m_eventsReply(nullptr), m_eventsReply(nullptr),
@ -542,9 +549,20 @@ void SyncthingConnection::readConnections()
if(jsonError.error == QJsonParseError::NoError) { if(jsonError.error == QJsonParseError::NoError) {
const QJsonObject replyObj(replyDoc.object()); const QJsonObject replyObj(replyDoc.object());
const QJsonObject totalObj(replyObj.value(QStringLiteral("total")).toObject()); const QJsonObject totalObj(replyObj.value(QStringLiteral("total")).toObject());
m_totalIncomingTraffic = totalObj.value(QStringLiteral("inBytesTotal")).toInt(0);
m_totalOutgoingTraffic = totalObj.value(QStringLiteral("outBytesTotal")).toInt(0); // read traffic
emit trafficChanged(m_totalIncomingTraffic, m_totalOutgoingTraffic); 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()); const QJsonObject connectionsObj(replyObj.value(QStringLiteral("connections")).toObject());
int index = 0; int index = 0;
for(SyncthingDev &dev : m_devs) { for(SyncthingDev &dev : m_devs) {
@ -576,7 +594,13 @@ void SyncthingConnection::readConnections()
} }
++index; ++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 { } else {
emit error(tr("Unable to parse connections: ") + jsonError.errorString()); emit error(tr("Unable to parse connections: ") + jsonError.errorString());
} }
@ -609,7 +633,12 @@ void SyncthingConnection::readEvents()
for(const QJsonValue &eventVal : replyArray) { for(const QJsonValue &eventVal : replyArray) {
const QJsonObject event = eventVal.toObject(); const QJsonObject event = eventVal.toObject();
m_lastEventId = event.value(QStringLiteral("id")).toInt(m_lastEventId); 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 QString eventType(event.value(QStringLiteral("type")).toString());
const QJsonObject eventData(event.value(QStringLiteral("data")).toObject()); const QJsonObject eventData(event.value(QStringLiteral("data")).toObject());
if(eventType == QLatin1String("Starting")) { if(eventType == QLatin1String("Starting")) {
@ -731,7 +760,7 @@ void SyncthingConnection::readDirEvent(const QString &eventType, const QJsonObje
dirInfo->localFiles = summary.value(QStringLiteral("localFiles")).toInt(); dirInfo->localFiles = summary.value(QStringLiteral("localFiles")).toInt();
dirInfo->neededByted = summary.value(QStringLiteral("needByted")).toInt(); dirInfo->neededByted = summary.value(QStringLiteral("needByted")).toInt();
dirInfo->neededFiles = summary.value(QStringLiteral("needFiles")).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); emit dirStatusChanged(*dirInfo, index);
} }
} else if(eventType == QLatin1String("FolderCompletion")) { } else if(eventType == QLatin1String("FolderCompletion")) {
@ -743,6 +772,16 @@ void SyncthingConnection::readDirEvent(const QString &eventType, const QJsonObje
// just show the smallest percentage for now // just show the smallest percentage for now
dirInfo->progressPercentage = percentage; 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(). * \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 return; // ignore device events happened before the last connections update
} }
const QString dev(eventData.value(QStringLiteral("device")).toString()); const QString dev(eventData.value(QStringLiteral("device")).toString());
@ -773,6 +812,7 @@ void SyncthingConnection::readDeviceEvent(const QDateTime &eventTime, const QStr
status = DevStatus::Rejected; status = DevStatus::Rejected;
} else if(eventType == QLatin1String("DeviceResumed")) { } else if(eventType == QLatin1String("DeviceResumed")) {
paused = false; paused = false;
status = DevStatus::Disconnected; // FIXME: correct to assume device which has just been resumed is still disconnected?
} else if(eventType == QLatin1String("DeviceDiscovered")) { } else if(eventType == QLatin1String("DeviceDiscovered")) {
// we know about this device already, set status anyways because it might still be unknown // we know about this device already, set status anyways because it might still be unknown
status = DevStatus::Disconnected; status = DevStatus::Disconnected;

View File

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

View File

@ -41,7 +41,12 @@ void DirView::showContextMenu()
{ {
if(selectionModel() && selectionModel()->selectedRows(0).size() == 1) { if(selectionModel() && selectionModel()->selectedRows(0).size() == 1) {
QMenu menu; 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()); 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: private Q_SLOTS:
void showContextMenu(); void showContextMenu();
void copySelectedItem(); 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_connectionoptionpage.h"
#include "ui_notificationsoptionpage.h" #include "ui_notificationsoptionpage.h"
#include "ui_appearanceoptionpage.h" #include "ui_appearanceoptionpage.h"
#include "ui_launcheroptionpage.h" #include "ui_autostartoptionpage.h"
#include "ui_webviewoptionpage.h" #include "ui_webviewoptionpage.h"
#include <tagparser/mediafileinfo.h> #include <tagparser/mediafileinfo.h>
@ -138,21 +138,21 @@ void AppearanceOptionPage::reset()
} }
// LauncherOptionPage // LauncherOptionPage
LauncherOptionPage::LauncherOptionPage(QWidget *parentWidget) : AutostartOptionPage::AutostartOptionPage(QWidget *parentWidget) :
LauncherOptionPageBase(parentWidget) AutostartOptionPageBase(parentWidget)
{} {}
LauncherOptionPage::~LauncherOptionPage() AutostartOptionPage::~AutostartOptionPage()
{} {}
bool LauncherOptionPage::apply() bool AutostartOptionPage::apply()
{ {
if(hasBeenShown()) { if(hasBeenShown()) {
} }
return true; return true;
} }
void LauncherOptionPage::reset() void AutostartOptionPage::reset()
{ {
if(hasBeenShown()) { if(hasBeenShown()) {
} }
@ -211,7 +211,7 @@ SettingsDialog::SettingsDialog(Data::SyncthingConnection *connection, QWidget *p
category->setDisplayName(tr("Tray")); category->setDisplayName(tr("Tray"));
category->assignPages(QList<Dialogs::OptionPage *>() category->assignPages(QList<Dialogs::OptionPage *>()
<< new ConnectionOptionPage(connection) << new NotificationsOptionPage << new ConnectionOptionPage(connection) << new NotificationsOptionPage
<< new AppearanceOptionPage << new LauncherOptionPage); << new AppearanceOptionPage << new AutostartOptionPage);
category->setIcon(QIcon(QStringLiteral(":/icons/hicolor/scalable/app/syncthingtray.svg"))); category->setIcon(QIcon(QStringLiteral(":/icons/hicolor/scalable/app/syncthingtray.svg")));
categories << category; 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(AppearanceOptionPage)
DECLARE_UI_FILE_BASED_OPTION_PAGE(LauncherOptionPage) DECLARE_UI_FILE_BASED_OPTION_PAGE(AutostartOptionPage)
#if defined(SYNCTHINGTRAY_USE_WEBENGINE) || defined(SYNCTHINGTRAY_USE_WEBKIT) #if defined(SYNCTHINGTRAY_USE_WEBENGINE) || defined(SYNCTHINGTRAY_USE_WEBKIT)
DECLARE_UI_FILE_BASED_OPTION_PAGE(WebViewOptionPage) 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 "./settingsdialog.h"
#include "./webviewdialog.h" #include "./webviewdialog.h"
#include "./dirbuttonsitemdelegate.h"
#include "../application/settings.h" #include "../application/settings.h"
#include "resources/config.h" #include "resources/config.h"
#include "ui_traywidget.h" #include "ui_traywidget.h"
#include <qtutilities/resources/qtconfigarguments.h> #include <qtutilities/resources/qtconfigarguments.h>
#include <qtutilities/resources/resources.h> #include <qtutilities/resources/resources.h>
#include <qtutilities/resources/importplugin.h>
#include <qtutilities/settingsdialog/qtsettings.h> #include <qtutilities/settingsdialog/qtsettings.h>
#include <qtutilities/aboutdialog/aboutdialog.h> #include <qtutilities/aboutdialog/aboutdialog.h>
#include <qtutilities/misc/dialogutils.h> #include <qtutilities/misc/dialogutils.h>
@ -19,17 +17,10 @@
#include <c++utilities/conversion/stringconversion.h> #include <c++utilities/conversion/stringconversion.h>
#include <QApplication> #include <QCoreApplication>
#include <QSvgRenderer>
#include <QPainter>
#include <QPixmap>
#include <QMenu>
#include <QDesktopServices> #include <QDesktopServices>
#include <QMainWindow>
#include <QMessageBox> #include <QMessageBox>
#include <QLabel>
#include <QClipboard> #include <QClipboard>
#include <QUrl>
#include <QDir> #include <QDir>
#include <QTextBrowser> #include <QTextBrowser>
#include <QStringBuilder> #include <QStringBuilder>
@ -98,7 +89,7 @@ TrayWidget::TrayWidget(TrayMenu *parent) :
// connect signals and slots // connect signals and slots
connect(m_ui->statusPushButton, &QPushButton::clicked, this, &TrayWidget::changeStatus); 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->aboutPushButton, &QPushButton::clicked, this, &TrayWidget::showAboutDialog);
connect(m_ui->webUiPushButton, &QPushButton::clicked, this, &TrayWidget::showWebUi); connect(m_ui->webUiPushButton, &QPushButton::clicked, this, &TrayWidget::showWebUi);
connect(m_ui->settingsPushButton, &QPushButton::clicked, this, &TrayWidget::showSettingsDialog); connect(m_ui->settingsPushButton, &QPushButton::clicked, this, &TrayWidget::showSettingsDialog);
@ -266,6 +257,9 @@ void TrayWidget::applySettings()
} }
m_connection.reconnect(); m_connection.reconnect();
m_ui->trafficFrame->setVisible(Settings::showTraffic()); m_ui->trafficFrame->setVisible(Settings::showTraffic());
if(Settings::showTraffic()) {
updateTraffic();
}
} }
void TrayWidget::openDir(const QModelIndex &dirIndex) 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")); if(m_ui->trafficFrame->isHidden()) {
m_ui->outTrafficLabel->setText(totalOutgoingTraffic >= 0 ? QString::fromUtf8(dataSizeToString(totalOutgoingTraffic).data()) : tr("unknown")); 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() void TrayWidget::handleWebViewDeleted()
@ -325,144 +335,4 @@ void TrayWidget::handleWebViewDeleted()
m_webViewDlg = nullptr; 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 #ifndef TRAY_WIDGET_H
#define TRAY_H #define TRAY_WIDGET_H
#include "./webviewprovider.h" #include "./webviewprovider.h"
#include "../data/syncthingconnection.h" #include "../data/syncthingconnection.h"
#include "../data/syncthingdirectorymodel.h" #include "../data/syncthingdirectorymodel.h"
#include "../data/syncthingdevicemodel.h" #include "../data/syncthingdevicemodel.h"
#include <QWidget> #include <QWidget>
#include <QSystemTrayIcon>
#include <QMenu>
#include <memory> #include <memory>
QT_FORWARD_DECLARE_CLASS(QString)
QT_FORWARD_DECLARE_CLASS(QPixmap)
namespace ApplicationUtilities { namespace ApplicationUtilities {
class QtConfigArguments; class QtConfigArguments;
} }
namespace Dialogs { namespace Dialogs {
class AboutDialog; class AboutDialog;
} }
@ -27,6 +24,7 @@ namespace QtGui {
class WebViewDialog; class WebViewDialog;
class SettingsDialog; class SettingsDialog;
class TrayMenu; class TrayMenu;
namespace Ui { namespace Ui {
class TrayWidget; class TrayWidget;
} }
@ -55,7 +53,7 @@ private slots:
void scanDir(const QModelIndex &dirIndex); void scanDir(const QModelIndex &dirIndex);
void pauseResumeDev(const QModelIndex &devIndex); void pauseResumeDev(const QModelIndex &devIndex);
void changeStatus(); void changeStatus();
void updateTraffic(int totalIncomingTraffic, int totalOutgoingTraffic); void updateTraffic();
void handleWebViewDeleted(); void handleWebViewDeleted();
private: private:
@ -76,52 +74,6 @@ inline Data::SyncthingConnection &TrayWidget::connection()
return m_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 #endif // TRAY_WIDGET_H
{
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

View File

@ -11,7 +11,11 @@
</rect> </rect>
</property> </property>
<property name="windowTitle"> <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> </property>
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing"> <property name="spacing">
@ -219,6 +223,9 @@
</item> </item>
<item row="0" column="1"> <item row="0" column="1">
<widget class="QLabel" name="inTrafficLabel"> <widget class="QLabel" name="inTrafficLabel">
<property name="toolTip">
<string>Incoming traffic</string>
</property>
<property name="text"> <property name="text">
<string>unknown</string> <string>unknown</string>
</property> </property>
@ -236,6 +243,9 @@
</item> </item>
<item row="1" column="1"> <item row="1" column="1">
<widget class="QLabel" name="outTrafficLabel"> <widget class="QLabel" name="outTrafficLabel">
<property name="toolTip">
<string>Outgoing traffic</string>
</property>
<property name="text"> <property name="text">
<string>unknown</string> <string>unknown</string>
</property> </property>
@ -335,6 +345,8 @@
<header>./gui/devview.h</header> <header>./gui/devview.h</header>
</customwidget> </customwidget>
</customwidgets> </customwidgets>
<resources/> <resources>
<include location="../resources/icons.qrc"/>
</resources>
<connections/> <connections/>
</ui> </ui>

View File

@ -4,89 +4,89 @@
<context> <context>
<name>Data::SyncthingConnection</name> <name>Data::SyncthingConnection</name>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="101"/> <location filename="../data/syncthingconnection.cpp" line="108"/>
<source>disconnected</source> <source>disconnected</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="103"/> <location filename="../data/syncthingconnection.cpp" line="110"/>
<source>connected</source> <source>connected</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="105"/> <location filename="../data/syncthingconnection.cpp" line="112"/>
<source>connected, notifications available</source> <source>connected, notifications available</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="107"/> <location filename="../data/syncthingconnection.cpp" line="114"/>
<source>connected, paused</source> <source>connected, paused</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="109"/> <location filename="../data/syncthingconnection.cpp" line="116"/>
<source>connected, synchronizing</source> <source>connected, synchronizing</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="111"/> <location filename="../data/syncthingconnection.cpp" line="118"/>
<source>unknown</source> <source>unknown</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="386"/> <location filename="../data/syncthingconnection.cpp" line="393"/>
<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="390"/> <location filename="../data/syncthingconnection.cpp" line="397"/>
<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="418"/> <location filename="../data/syncthingconnection.cpp" line="425"/>
<location filename="../data/syncthingconnection.cpp" line="518"/> <location filename="../data/syncthingconnection.cpp" line="525"/>
<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="423"/> <location filename="../data/syncthingconnection.cpp" line="430"/>
<location filename="../data/syncthingconnection.cpp" line="523"/> <location filename="../data/syncthingconnection.cpp" line="530"/>
<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="580"/> <location filename="../data/syncthingconnection.cpp" line="605"/>
<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="585"/> <location filename="../data/syncthingconnection.cpp" line="610"/>
<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="626"/> <location filename="../data/syncthingconnection.cpp" line="657"/>
<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="648"/> <location filename="../data/syncthingconnection.cpp" line="679"/>
<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="799"/> <location filename="../data/syncthingconnection.cpp" line="844"/>
<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="814"/> <location filename="../data/syncthingconnection.cpp" line="859"/>
<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="354"/> <location filename="../data/syncthingconnection.cpp" line="361"/>
<source>Unable to request QR-Code: </source> <source>Unable to request QR-Code: </source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -282,6 +282,19 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
</context> </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> <context>
<name>QtGui::ConnectionOptionPage</name> <name>QtGui::ConnectionOptionPage</name>
<message> <message>
@ -333,29 +346,36 @@
<context> <context>
<name>QtGui::DevView</name> <name>QtGui::DevView</name>
<message> <message>
<location filename="../gui/devview.cpp" line="44"/> <location filename="../gui/devview.cpp" line="45"/>
<source>Copy</source> <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> <translation type="unfinished"></translation>
</message> </message>
</context> </context>
<context> <context>
<name>QtGui::DirView</name> <name>QtGui::DirView</name>
<message> <message>
<location filename="../gui/dirview.cpp" line="44"/> <location filename="../gui/dirview.cpp" line="45"/>
<source>Copy</source> <source>Copy value</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QtGui::LauncherOptionPage</name>
<message>
<location filename="../gui/launcheroptionpage.ui" line="14"/>
<source>Launcher</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/launcheroptionpage.ui" line="20"/> <location filename="../gui/dirview.cpp" line="47"/>
<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> <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> <translation type="unfinished"></translation>
</message> </message>
</context> </context>
@ -403,67 +423,67 @@
<context> <context>
<name>QtGui::TrayIcon</name> <name>QtGui::TrayIcon</name>
<message> <message>
<location filename="../gui/tray.cpp" line="357"/> <location filename="../gui/trayicon.cpp" line="33"/>
<source>Web UI</source> <source>Web UI</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/tray.cpp" line="358"/> <location filename="../gui/trayicon.cpp" line="34"/>
<source>Settings</source> <source>Settings</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/tray.cpp" line="359"/> <location filename="../gui/trayicon.cpp" line="35"/>
<source>About</source> <source>About</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/tray.cpp" line="361"/> <location filename="../gui/trayicon.cpp" line="37"/>
<source>Close</source> <source>Close</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/tray.cpp" line="402"/> <location filename="../gui/trayicon.cpp" line="78"/>
<source>Syncthing error</source> <source>Syncthing error</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/tray.cpp" line="409"/> <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/tray.cpp" line="418"/> <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/tray.cpp" line="420"/> <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/tray.cpp" line="425"/> <location filename="../gui/trayicon.cpp" line="101"/>
<source>Syncthing is running</source> <source>Syncthing is running</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/tray.cpp" line="429"/> <location filename="../gui/trayicon.cpp" line="105"/>
<source>Notifications available</source> <source>Notifications available</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/tray.cpp" line="433"/> <location filename="../gui/trayicon.cpp" line="109"/>
<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/tray.cpp" line="437"/> <location filename="../gui/trayicon.cpp" line="113"/>
<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/tray.cpp" line="446"/> <location filename="../gui/trayicon.cpp" line="122"/>
<source>Synchronization complete</source> <source>Synchronization complete</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -471,146 +491,156 @@
<context> <context>
<name>QtGui::TrayWidget</name> <name>QtGui::TrayWidget</name>
<message> <message>
<location filename="../gui/traywidget.ui" line="14"/> <location filename="../gui/traywidget.ui" line="66"/>
<source>Form</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/traywidget.ui" line="62"/>
<source>Close</source> <source>Close</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.ui" line="103"/> <location filename="../gui/traywidget.ui" line="107"/>
<location filename="../gui/tray.cpp" line="239"/> <location filename="../gui/traywidget.cpp" line="230"/>
<source>Connect</source> <source>Connect</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.ui" line="191"/> <location filename="../gui/traywidget.ui" line="195"/>
<source>Traffic</source> <source>Traffic</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.ui" line="216"/> <location filename="../gui/traywidget.ui" line="220"/>
<source>In</source> <source>In</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.ui" line="223"/> <location filename="../gui/traywidget.ui" line="227"/>
<location filename="../gui/traywidget.ui" line="240"/> <source>Incoming traffic</source>
<location filename="../gui/tray.cpp" line="319"/> <translation type="unfinished"></translation>
<location filename="../gui/tray.cpp" line="320"/> </message>
<source>unknown</source> <message>
<location filename="../gui/traywidget.ui" line="247"/>
<source>Outgoing traffic</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<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.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> <source>Out</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.ui" line="270"/> <location filename="../gui/traywidget.ui" line="280"/>
<source>Directories</source> <source>Directories</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.ui" line="299"/> <location filename="../gui/traywidget.ui" line="309"/>
<source>Devices</source> <source>Devices</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.ui" line="76"/> <location filename="../gui/traywidget.ui" line="80"/>
<source>About</source> <source>About</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.ui" line="130"/> <location filename="../gui/traywidget.ui" line="134"/>
<source>Settings</source> <source>Settings</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.ui" line="144"/> <location filename="../gui/traywidget.ui" line="148"/>
<source>Web UI</source> <source>Web UI</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/tray.cpp" line="79"/> <location filename="../gui/traywidget.cpp" line="70"/>
<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/tray.cpp" line="121"/> <location filename="../gui/traywidget.cpp" line="112"/>
<source>Settings - Syncthing tray</source> <source>Settings - Syncthing tray</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/tray.cpp" line="140"/> <location filename="../gui/traywidget.cpp" line="131"/>
<source>Tray application for Syncthing</source> <source>Tray application for Syncthing</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/tray.cpp" line="90"/> <location filename="../gui/traywidget.cpp" line="81"/>
<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/tray.cpp" line="84"/> <location filename="../gui/traywidget.cpp" line="75"/>
<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/tray.cpp" line="141"/> <location filename="../gui/traywidget.cpp" line="132"/>
<source>About - Syncthing Tray</source> <source>About - Syncthing Tray</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/tray.cpp" line="179"/> <location filename="../gui/traywidget.cpp" line="170"/>
<source>Own device ID - Syncthing Tray</source> <source>Own device ID - Syncthing Tray</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/tray.cpp" line="189"/> <location filename="../gui/traywidget.cpp" line="180"/>
<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/tray.cpp" line="197"/> <location filename="../gui/traywidget.cpp" line="188"/>
<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/tray.cpp" line="213"/> <location filename="../gui/traywidget.cpp" line="204"/>
<source>Log - Syncthing</source> <source>Log - Syncthing</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<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> <source>Not connected to Syncthing, click to connect</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/tray.cpp" line="246"/> <location filename="../gui/traywidget.cpp" line="237"/>
<source>Pause</source> <source>Pause</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<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> <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/tray.cpp" line="252"/> <location filename="../gui/traywidget.cpp" line="243"/>
<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/tray.cpp" line="251"/> <location filename="../gui/traywidget.cpp" line="242"/>
<source>Continue</source> <source>Continue</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<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> <source>The directly &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>
@ -666,12 +696,12 @@ The Web UI will be opened in the default web browser instead.</source>
<context> <context>
<name>main</name> <name>main</name>
<message> <message>
<location filename="../application/main.cpp" line="50"/> <location filename="../application/main.cpp" line="61"/>
<source>The system tray is (currently) not available.</source> <source>The system tray is (currently) not available.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<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> <source>The Qt libraries have not been built with tray icon support.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>

View File

@ -4,89 +4,89 @@
<context> <context>
<name>Data::SyncthingConnection</name> <name>Data::SyncthingConnection</name>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="101"/> <location filename="../data/syncthingconnection.cpp" line="108"/>
<source>disconnected</source> <source>disconnected</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="103"/> <location filename="../data/syncthingconnection.cpp" line="110"/>
<source>connected</source> <source>connected</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="105"/> <location filename="../data/syncthingconnection.cpp" line="112"/>
<source>connected, notifications available</source> <source>connected, notifications available</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="107"/> <location filename="../data/syncthingconnection.cpp" line="114"/>
<source>connected, paused</source> <source>connected, paused</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="109"/> <location filename="../data/syncthingconnection.cpp" line="116"/>
<source>connected, synchronizing</source> <source>connected, synchronizing</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="111"/> <location filename="../data/syncthingconnection.cpp" line="118"/>
<source>unknown</source> <source>unknown</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="386"/> <location filename="../data/syncthingconnection.cpp" line="393"/>
<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="390"/> <location filename="../data/syncthingconnection.cpp" line="397"/>
<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="418"/> <location filename="../data/syncthingconnection.cpp" line="425"/>
<location filename="../data/syncthingconnection.cpp" line="518"/> <location filename="../data/syncthingconnection.cpp" line="525"/>
<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="423"/> <location filename="../data/syncthingconnection.cpp" line="430"/>
<location filename="../data/syncthingconnection.cpp" line="523"/> <location filename="../data/syncthingconnection.cpp" line="530"/>
<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="580"/> <location filename="../data/syncthingconnection.cpp" line="605"/>
<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="585"/> <location filename="../data/syncthingconnection.cpp" line="610"/>
<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="626"/> <location filename="../data/syncthingconnection.cpp" line="657"/>
<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="648"/> <location filename="../data/syncthingconnection.cpp" line="679"/>
<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="799"/> <location filename="../data/syncthingconnection.cpp" line="844"/>
<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="814"/> <location filename="../data/syncthingconnection.cpp" line="859"/>
<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="354"/> <location filename="../data/syncthingconnection.cpp" line="361"/>
<source>Unable to request QR-Code: </source> <source>Unable to request QR-Code: </source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -282,6 +282,19 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
</context> </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> <context>
<name>QtGui::ConnectionOptionPage</name> <name>QtGui::ConnectionOptionPage</name>
<message> <message>
@ -333,29 +346,36 @@
<context> <context>
<name>QtGui::DevView</name> <name>QtGui::DevView</name>
<message> <message>
<location filename="../gui/devview.cpp" line="44"/> <location filename="../gui/devview.cpp" line="45"/>
<source>Copy</source> <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> <translation type="unfinished"></translation>
</message> </message>
</context> </context>
<context> <context>
<name>QtGui::DirView</name> <name>QtGui::DirView</name>
<message> <message>
<location filename="../gui/dirview.cpp" line="44"/> <location filename="../gui/dirview.cpp" line="45"/>
<source>Copy</source> <source>Copy value</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QtGui::LauncherOptionPage</name>
<message>
<location filename="../gui/launcheroptionpage.ui" line="14"/>
<source>Launcher</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/launcheroptionpage.ui" line="20"/> <location filename="../gui/dirview.cpp" line="47"/>
<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> <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> <translation type="unfinished"></translation>
</message> </message>
</context> </context>
@ -403,67 +423,67 @@
<context> <context>
<name>QtGui::TrayIcon</name> <name>QtGui::TrayIcon</name>
<message> <message>
<location filename="../gui/tray.cpp" line="357"/> <location filename="../gui/trayicon.cpp" line="33"/>
<source>Web UI</source> <source>Web UI</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/tray.cpp" line="358"/> <location filename="../gui/trayicon.cpp" line="34"/>
<source>Settings</source> <source>Settings</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/tray.cpp" line="359"/> <location filename="../gui/trayicon.cpp" line="35"/>
<source>About</source> <source>About</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/tray.cpp" line="361"/> <location filename="../gui/trayicon.cpp" line="37"/>
<source>Close</source> <source>Close</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/tray.cpp" line="402"/> <location filename="../gui/trayicon.cpp" line="78"/>
<source>Syncthing error</source> <source>Syncthing error</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/tray.cpp" line="409"/> <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/tray.cpp" line="418"/> <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/tray.cpp" line="420"/> <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/tray.cpp" line="425"/> <location filename="../gui/trayicon.cpp" line="101"/>
<source>Syncthing is running</source> <source>Syncthing is running</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/tray.cpp" line="429"/> <location filename="../gui/trayicon.cpp" line="105"/>
<source>Notifications available</source> <source>Notifications available</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/tray.cpp" line="433"/> <location filename="../gui/trayicon.cpp" line="109"/>
<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/tray.cpp" line="437"/> <location filename="../gui/trayicon.cpp" line="113"/>
<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/tray.cpp" line="446"/> <location filename="../gui/trayicon.cpp" line="122"/>
<source>Synchronization complete</source> <source>Synchronization complete</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -471,146 +491,156 @@
<context> <context>
<name>QtGui::TrayWidget</name> <name>QtGui::TrayWidget</name>
<message> <message>
<location filename="../gui/traywidget.ui" line="14"/> <location filename="../gui/traywidget.ui" line="66"/>
<source>Form</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/traywidget.ui" line="62"/>
<source>Close</source> <source>Close</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.ui" line="103"/> <location filename="../gui/traywidget.ui" line="107"/>
<location filename="../gui/tray.cpp" line="239"/> <location filename="../gui/traywidget.cpp" line="230"/>
<source>Connect</source> <source>Connect</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.ui" line="191"/> <location filename="../gui/traywidget.ui" line="195"/>
<source>Traffic</source> <source>Traffic</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.ui" line="216"/> <location filename="../gui/traywidget.ui" line="220"/>
<source>In</source> <source>In</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.ui" line="223"/> <location filename="../gui/traywidget.ui" line="227"/>
<location filename="../gui/traywidget.ui" line="240"/> <source>Incoming traffic</source>
<location filename="../gui/tray.cpp" line="319"/> <translation type="unfinished"></translation>
<location filename="../gui/tray.cpp" line="320"/> </message>
<source>unknown</source> <message>
<location filename="../gui/traywidget.ui" line="247"/>
<source>Outgoing traffic</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<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.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> <source>Out</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.ui" line="270"/> <location filename="../gui/traywidget.ui" line="280"/>
<source>Directories</source> <source>Directories</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.ui" line="299"/> <location filename="../gui/traywidget.ui" line="309"/>
<source>Devices</source> <source>Devices</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.ui" line="76"/> <location filename="../gui/traywidget.ui" line="80"/>
<source>About</source> <source>About</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.ui" line="130"/> <location filename="../gui/traywidget.ui" line="134"/>
<source>Settings</source> <source>Settings</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.ui" line="144"/> <location filename="../gui/traywidget.ui" line="148"/>
<source>Web UI</source> <source>Web UI</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/tray.cpp" line="79"/> <location filename="../gui/traywidget.cpp" line="70"/>
<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/tray.cpp" line="121"/> <location filename="../gui/traywidget.cpp" line="112"/>
<source>Settings - Syncthing tray</source> <source>Settings - Syncthing tray</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/tray.cpp" line="140"/> <location filename="../gui/traywidget.cpp" line="131"/>
<source>Tray application for Syncthing</source> <source>Tray application for Syncthing</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/tray.cpp" line="90"/> <location filename="../gui/traywidget.cpp" line="81"/>
<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/tray.cpp" line="84"/> <location filename="../gui/traywidget.cpp" line="75"/>
<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/tray.cpp" line="141"/> <location filename="../gui/traywidget.cpp" line="132"/>
<source>About - Syncthing Tray</source> <source>About - Syncthing Tray</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/tray.cpp" line="179"/> <location filename="../gui/traywidget.cpp" line="170"/>
<source>Own device ID - Syncthing Tray</source> <source>Own device ID - Syncthing Tray</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/tray.cpp" line="189"/> <location filename="../gui/traywidget.cpp" line="180"/>
<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/tray.cpp" line="197"/> <location filename="../gui/traywidget.cpp" line="188"/>
<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/tray.cpp" line="213"/> <location filename="../gui/traywidget.cpp" line="204"/>
<source>Log - Syncthing</source> <source>Log - Syncthing</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<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> <source>Not connected to Syncthing, click to connect</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/tray.cpp" line="246"/> <location filename="../gui/traywidget.cpp" line="237"/>
<source>Pause</source> <source>Pause</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<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> <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/tray.cpp" line="252"/> <location filename="../gui/traywidget.cpp" line="243"/>
<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/tray.cpp" line="251"/> <location filename="../gui/traywidget.cpp" line="242"/>
<source>Continue</source> <source>Continue</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<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> <source>The directly &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>
@ -666,12 +696,12 @@ The Web UI will be opened in the default web browser instead.</source>
<context> <context>
<name>main</name> <name>main</name>
<message> <message>
<location filename="../application/main.cpp" line="50"/> <location filename="../application/main.cpp" line="61"/>
<source>The system tray is (currently) not available.</source> <source>The system tray is (currently) not available.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<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> <source>The Qt libraries have not been built with tray icon support.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>