Show ongoing downloads

This commit is contained in:
Martchus 2016-09-21 21:09:12 +02:00
parent f4e3d3d783
commit 23a4833b6e
25 changed files with 993 additions and 235 deletions

View File

@ -11,7 +11,7 @@ set(META_APP_CATEGORIES "Utility;Network;")
set(META_GUI_OPTIONAL false) set(META_GUI_OPTIONAL false)
set(META_VERSION_MAJOR 0) set(META_VERSION_MAJOR 0)
set(META_VERSION_MINOR 0) set(META_VERSION_MINOR 0)
set(META_VERSION_PATCH 1) set(META_VERSION_PATCH 2)
set(META_APP_VERSION ${META_VERSION_MAJOR}.${META_VERSION_MINOR}.${META_VERSION_PATCH}) set(META_APP_VERSION ${META_VERSION_MAJOR}.${META_VERSION_MINOR}.${META_VERSION_PATCH})
# add project files # add project files
@ -19,6 +19,7 @@ set(HEADER_FILES
data/syncthingconnection.h data/syncthingconnection.h
data/syncthingdirectorymodel.h data/syncthingdirectorymodel.h
data/syncthingdevicemodel.h data/syncthingdevicemodel.h
data/syncthingdownloadmodel.h
data/syncthingconfig.h data/syncthingconfig.h
data/syncthingprocess.h data/syncthingprocess.h
data/utils.h data/utils.h
@ -27,6 +28,7 @@ set(SRC_FILES
data/syncthingconnection.cpp data/syncthingconnection.cpp
data/syncthingdirectorymodel.cpp data/syncthingdirectorymodel.cpp
data/syncthingdevicemodel.cpp data/syncthingdevicemodel.cpp
data/syncthingdownloadmodel.cpp
data/syncthingconfig.cpp data/syncthingconfig.cpp
data/syncthingprocess.cpp data/syncthingprocess.cpp
data/utils.cpp data/utils.cpp
@ -43,8 +45,10 @@ set(WIDGETS_HEADER_FILES
gui/webviewprovider.h gui/webviewprovider.h
gui/dirbuttonsitemdelegate.h gui/dirbuttonsitemdelegate.h
gui/devbuttonsitemdelegate.h gui/devbuttonsitemdelegate.h
gui/downloaditemdelegate.h
gui/dirview.h gui/dirview.h
gui/devview.h gui/devview.h
gui/downloadview.h
gui/textviewdialog.h gui/textviewdialog.h
) )
set(WIDGETS_SRC_FILES set(WIDGETS_SRC_FILES
@ -58,8 +62,10 @@ set(WIDGETS_SRC_FILES
gui/webviewdialog.cpp gui/webviewdialog.cpp
gui/dirbuttonsitemdelegate.cpp gui/dirbuttonsitemdelegate.cpp
gui/devbuttonsitemdelegate.cpp gui/devbuttonsitemdelegate.cpp
gui/downloaditemdelegate.cpp
gui/dirview.cpp gui/dirview.cpp
gui/devview.cpp gui/devview.cpp
gui/downloadview.cpp
gui/textviewdialog.cpp gui/textviewdialog.cpp
resources/icons.qrc resources/icons.qrc
) )
@ -100,6 +106,7 @@ set(REQUIRED_ICONS
edit-copy edit-copy
edit-paste edit-paste
folder folder
folder-download
folder-open folder-open
folder-sync folder-sync
help-about help-about

View File

@ -18,6 +18,7 @@ support
* Check current traffic statistics * Check current traffic statistics
* Display further details about direcoties and devices, like last file, last * Display further details about direcoties and devices, like last file, last
scan, ... scan, ...
* Display ongoing downloads
* Trigger re-scan of a specific directory or all directories at once * Trigger re-scan of a specific directory or all directories at once
* Open a directory with the default file browser * Open a directory with the default file browser
* Pause/resume a specific device or all devices at once * Pause/resume a specific device or all devices at once
@ -33,7 +34,6 @@ support
## Planned features ## Planned features
The tray is still under development; the following features are planned: The tray is still under development; the following features are planned:
* Show currently processed items
* Show recently processed items * Show recently processed items
* Improve notification handling * Improve notification handling
* Create Plasmoid for Plasma 5 desktop * Create Plasmoid for Plasma 5 desktop

View File

@ -65,7 +65,7 @@ bool &showTraffic()
} }
QSize &trayMenuSize() QSize &trayMenuSize()
{ {
static QSize v(350, 300); static QSize v(450, 400);
return v; return v;
} }
int &frameStyle() int &frameStyle()

View File

@ -4,6 +4,7 @@
#include "../application/settings.h" #include "../application/settings.h"
#include <c++utilities/conversion/conversionexception.h> #include <c++utilities/conversion/conversionexception.h>
#include <c++utilities/conversion/stringconversion.h>
#include <QNetworkAccessManager> #include <QNetworkAccessManager>
#include <QNetworkReply> #include <QNetworkReply>
@ -99,6 +100,27 @@ bool SyncthingDir::assignStatus(DirStatus newStatus, DateTime time)
return false; return false;
} }
SyncthingItemDownloadProgress::SyncthingItemDownloadProgress(const QString &containingDirPath, const QString &relativeItemPath, const QJsonObject &values) :
relativePath(relativeItemPath),
fileInfo(containingDirPath % QChar('/') % relativeItemPath),
blocksCurrentlyDownloading(values.value(QStringLiteral("Pulling")).toInt()),
blocksAlreadyDownloaded(values.value(QStringLiteral("Pulled")).toInt()),
totalNumberOfBlocks(values.value(QStringLiteral("Total")).toInt()),
downloadPercentage((blocksAlreadyDownloaded > 0 && totalNumberOfBlocks > 0)
? (static_cast<unsigned int>(blocksAlreadyDownloaded) * 100 / static_cast<unsigned int>(totalNumberOfBlocks))
: 0),
blocksCopiedFromOrigin(values.value(QStringLiteral("CopiedFromOrigin")).toInt()),
blocksCopiedFromElsewhere(values.value(QStringLiteral("CopiedFromElsewhere")).toInt()),
blocksReused(values.value(QStringLiteral("Reused")).toInt()),
bytesAlreadyHandled(values.value(QStringLiteral("BytesDone")).toInt()),
totalNumberOfBytes(values.value(QStringLiteral("BytesTotal")).toInt()),
label(QStringLiteral("%1 / %2 - %3 %").arg(
QString::fromLatin1(dataSizeToString(blocksAlreadyDownloaded > 0 ? static_cast<uint64>(blocksAlreadyDownloaded) * syncthingBlockSize : 0).data()),
QString::fromLatin1(dataSizeToString(totalNumberOfBlocks > 0 ? static_cast<uint64>(totalNumberOfBlocks) * syncthingBlockSize : 0).data()),
QString::number(downloadPercentage))
)
{}
/*! /*!
* \class SyncthingConnection * \class SyncthingConnection
* \brief The SyncthingConnection class allows Qt applications to access Syncthing. * \brief The SyncthingConnection class allows Qt applications to access Syncthing.
@ -972,7 +994,7 @@ void SyncthingConnection::readEvents()
} else if(eventType == QLatin1String("StateChanged")) { } else if(eventType == QLatin1String("StateChanged")) {
readStatusChangedEvent(eventTime, eventData); readStatusChangedEvent(eventTime, eventData);
} else if(eventType == QLatin1String("DownloadProgress")) { } else if(eventType == QLatin1String("DownloadProgress")) {
readDownloadProgressEvent(eventData); readDownloadProgressEvent(eventTime, eventData);
} else if(eventType.startsWith(QLatin1String("Folder"))) { } else if(eventType.startsWith(QLatin1String("Folder"))) {
readDirEvent(eventTime, eventType, eventData); readDirEvent(eventTime, eventType, eventData);
} else if(eventType.startsWith(QLatin1String("Device"))) { } else if(eventType.startsWith(QLatin1String("Device"))) {
@ -1053,9 +1075,34 @@ void SyncthingConnection::readStatusChangedEvent(DateTime eventTime, const QJson
* \brief Reads results of requestEvents(). * \brief Reads results of requestEvents().
* \remarks TODO * \remarks TODO
*/ */
void SyncthingConnection::readDownloadProgressEvent(const QJsonObject &eventData) void SyncthingConnection::readDownloadProgressEvent(DateTime eventTime, const QJsonObject &eventData)
{ {
VAR_UNUSED(eventData) VAR_UNUSED(eventTime)
for(SyncthingDir &dirInfo : m_dirs) {
// disappearing implies that the download has been finished so just wipe old entries
dirInfo.downloadingItems.clear();
dirInfo.blocksAlreadyDownloaded = dirInfo.blocksToBeDownloaded = 0;
// read progress of currently downloading items
const QJsonObject dirObj(eventData.value(dirInfo.id).toObject());
if(!dirObj.isEmpty()) {
dirInfo.downloadingItems.reserve(static_cast<size_t>(dirObj.size()));
for(auto filePair = dirObj.constBegin(), end = dirObj.constEnd(); filePair != end; ++filePair) {
dirInfo.downloadingItems.emplace_back(dirInfo.path, filePair.key(), filePair.value().toObject());
const SyncthingItemDownloadProgress &itemProgress = dirInfo.downloadingItems.back();
dirInfo.blocksAlreadyDownloaded += itemProgress.blocksAlreadyDownloaded;
dirInfo.blocksToBeDownloaded += itemProgress.totalNumberOfBlocks;
}
}
dirInfo.downloadPercentage = (dirInfo.blocksAlreadyDownloaded > 0 && dirInfo.blocksToBeDownloaded > 0)
? (static_cast<unsigned int>(dirInfo.blocksAlreadyDownloaded) * 100 / static_cast<unsigned int>(dirInfo.blocksToBeDownloaded))
: 0;
dirInfo.downloadLabel = QStringLiteral("%1 / %2 - %3 %").arg(
QString::fromLatin1(dataSizeToString(dirInfo.blocksAlreadyDownloaded > 0 ? static_cast<uint64>(dirInfo.blocksAlreadyDownloaded) * SyncthingItemDownloadProgress::syncthingBlockSize : 0).data()),
QString::fromLatin1(dataSizeToString(dirInfo.blocksToBeDownloaded > 0 ? static_cast<uint64>(dirInfo.blocksToBeDownloaded) * SyncthingItemDownloadProgress::syncthingBlockSize : 0).data()),
QString::number(dirInfo.downloadPercentage));
}
emit downloadProgressChanged();
} }
/*! /*!

View File

@ -6,6 +6,7 @@
#include <QObject> #include <QObject>
#include <QList> #include <QList>
#include <QSslError> #include <QSslError>
#include <QFileInfo>
#include <functional> #include <functional>
#include <vector> #include <vector>
@ -56,8 +57,27 @@ struct DirErrors
QString path; QString path;
}; };
struct SyncthingItemDownloadProgress
{
SyncthingItemDownloadProgress(const QString &containingDirPath, const QString &relativeItemPath, const QJsonObject &values);
QString relativePath;
QFileInfo fileInfo;
int blocksCurrentlyDownloading = 0;
int blocksAlreadyDownloaded = 0;
int totalNumberOfBlocks = 0;
unsigned int downloadPercentage = 0;
int blocksCopiedFromOrigin = 0;
int blocksCopiedFromElsewhere = 0;
int blocksReused = 0;
int bytesAlreadyHandled;
int totalNumberOfBytes = 0;
QString label;
ChronoUtilities::DateTime lastUpdate;
static constexpr unsigned int syncthingBlockSize = 128 * 1024;
};
struct SyncthingDir struct SyncthingDir
{ {
QString id; QString id;
QString label; QString label;
QString path; QString path;
@ -79,6 +99,11 @@ struct SyncthingDir
ChronoUtilities::DateTime lastFileTime; ChronoUtilities::DateTime lastFileTime;
QString lastFileName; QString lastFileName;
bool lastFileDeleted = false; bool lastFileDeleted = false;
std::vector<SyncthingItemDownloadProgress> downloadingItems;
int blocksAlreadyDownloaded = 0;
int blocksToBeDownloaded = 0;
unsigned int downloadPercentage = 0;
QString downloadLabel;
bool assignStatus(const QString &statusStr, ChronoUtilities::DateTime time); bool assignStatus(const QString &statusStr, ChronoUtilities::DateTime time);
bool assignStatus(DirStatus newStatus, ChronoUtilities::DateTime time); bool assignStatus(DirStatus newStatus, ChronoUtilities::DateTime time);
@ -215,6 +240,11 @@ Q_SIGNALS:
*/ */
void devStatusChanged(const SyncthingDev &dev, int index); void devStatusChanged(const SyncthingDev &dev, int index);
/*!
* \brief Indicates the download progress changed.
*/
void downloadProgressChanged();
/*! /*!
* \brief Indicates a new Syncthing notification is available. * \brief Indicates a new Syncthing notification is available.
*/ */
@ -266,7 +296,7 @@ private Q_SLOTS:
void readEvents(); void readEvents();
void readStartingEvent(const QJsonObject &eventData); void readStartingEvent(const QJsonObject &eventData);
void readStatusChangedEvent(ChronoUtilities::DateTime eventTime, const QJsonObject &eventData); void readStatusChangedEvent(ChronoUtilities::DateTime eventTime, const QJsonObject &eventData);
void readDownloadProgressEvent(const QJsonObject &eventData); void readDownloadProgressEvent(ChronoUtilities::DateTime eventTime, const QJsonObject &eventData);
void readDirEvent(ChronoUtilities::DateTime eventTime, const QString &eventType, const QJsonObject &eventData); void readDirEvent(ChronoUtilities::DateTime eventTime, const QString &eventType, const QJsonObject &eventData);
void readDeviceEvent(ChronoUtilities::DateTime eventTime, const QString &eventType, const QJsonObject &eventData); void readDeviceEvent(ChronoUtilities::DateTime eventTime, const QString &eventType, const QJsonObject &eventData);
void readItemStarted(ChronoUtilities::DateTime eventTime, const QJsonObject &eventData); void readItemStarted(ChronoUtilities::DateTime eventTime, const QJsonObject &eventData);

View File

@ -108,7 +108,7 @@ QVariant SyncthingDeviceModel::data(const QModelIndex &index, int role) const
case Qt::ForegroundRole: case Qt::ForegroundRole:
switch(index.column()) { switch(index.column()) {
case 1: case 1:
const SyncthingDev &dev = m_devs[index.parent().row()]; const SyncthingDev &dev = m_devs[static_cast<size_t>(index.parent().row())];
switch(index.row()) { switch(index.row()) {
case 2: case 2:
if(dev.lastSeen.isNull()) { if(dev.lastSeen.isNull()) {
@ -128,7 +128,7 @@ QVariant SyncthingDeviceModel::data(const QModelIndex &index, int role) const
case 1: case 1:
switch(index.row()) { switch(index.row()) {
case 2: case 2:
const SyncthingDev &dev = m_devs[index.parent().row()]; const SyncthingDev &dev = m_devs[static_cast<size_t>(index.parent().row())];
if(!dev.lastSeen.isNull()) { if(!dev.lastSeen.isNull()) {
return agoString(dev.lastSeen); return agoString(dev.lastSeen);
} }

View File

@ -34,7 +34,7 @@ public Q_SLOTS:
int columnCount(const QModelIndex &parent) const; int columnCount(const QModelIndex &parent) const;
const SyncthingDev *devInfo(const QModelIndex &index) const; const SyncthingDev *devInfo(const QModelIndex &index) const;
private slots: private Q_SLOTS:
void newConfig(); void newConfig();
void newDevices(); void newDevices();
void devStatusChanged(const SyncthingDev &, int index); void devStatusChanged(const SyncthingDev &, int index);

View File

@ -35,12 +35,12 @@ QModelIndex SyncthingDirectoryModel::index(int row, int column, const QModelInde
if(!parent.isValid()) { if(!parent.isValid()) {
// top-level: all dir labels/IDs // top-level: all dir labels/IDs
if(row < rowCount(parent)) { if(row < rowCount(parent)) {
return createIndex(row, column, -1); return createIndex(row, column, static_cast<quintptr>(-1));
} }
} else if(!parent.parent().isValid()) { } else if(!parent.parent().isValid()) {
// dir-level: dir attributes // dir-level: dir attributes
if(row < rowCount(parent)) { if(row < rowCount(parent)) {
return createIndex(row, column, parent.row()); return createIndex(row, column, static_cast<quintptr>(parent.row()));
} }
} }
return QModelIndex(); return QModelIndex();
@ -48,7 +48,7 @@ QModelIndex SyncthingDirectoryModel::index(int row, int column, const QModelInde
QModelIndex SyncthingDirectoryModel::parent(const QModelIndex &child) const QModelIndex SyncthingDirectoryModel::parent(const QModelIndex &child) const
{ {
return child.internalId() != static_cast<quintptr>(-1) ? index(child.internalId(), 0, QModelIndex()) : QModelIndex(); return child.internalId() != static_cast<quintptr>(-1) ? index(static_cast<int>(child.internalId()), 0, QModelIndex()) : QModelIndex();
} }
QVariant SyncthingDirectoryModel::headerData(int section, Qt::Orientation orientation, int role) const QVariant SyncthingDirectoryModel::headerData(int section, Qt::Orientation orientation, int role) const
@ -94,7 +94,7 @@ QVariant SyncthingDirectoryModel::data(const QModelIndex &index, int role) const
} }
break; break;
case 1: // attribute values case 1: // attribute values
const SyncthingDir &dir = m_dirs[index.parent().row()]; const SyncthingDir &dir = m_dirs[static_cast<size_t>(index.parent().row())];
switch(index.row()) { switch(index.row()) {
case 0: return dir.id; case 0: return dir.id;
case 1: return dir.path; case 1: return dir.path;
@ -110,7 +110,7 @@ QVariant SyncthingDirectoryModel::data(const QModelIndex &index, int role) const
case Qt::ForegroundRole: case Qt::ForegroundRole:
switch(index.column()) { switch(index.column()) {
case 1: case 1:
const SyncthingDir &dir = m_dirs[index.parent().row()]; const SyncthingDir &dir = m_dirs[static_cast<size_t>(index.parent().row())];
switch(index.row()) { switch(index.row()) {
case 5: case 5:
if(dir.lastScanTime.isNull()) { if(dir.lastScanTime.isNull()) {
@ -130,7 +130,7 @@ QVariant SyncthingDirectoryModel::data(const QModelIndex &index, int role) const
case Qt::ToolTipRole: case Qt::ToolTipRole:
switch(index.column()) { switch(index.column()) {
case 1: case 1:
const SyncthingDir &dir = m_dirs[index.parent().row()]; const SyncthingDir &dir = m_dirs[static_cast<size_t>(index.parent().row())];
switch(index.row()) { switch(index.row()) {
case 5: case 5:
if(!dir.lastScanTime.isNull()) { if(!dir.lastScanTime.isNull()) {

View File

@ -27,7 +27,7 @@ public Q_SLOTS:
int columnCount(const QModelIndex &parent) const; int columnCount(const QModelIndex &parent) const;
const SyncthingDir *dirInfo(const QModelIndex &index) const; const SyncthingDir *dirInfo(const QModelIndex &index) const;
private slots: private Q_SLOTS:
void newConfig(); void newConfig();
void newDirs(); void newDirs();
void dirStatusChanged(const SyncthingDir &, int index); void dirStatusChanged(const SyncthingDir &, int index);

View File

@ -0,0 +1,213 @@
#include "./syncthingdownloadmodel.h"
#include "./syncthingconnection.h"
#include "./utils.h"
#include <QStringBuilder>
using namespace ChronoUtilities;
namespace Data {
SyncthingDownloadModel::SyncthingDownloadModel(SyncthingConnection &connection, QObject *parent) :
QAbstractItemModel(parent),
m_connection(connection),
m_dirs(connection.dirInfo()),
m_unknownIcon(QIcon::fromTheme(QStringLiteral("text-x-generic"), QIcon(QStringLiteral(":/icons/hicolor/scalable/mimetypes/text-x-generic.svg")))),
m_pendingDirs(0)
{
connect(&m_connection, &SyncthingConnection::newConfig, this, &SyncthingDownloadModel::newConfig);
connect(&m_connection, &SyncthingConnection::newDirs, this, &SyncthingDownloadModel::newDirs);
connect(&m_connection, &SyncthingConnection::downloadProgressChanged, this, &SyncthingDownloadModel::downloadProgressChanged);
}
/*!
* \brief Returns the directory info for the spcified \a index. The returned object is not persistent.
*/
const SyncthingDir *SyncthingDownloadModel::dirInfo(const QModelIndex &index) const
{
return (index.parent().isValid() ? dirInfo(index.parent()) : (static_cast<size_t>(index.row()) < m_pendingDirs.size() ? m_pendingDirs[static_cast<size_t>(index.row())] : nullptr));
}
const SyncthingItemDownloadProgress *SyncthingDownloadModel::progressInfo(const QModelIndex &index) const
{
if(index.parent().isValid()
&& static_cast<size_t>(index.parent().row()) < m_pendingDirs.size()
&& static_cast<size_t>(index.row()) < m_pendingDirs[static_cast<size_t>(index.parent().row())]->downloadingItems.size()) {
return &(m_pendingDirs[static_cast<size_t>(index.parent().row())]->downloadingItems[static_cast<size_t>(index.row())]);
} else {
return nullptr;
}
}
QModelIndex SyncthingDownloadModel::index(int row, int column, const QModelIndex &parent) const
{
if(!parent.isValid()) {
// top-level: all pending dir labels/IDs
if(row < rowCount(parent)) {
return createIndex(row, column, static_cast<quintptr>(-1));
}
} else if(!parent.parent().isValid()) {
// dir-level: pending downloads
if(row < rowCount(parent)) {
return createIndex(row, column, static_cast<quintptr>(parent.row()));
}
}
return QModelIndex();
}
QModelIndex SyncthingDownloadModel::parent(const QModelIndex &child) const
{
return child.internalId() != static_cast<quintptr>(-1) ? index(static_cast<int>(child.internalId()), 0, QModelIndex()) : QModelIndex();
}
QVariant SyncthingDownloadModel::headerData(int section, Qt::Orientation orientation, int role) const
{
switch(orientation) {
case Qt::Horizontal:
switch(role) {
case Qt::DisplayRole:
switch(section) {
case 0: return tr("Dir/item");
case 1: return tr("Progress");
}
break;
default:
;
}
break;
default:
;
}
return QVariant();
}
QVariant SyncthingDownloadModel::data(const QModelIndex &index, int role) const
{
if(index.isValid()) {
if(index.parent().isValid()) {
// dir attributes
if(static_cast<size_t>(index.parent().row()) < m_pendingDirs.size()) {
const SyncthingDir &dir = *m_pendingDirs[static_cast<size_t>(index.parent().row())];
if(static_cast<size_t>(index.row()) < dir.downloadingItems.size()) {
const SyncthingItemDownloadProgress &progress = dir.downloadingItems[static_cast<size_t>(index.row())];
switch(role) {
case Qt::DisplayRole:
case Qt::EditRole:
switch(index.column()) {
case 0: // file names
return progress.relativePath;
case 1: // progress information
return progress.label;
}
break;
case Qt::ToolTipRole:
break;
case Qt::DecorationRole:
switch(index.column()) {
case 0: // file icon
return progress.fileInfo.exists() ? m_fileIconProvider.icon(progress.fileInfo) : m_unknownIcon;
default:
;
}
break;
case ItemPercentage:
return progress.downloadPercentage;
default:
;
}
}
}
} else if(static_cast<size_t>(index.row()) < m_pendingDirs.size()) {
// dir IDs and overall dir progress
const SyncthingDir &dir = *m_pendingDirs[static_cast<size_t>(index.row())];
switch(role) {
case Qt::DisplayRole:
case Qt::EditRole:
switch(index.column()) {
case 0: return QVariant((dir.label.isEmpty() ? dir.id : dir.label) % QChar(' ') % QChar('(') % QString::number(dir.downloadingItems.size()) % QChar(')'));
case 1: return dir.downloadLabel;
}
break;
case Qt::TextAlignmentRole:
switch(index.column()) {
case 0: break;
case 1: return static_cast<int>(Qt::AlignRight | Qt::AlignVCenter);
}
break;
case ItemPercentage:
return dir.downloadPercentage;
default:
;
}
}
}
return QVariant();
}
bool SyncthingDownloadModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
Q_UNUSED(index) Q_UNUSED(value) Q_UNUSED(role)
return false;
}
int SyncthingDownloadModel::rowCount(const QModelIndex &parent) const
{
if(!parent.isValid()) {
return static_cast<int>(m_pendingDirs.size());
} else if(!parent.parent().isValid() && parent.row() >= 0 && static_cast<size_t>(parent.row()) < m_pendingDirs.size()) {
return static_cast<int>(m_pendingDirs[static_cast<size_t>(parent.row())]->downloadingItems.size());
} else {
return 0;
}
}
int SyncthingDownloadModel::columnCount(const QModelIndex &parent) const
{
if(!parent.isValid()) {
return 2; // label/ID, status/progress
} else if(!parent.parent().isValid()) {
return 2; // file, progress
} else {
return 0;
}
}
void SyncthingDownloadModel::newConfig()
{
beginResetModel();
m_pendingDirs.clear();
endResetModel();
}
void SyncthingDownloadModel::newDirs()
{
m_pendingDirs.reserve(m_connection.dirInfo().size());
}
void SyncthingDownloadModel::downloadProgressChanged()
{
int row = 0;
for(const SyncthingDir &dirInfo : m_connection.dirInfo()) {
auto pendingIterator = find(m_pendingDirs.begin(), m_pendingDirs.end(), &dirInfo);
if(dirInfo.downloadingItems.empty()) {
if(pendingIterator != m_pendingDirs.end()) {
beginRemoveRows(QModelIndex(), row, row);
m_pendingDirs.erase(pendingIterator);
endRemoveRows();
}
} else {
if(pendingIterator != m_pendingDirs.end()) {
emit dataChanged(index(row, 0), index(row, 1), QVector<int>() << Qt::DisplayRole << Qt::EditRole << Qt::DecorationRole << Qt::ForegroundRole << Qt::ToolTipRole);
} else {
beginInsertRows(QModelIndex(), row, row);
beginInsertRows(index(row, row), 0, static_cast<int>(dirInfo.downloadingItems.size()));
m_pendingDirs.insert(pendingIterator, &dirInfo);
endInsertRows();
endInsertRows();
}
++row;
}
}
}
} // namespace Data

View File

@ -0,0 +1,64 @@
#ifndef DATA_SYNCTHINGDOWNLOADMODEL_H
#define DATA_SYNCTHINGDOWNLOADMODEL_H
#include <QAbstractItemModel>
#include <QIcon>
#include <QFileIconProvider>
#include <vector>
namespace Data {
class SyncthingConnection;
struct SyncthingDir;
struct SyncthingItemDownloadProgress;
class SyncthingDownloadModel : public QAbstractItemModel
{
Q_OBJECT
Q_PROPERTY(unsigned int pendingDownloads READ pendingDownloads NOTIFY pendingDownloadsChanged)
public:
explicit SyncthingDownloadModel(SyncthingConnection &connection, QObject *parent = nullptr);
enum SyncthingDownloadModelRole
{
ItemPercentage = Qt::UserRole + 1
};
public Q_SLOTS:
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
QModelIndex parent(const QModelIndex &child) const;
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
QVariant data(const QModelIndex &index, int role) const;
bool setData(const QModelIndex &index, const QVariant &value, int role);
int rowCount(const QModelIndex &parent) const;
int columnCount(const QModelIndex &parent) const;
const SyncthingDir *dirInfo(const QModelIndex &index) const;
const SyncthingItemDownloadProgress *progressInfo(const QModelIndex &index) const;
unsigned int pendingDownloads() const;
Q_SIGNALS:
void pendingDownloadsChanged(unsigned int pendingDownloads);
private Q_SLOTS:
void newConfig();
void newDirs();
void downloadProgressChanged();
private:
Data::SyncthingConnection &m_connection;
const std::vector<SyncthingDir> &m_dirs;
const QIcon m_unknownIcon;
const QFileIconProvider m_fileIconProvider;
std::vector<const SyncthingDir *> m_pendingDirs;
unsigned int m_pendingDownloads;
};
inline unsigned int SyncthingDownloadModel::pendingDownloads() const
{
return m_pendingDownloads;
}
} // namespace Data
#endif // DATA_SYNCTHINGDOWNLOADMODEL_H

View File

@ -1,6 +1,8 @@
#include "./devview.h" #include "./devview.h"
#include "./devbuttonsitemdelegate.h" #include "./devbuttonsitemdelegate.h"
#include "../data/syncthingdevicemodel.h"
#include <QHeaderView> #include <QHeaderView>
#include <QMouseEvent> #include <QMouseEvent>
#include <QMenu> #include <QMenu>
@ -8,6 +10,8 @@
#include <QGuiApplication> #include <QGuiApplication>
#include <QClipboard> #include <QClipboard>
using namespace Data;
namespace QtGui { namespace QtGui {
DevView::DevView(QWidget *parent) : DevView::DevView(QWidget *parent) :
@ -23,16 +27,16 @@ DevView::DevView(QWidget *parent) :
void DevView::mouseReleaseEvent(QMouseEvent *event) void DevView::mouseReleaseEvent(QMouseEvent *event)
{ {
QTreeView::mouseReleaseEvent(event); QTreeView::mouseReleaseEvent(event);
const QPoint pos(event->pos()); if(const auto *devModel = qobject_cast<SyncthingDeviceModel *>(model())) {
const QModelIndex clickedIndex(indexAt(event->pos())); const QPoint pos(event->pos());
if(clickedIndex.isValid() && clickedIndex.column() == 1 && !clickedIndex.parent().isValid()) { const QModelIndex clickedIndex(indexAt(event->pos()));
const QRect itemRect(visualRect(clickedIndex)); if(clickedIndex.isValid() && clickedIndex.column() == 1 && !clickedIndex.parent().isValid()) {
//if(pos.x() > itemRect.right() - 34) { if(const SyncthingDev *devInfo = devModel->devInfo(clickedIndex)) {
if(pos.x() > itemRect.right() - 17) { const QRect itemRect(visualRect(clickedIndex));
emit pauseResumeDev(clickedIndex); if(pos.x() > itemRect.right() - 17) {
// } else { emit pauseResumeDev(*devInfo);
// emit scanDir(clickedIndex); }
// } }
} }
} }
} }

View File

@ -3,6 +3,10 @@
#include <QTreeView> #include <QTreeView>
namespace Data {
struct SyncthingDev;
}
namespace QtGui { namespace QtGui {
class DevView : public QTreeView class DevView : public QTreeView
@ -12,7 +16,7 @@ public:
DevView(QWidget *parent = nullptr); DevView(QWidget *parent = nullptr);
Q_SIGNALS: Q_SIGNALS:
void pauseResumeDev(const QModelIndex &index); void pauseResumeDev(const Data::SyncthingDev &dev);
protected: protected:
void mouseReleaseEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event);

View File

@ -1,6 +1,8 @@
#include "./dirview.h" #include "./dirview.h"
#include "./dirbuttonsitemdelegate.h" #include "./dirbuttonsitemdelegate.h"
#include "../data/syncthingdirectorymodel.h"
#include <QHeaderView> #include <QHeaderView>
#include <QMouseEvent> #include <QMouseEvent>
#include <QMenu> #include <QMenu>
@ -8,6 +10,8 @@
#include <QGuiApplication> #include <QGuiApplication>
#include <QClipboard> #include <QClipboard>
using namespace Data;
namespace QtGui { namespace QtGui {
DirView::DirView(QWidget *parent) : DirView::DirView(QWidget *parent) :
@ -23,15 +27,19 @@ DirView::DirView(QWidget *parent) :
void DirView::mouseReleaseEvent(QMouseEvent *event) void DirView::mouseReleaseEvent(QMouseEvent *event)
{ {
QTreeView::mouseReleaseEvent(event); QTreeView::mouseReleaseEvent(event);
const QPoint pos(event->pos()); if(const SyncthingDirectoryModel *dirModel = qobject_cast<SyncthingDirectoryModel *>(model())) {
const QModelIndex clickedIndex(indexAt(event->pos())); const QPoint pos(event->pos());
if(clickedIndex.isValid() && clickedIndex.column() == 1 && !clickedIndex.parent().isValid()) { const QModelIndex clickedIndex(indexAt(event->pos()));
const QRect itemRect(visualRect(clickedIndex)); if(clickedIndex.isValid() && clickedIndex.column() == 1 && !clickedIndex.parent().isValid()) {
if(pos.x() > itemRect.right() - 34) { if(const SyncthingDir *dir = dirModel->dirInfo(clickedIndex)) {
if(pos.x() > itemRect.right() - 17) { const QRect itemRect(visualRect(clickedIndex));
emit openDir(clickedIndex); if(pos.x() > itemRect.right() - 34) {
} else { if(pos.x() > itemRect.right() - 17) {
emit scanDir(clickedIndex); emit openDir(*dir);
} else {
emit scanDir(*dir);
}
}
} }
} }
} }

View File

@ -3,6 +3,10 @@
#include <QTreeView> #include <QTreeView>
namespace Data {
struct SyncthingDir;
}
namespace QtGui { namespace QtGui {
class DirView : public QTreeView class DirView : public QTreeView
@ -12,8 +16,8 @@ public:
DirView(QWidget *parent = nullptr); DirView(QWidget *parent = nullptr);
Q_SIGNALS: Q_SIGNALS:
void openDir(const QModelIndex &index); void openDir(const Data::SyncthingDir &dir);
void scanDir(const QModelIndex &index); void scanDir(const Data::SyncthingDir &dir);
protected: protected:
void mouseReleaseEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event);

View File

@ -0,0 +1,63 @@
#include "./downloaditemdelegate.h"
#include "../data/syncthingdownloadmodel.h"
#include <QPixmap>
#include <QPainter>
#include <QApplication>
#include <QStyle>
#include <QTextOption>
#include <QStyleOptionViewItem>
#include <QBrush>
#include <QPalette>
using namespace Data;
namespace QtGui {
inline int centerObj(int avail, int size)
{
return (avail - size) / 2;
}
DownloadItemDelegate::DownloadItemDelegate(QObject* parent) :
QStyledItemDelegate(parent),
m_folderIcon(QIcon::fromTheme(QStringLiteral("folder-open"), QIcon(QStringLiteral(":/icons/hicolor/scalable/places/folder-open.svg"))).pixmap(QSize(16, 16)))
{}
void DownloadItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
// use the customization only on top-level rows
//if(!index.parent().isValid()) {
// QStyledItemDelegate::paint(painter, option, index);
//} else {
// init style options to use drawControl(), except for the text
QStyleOptionViewItem opt = option;
initStyleOption(&opt, index);
opt.text.clear();
opt.features = QStyleOptionViewItem::None;
QApplication::style()->drawControl(QStyle::CE_ItemViewItem, &opt, painter);
// draw progress bar
const QAbstractItemModel *model = index.model();
QStyleOptionProgressBar progressBarOption;
progressBarOption.state = QStyle::State_Enabled;
progressBarOption.direction = QApplication::layoutDirection();
progressBarOption.rect = option.rect;
progressBarOption.rect.setWidth(option.rect.width() - 20);
progressBarOption.textAlignment = Qt::AlignCenter;
progressBarOption.textVisible = true;
progressBarOption.progress = model->data(index, SyncthingDownloadModel::ItemPercentage).toInt();
progressBarOption.minimum = 0;
progressBarOption.maximum = 100;
progressBarOption.text = model->data(index, Qt::DisplayRole).toString();
QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progressBarOption, painter);
// draw buttons
const int buttonY = option.rect.y() + centerObj(option.rect.height(), 16);
painter->drawPixmap(option.rect.right() - 16, buttonY, 16, 16, m_folderIcon);
//}
}
}

View File

@ -0,0 +1,23 @@
#ifndef DOWNLOADITEMDELEGATE_H
#define DOWNLOADITEMDELEGATE_H
#include <QStyledItemDelegate>
#include <QPixmap>
namespace QtGui {
class DownloadItemDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
DownloadItemDelegate(QObject *parent);
void paint(QPainter *, const QStyleOptionViewItem &, const QModelIndex &) const;
private:
const QPixmap m_folderIcon;
};
}
#endif // DOWNLOADITEMDELEGATE_H

79
gui/downloadview.cpp Normal file
View File

@ -0,0 +1,79 @@
#include "./downloadview.h"
#include "./downloaditemdelegate.h"
#include "../data/syncthingdownloadmodel.h"
#include <QHeaderView>
#include <QMouseEvent>
#include <QMenu>
#include <QCursor>
#include <QGuiApplication>
#include <QClipboard>
using namespace Data;
namespace QtGui {
DownloadView::DownloadView(QWidget *parent) :
QTreeView(parent)
{
header()->setSectionResizeMode(QHeaderView::ResizeToContents);
header()->hide();
setItemDelegateForColumn(1, new DownloadItemDelegate(this));
setContextMenuPolicy(Qt::CustomContextMenu);
connect(this, &DownloadView::customContextMenuRequested, this, &DownloadView::showContextMenu);
}
void DownloadView::mouseReleaseEvent(QMouseEvent *event)
{
QTreeView::mouseReleaseEvent(event);
if(const SyncthingDownloadModel *dlModel = qobject_cast<SyncthingDownloadModel *>(model())) {
const QPoint pos(event->pos());
const QModelIndex clickedIndex(indexAt(event->pos()));
if(clickedIndex.isValid() && clickedIndex.column() == 1) {
const QRect itemRect(visualRect(clickedIndex));
if(pos.x() > itemRect.right() - 17) {
if(clickedIndex.parent().isValid()) {
if(const SyncthingItemDownloadProgress *progress = dlModel->progressInfo(clickedIndex)) {
emit openItemDir(*progress);
}
} else if(const SyncthingDir *dir = dlModel->dirInfo(clickedIndex)) {
emit openDir(*dir);
}
}
}
}
}
void DownloadView::showContextMenu()
{
if(selectionModel() && selectionModel()->selectedRows(0).size() == 1) {
QMenu menu;
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, &DownloadView::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, &DownloadView::copySelectedItem);
}
menu.exec(QCursor::pos());
}
}
void DownloadView::copySelectedItem()
{
if(selectionModel() && selectionModel()->selectedRows(0).size() == 1) {
const QModelIndex selectedIndex = selectionModel()->selectedRows(0).at(0);
QString text;
if(selectedIndex.parent().isValid()) {
// dev attribute
text = model()->data(model()->index(selectedIndex.row(), 1, selectedIndex.parent())).toString();
} else {
// dev label/id
text = model()->data(selectedIndex).toString();
}
if(!text.isEmpty()) {
QGuiApplication::clipboard()->setText(text);
}
}
}
}

34
gui/downloadview.h Normal file
View File

@ -0,0 +1,34 @@
#ifndef DOWNLOADVIEW_H
#define DOWNLOADVIEW_H
#include <QTreeView>
namespace Data {
struct SyncthingItemDownloadProgress;
struct SyncthingDir;
}
namespace QtGui {
class DownloadView : public QTreeView
{
Q_OBJECT
public:
DownloadView(QWidget *parent = nullptr);
Q_SIGNALS:
void openDir(const Data::SyncthingDir &dir);
void openItemDir(const Data::SyncthingItemDownloadProgress &dir);
protected:
void mouseReleaseEvent(QMouseEvent *event);
private Q_SLOTS:
void showContextMenu();
void copySelectedItem();
};
}
#endif // DOWNLOADVIEW_H

View File

@ -52,6 +52,7 @@ TrayWidget::TrayWidget(TrayMenu *parent) :
#endif #endif
m_dirModel(m_connection), m_dirModel(m_connection),
m_devModel(m_connection), m_devModel(m_connection),
m_dlModel(m_connection),
m_selectedConnection(nullptr) m_selectedConnection(nullptr)
{ {
m_ui->setupUi(this); m_ui->setupUi(this);
@ -59,6 +60,7 @@ TrayWidget::TrayWidget(TrayMenu *parent) :
// setup model and view // setup model and view
m_ui->dirsTreeView->setModel(&m_dirModel); m_ui->dirsTreeView->setModel(&m_dirModel);
m_ui->devsTreeView->setModel(&m_devModel); m_ui->devsTreeView->setModel(&m_devModel);
m_ui->downloadsTreeView->setModel(&m_dlModel);
// setup sync-all button // setup sync-all button
m_cornerFrame = new QFrame(this); m_cornerFrame = new QFrame(this);
@ -113,6 +115,8 @@ TrayWidget::TrayWidget(TrayMenu *parent) :
connect(m_ui->dirsTreeView, &DirView::openDir, this, &TrayWidget::openDir); connect(m_ui->dirsTreeView, &DirView::openDir, this, &TrayWidget::openDir);
connect(m_ui->dirsTreeView, &DirView::scanDir, this, &TrayWidget::scanDir); connect(m_ui->dirsTreeView, &DirView::scanDir, this, &TrayWidget::scanDir);
connect(m_ui->devsTreeView, &DevView::pauseResumeDev, this, &TrayWidget::pauseResumeDev); connect(m_ui->devsTreeView, &DevView::pauseResumeDev, this, &TrayWidget::pauseResumeDev);
connect(m_ui->downloadsTreeView, &DownloadView::openDir, this, &TrayWidget::openDir);
connect(m_ui->downloadsTreeView, &DownloadView::openItemDir, this, &TrayWidget::openItemDir);
connect(scanAllButton, &QPushButton::clicked, &m_connection, &SyncthingConnection::rescanAllDirs); connect(scanAllButton, &QPushButton::clicked, &m_connection, &SyncthingConnection::rescanAllDirs);
connect(viewIdButton, &QPushButton::clicked, this, &TrayWidget::showOwnDeviceId); connect(viewIdButton, &QPushButton::clicked, this, &TrayWidget::showOwnDeviceId);
connect(showLogButton, &QPushButton::clicked, this, &TrayWidget::showLog); connect(showLogButton, &QPushButton::clicked, this, &TrayWidget::showLog);
@ -307,32 +311,35 @@ void TrayWidget::applySettings()
} }
} }
void TrayWidget::openDir(const QModelIndex &dirIndex) void TrayWidget::openDir(const SyncthingDir &dir)
{ {
if(const SyncthingDir *dir = m_dirModel.dirInfo(dirIndex)) { if(QDir(dir.path).exists()) {
if(QDir(dir->path).exists()) { DesktopUtils::openLocalFileOrDir(dir.path);
DesktopUtils::openLocalFileOrDir(dir->path); } else {
} else { QMessageBox::warning(this, QCoreApplication::applicationName(), tr("The directory <i>%1</i> does not exist on the local machine.").arg(dir.path));
QMessageBox::warning(this, QCoreApplication::applicationName(), tr("The directory <i>%1</i> does not exist on the local machine.").arg(dir->path));
}
} }
} }
void TrayWidget::scanDir(const QModelIndex &dirIndex) void TrayWidget::openItemDir(const SyncthingItemDownloadProgress &item)
{ {
if(const SyncthingDir *dir = m_dirModel.dirInfo(dirIndex)) { if(item.fileInfo.exists()) {
m_connection.rescan(dir->id); DesktopUtils::openLocalFileOrDir(item.fileInfo.path());
} else {
QMessageBox::warning(this, QCoreApplication::applicationName(), tr("The file <i>%1</i> does not exist on the local machine.").arg(item.fileInfo.filePath()));
} }
} }
void TrayWidget::pauseResumeDev(const QModelIndex &devIndex) void TrayWidget::scanDir(const SyncthingDir &dir)
{ {
if(const SyncthingDev *dev = m_devModel.devInfo(devIndex)) { m_connection.rescan(dir.id);
if(dev->paused) { }
m_connection.resume(dev->id);
} else { void TrayWidget::pauseResumeDev(const SyncthingDev &dev)
m_connection.pause(dev->id); {
} if(dev.paused) {
m_connection.resume(dev.id);
} else {
m_connection.pause(dev.id);
} }
} }

View File

@ -6,6 +6,7 @@
#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 "../data/syncthingdownloadmodel.h"
#include "../data/syncthingprocess.h" #include "../data/syncthingprocess.h"
#include "../application/settings.h" #include "../application/settings.h"
@ -57,9 +58,10 @@ public slots:
private slots: private slots:
void handleStatusChanged(Data::SyncthingStatus status); void handleStatusChanged(Data::SyncthingStatus status);
void applySettings(); void applySettings();
void openDir(const QModelIndex &dirIndex); void openDir(const Data::SyncthingDir &dir);
void scanDir(const QModelIndex &dirIndex); void openItemDir(const Data::SyncthingItemDownloadProgress &item);
void pauseResumeDev(const QModelIndex &devIndex); void scanDir(const Data::SyncthingDir &dir);
void pauseResumeDev(const Data::SyncthingDev &dev);
void changeStatus(); void changeStatus();
void updateTraffic(); void updateTraffic();
#ifndef SYNCTHINGTRAY_NO_WEBVIEW #ifndef SYNCTHINGTRAY_NO_WEBVIEW
@ -81,6 +83,7 @@ private:
Data::SyncthingConnection m_connection; Data::SyncthingConnection m_connection;
Data::SyncthingDirectoryModel m_dirModel; Data::SyncthingDirectoryModel m_dirModel;
Data::SyncthingDeviceModel m_devModel; Data::SyncthingDeviceModel m_devModel;
Data::SyncthingDownloadModel m_dlModel;
QMenu *m_connectionsMenu; QMenu *m_connectionsMenu;
QActionGroup *m_connectionsActionGroup; QActionGroup *m_connectionsActionGroup;
Settings::ConnectionSettings *m_selectedConnection; Settings::ConnectionSettings *m_selectedConnection;

View File

@ -276,7 +276,8 @@ For &lt;i&gt;all&lt;/i&gt; notifications, checkout the log</string>
<string>New notifications</string> <string>New notifications</string>
</property> </property>
<property name="icon"> <property name="icon">
<iconset theme="dialog-warning"/> <iconset theme="dialog-warning">
<normaloff>.</normaloff>.</iconset>
</property> </property>
<property name="flat"> <property name="flat">
<bool>true</bool> <bool>true</bool>
@ -375,6 +376,35 @@ For &lt;i&gt;all&lt;/i&gt; notifications, checkout the log</string>
</item> </item>
</layout> </layout>
</widget> </widget>
<widget class="QWidget" name="downloadsTab">
<attribute name="icon">
<iconset theme="folder-download">
<normaloff>.</normaloff>.</iconset>
</attribute>
<attribute name="title">
<string>Downloads</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QtGui::DownloadView" name="downloadsTreeView"/>
</item>
</layout>
</widget>
</widget> </widget>
</item> </item>
</layout> </layout>
@ -390,6 +420,11 @@ For &lt;i&gt;all&lt;/i&gt; notifications, checkout the log</string>
<extends>QTreeView</extends> <extends>QTreeView</extends>
<header>./gui/devview.h</header> <header>./gui/devview.h</header>
</customwidget> </customwidget>
<customwidget>
<class>QtGui::DownloadView</class>
<extends>QTreeView</extends>
<header>./gui/downloadview.h</header>
</customwidget>
</customwidgets> </customwidgets>
<resources> <resources>
<include location="../resources/icons.qrc"/> <include location="../resources/icons.qrc"/>

51
testdata/downloadprogressevent.json vendored Normal file
View File

@ -0,0 +1,51 @@
{
"id": 221,
"type": "DownloadProgress",
"time": "2014-12-13T00:26:12.9876937Z",
"data": {
"repo": {
"file1": {
"Total": 800,
"Pulling": 2,
"CopiedFromOrigin": 0,
"Reused": 633,
"CopiedFromElsewhere": 0,
"Pulled": 38,
"BytesTotal": 104792064,
"BytesDone": 87883776
},
"dir\\file2": {
"Total": 80,
"Pulling": 2,
"CopiedFromOrigin": 0,
"Reused": 0,
"CopiedFromElsewhere": 0,
"Pulled": 32,
"BytesTotal": 10420224,
"BytesDone": 4128768
}
},
"projects": {
"file3": {
"Total": 800,
"Pulling": 2,
"CopiedFromOrigin": 0,
"Reused": 633,
"CopiedFromElsewhere": 0,
"Pulled": 38,
"BytesTotal": 104792064,
"BytesDone": 87883776
},
"dir\\file4": {
"Total": 80,
"Pulling": 2,
"CopiedFromOrigin": 0,
"Reused": 0,
"CopiedFromElsewhere": 0,
"Pulled": 32,
"BytesTotal": 10420224,
"BytesDone": 4128768
}
}
}
}

View File

@ -4,145 +4,145 @@
<context> <context>
<name>Data::SyncthingConnection</name> <name>Data::SyncthingConnection</name>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="148"/> <location filename="../data/syncthingconnection.cpp" line="172"/>
<source>disconnected</source> <source>disconnected</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="150"/> <location filename="../data/syncthingconnection.cpp" line="174"/>
<source>reconnecting</source> <source>reconnecting</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="152"/> <location filename="../data/syncthingconnection.cpp" line="176"/>
<source>connected</source> <source>connected</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="154"/> <location filename="../data/syncthingconnection.cpp" line="178"/>
<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="156"/> <location filename="../data/syncthingconnection.cpp" line="180"/>
<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="158"/> <location filename="../data/syncthingconnection.cpp" line="182"/>
<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="160"/> <location filename="../data/syncthingconnection.cpp" line="184"/>
<source>unknown</source> <source>unknown</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="172"/> <location filename="../data/syncthingconnection.cpp" line="196"/>
<location filename="../data/syncthingconnection.cpp" line="252"/> <location filename="../data/syncthingconnection.cpp" line="276"/>
<source>Connection configuration is insufficient.</source> <source>Connection configuration is insufficient.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="532"/> <location filename="../data/syncthingconnection.cpp" line="556"/>
<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="536"/> <location filename="../data/syncthingconnection.cpp" line="560"/>
<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="558"/> <location filename="../data/syncthingconnection.cpp" line="582"/>
<source>Unable to locate certificate used by Syncthing GUI.</source> <source>Unable to locate certificate used by Syncthing GUI.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="564"/> <location filename="../data/syncthingconnection.cpp" line="588"/>
<source>Unable to load certificate used by Syncthing GUI.</source> <source>Unable to load certificate used by Syncthing GUI.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="597"/> <location filename="../data/syncthingconnection.cpp" line="621"/>
<location filename="../data/syncthingconnection.cpp" line="699"/> <location filename="../data/syncthingconnection.cpp" line="723"/>
<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="603"/> <location filename="../data/syncthingconnection.cpp" line="627"/>
<location filename="../data/syncthingconnection.cpp" line="705"/> <location filename="../data/syncthingconnection.cpp" line="729"/>
<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="780"/> <location filename="../data/syncthingconnection.cpp" line="804"/>
<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="786"/> <location filename="../data/syncthingconnection.cpp" line="810"/>
<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="841"/> <location filename="../data/syncthingconnection.cpp" line="865"/>
<source>Unable to parse directory statistics: </source> <source>Unable to parse directory statistics: </source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="847"/> <location filename="../data/syncthingconnection.cpp" line="871"/>
<source>Unable to request directory statistics: </source> <source>Unable to request directory statistics: </source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="884"/> <location filename="../data/syncthingconnection.cpp" line="908"/>
<source>Unable to parse device statistics: </source> <source>Unable to parse device statistics: </source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="890"/> <location filename="../data/syncthingconnection.cpp" line="914"/>
<source>Unable to request device statistics: </source> <source>Unable to request device statistics: </source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="925"/> <location filename="../data/syncthingconnection.cpp" line="949"/>
<source>Unable to parse errors: </source> <source>Unable to parse errors: </source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="936"/> <location filename="../data/syncthingconnection.cpp" line="960"/>
<source>Unable to request errors: </source> <source>Unable to request errors: </source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="987"/> <location filename="../data/syncthingconnection.cpp" line="1011"/>
<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="1006"/> <location filename="../data/syncthingconnection.cpp" line="1030"/>
<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="1218"/> <location filename="../data/syncthingconnection.cpp" line="1272"/>
<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="1233"/> <location filename="../data/syncthingconnection.cpp" line="1287"/>
<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="1248"/> <location filename="../data/syncthingconnection.cpp" line="1302"/>
<source>Unable to request restart: </source> <source>Unable to request restart: </source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="503"/> <location filename="../data/syncthingconnection.cpp" line="527"/>
<source>Unable to request QR-Code: </source> <source>Unable to request QR-Code: </source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -361,6 +361,19 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
</context> </context>
<context>
<name>Data::SyncthingDownloadModel</name>
<message>
<location filename="../data/syncthingdownloadmodel.cpp" line="70"/>
<source>Dir/item</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../data/syncthingdownloadmodel.cpp" line="71"/>
<source>Progress</source>
<translation type="unfinished"></translation>
</message>
</context>
<context> <context>
<name>Data::Utils</name> <name>Data::Utils</name>
<message> <message>
@ -488,77 +501,77 @@
<context> <context>
<name>QtGui::ConnectionOptionPage</name> <name>QtGui::ConnectionOptionPage</name>
<message> <message>
<location filename="../gui/connectionoptionpage.ui" line="14"/> <location filename="../gui/connectionoptionpage.ui" line="6"/>
<source>Connection</source> <source>Connection</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/connectionoptionpage.ui" line="30"/> <location filename="../gui/connectionoptionpage.ui" line="22"/>
<source>Config label</source> <source>Config label</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/connectionoptionpage.ui" line="80"/> <location filename="../gui/connectionoptionpage.ui" line="72"/>
<source>Add secondary instance</source> <source>Add secondary instance</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/connectionoptionpage.ui" line="97"/> <location filename="../gui/connectionoptionpage.ui" line="89"/>
<source>Remove currently selected secondary instance</source> <source>Remove currently selected secondary instance</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/connectionoptionpage.ui" line="111"/> <location filename="../gui/connectionoptionpage.ui" line="103"/>
<source>Syncthing URL</source> <source>Syncthing URL</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/connectionoptionpage.ui" line="121"/> <location filename="../gui/connectionoptionpage.ui" line="113"/>
<source>Authentication</source> <source>Authentication</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/connectionoptionpage.ui" line="134"/> <location filename="../gui/connectionoptionpage.ui" line="126"/>
<source>User</source> <source>User</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/connectionoptionpage.ui" line="212"/> <location filename="../gui/connectionoptionpage.ui" line="204"/>
<source>disconnected</source> <source>disconnected</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/connectionoptionpage.ui" line="219"/> <location filename="../gui/connectionoptionpage.ui" line="211"/>
<source>Apply connection settings and try to reconnect with the currently selected config</source> <source>Apply connection settings and try to reconnect with the currently selected config</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/connectionoptionpage.ui" line="255"/> <location filename="../gui/connectionoptionpage.ui" line="247"/>
<source>It is possible to save multiple configurations. This allows switching quickly between multiple Syncthing instances using the arrow in the right corner of the tray menu. The config label is an arbitrary name to identify a configuration and must not match the name of the corresponding Syncthing device.</source> <source>It is possible to save multiple configurations. This allows switching quickly between multiple Syncthing instances using the connection button in the right corner of the tray menu. The config label is an arbitrary name to identify a configuration and does not have to match the name of the corresponding Syncthing device.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/connectionoptionpage.ui" line="265"/> <location filename="../gui/connectionoptionpage.ui" line="257"/>
<source>HTTPS certificate</source> <source>HTTPS certificate</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/connectionoptionpage.ui" line="205"/> <location filename="../gui/connectionoptionpage.ui" line="197"/>
<source>Status</source> <source>Status</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/connectionoptionpage.ui" line="168"/> <location filename="../gui/connectionoptionpage.ui" line="160"/>
<source>API key</source> <source>API key</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/connectionoptionpage.ui" line="181"/> <location filename="../gui/connectionoptionpage.ui" line="173"/>
<source>Insert values from local Syncthing configuration</source> <source>Insert values from local Syncthing configuration</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/connectionoptionpage.ui" line="151"/> <location filename="../gui/connectionoptionpage.ui" line="143"/>
<source>Password</source> <source>Password</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -591,17 +604,17 @@
<context> <context>
<name>QtGui::DevView</name> <name>QtGui::DevView</name>
<message> <message>
<location filename="../gui/devview.cpp" line="45"/> <location filename="../gui/devview.cpp" line="49"/>
<source>Copy value</source> <source>Copy value</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/devview.cpp" line="47"/> <location filename="../gui/devview.cpp" line="51"/>
<source>Copy name</source> <source>Copy name</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/devview.cpp" line="48"/> <location filename="../gui/devview.cpp" line="52"/>
<source>Copy ID</source> <source>Copy ID</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -609,21 +622,34 @@
<context> <context>
<name>QtGui::DirView</name> <name>QtGui::DirView</name>
<message> <message>
<location filename="../gui/dirview.cpp" line="45"/> <location filename="../gui/dirview.cpp" line="53"/>
<source>Copy value</source> <source>Copy value</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/dirview.cpp" line="47"/> <location filename="../gui/dirview.cpp" line="55"/>
<source>Copy label/ID</source> <source>Copy label/ID</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/dirview.cpp" line="48"/> <location filename="../gui/dirview.cpp" line="56"/>
<source>Copy path</source> <source>Copy path</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
</context> </context>
<context>
<name>QtGui::DownloadView</name>
<message>
<location filename="../gui/downloadview.cpp" line="53"/>
<source>Copy value</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/downloadview.cpp" line="55"/>
<source>Copy label/ID</source>
<translation type="unfinished"></translation>
</message>
</context>
<context> <context>
<name>QtGui::LauncherOptionPage</name> <name>QtGui::LauncherOptionPage</name>
<message> <message>
@ -753,67 +779,72 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/trayicon.cpp" line="37"/> <location filename="../gui/trayicon.cpp" line="36"/>
<source>Rescan all</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/trayicon.cpp" line="38"/>
<source>About</source> <source>About</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/trayicon.cpp" line="39"/> <location filename="../gui/trayicon.cpp" line="40"/>
<source>Close</source> <source>Close</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/trayicon.cpp" line="84"/> <location filename="../gui/trayicon.cpp" line="85"/>
<source>Error</source> <source>Error</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/trayicon.cpp" line="91"/> <location filename="../gui/trayicon.cpp" line="92"/>
<source>Syncthing notification - click to dismiss</source> <source>Syncthing notification - click to dismiss</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/trayicon.cpp" line="100"/> <location filename="../gui/trayicon.cpp" line="101"/>
<source>Not connected to Syncthing</source> <source>Not connected to Syncthing</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/trayicon.cpp" line="102"/> <location filename="../gui/trayicon.cpp" line="103"/>
<source>Disconnected from Syncthing</source> <source>Disconnected from Syncthing</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/trayicon.cpp" line="107"/> <location filename="../gui/trayicon.cpp" line="108"/>
<source>Reconnecting ...</source> <source>Reconnecting ...</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/trayicon.cpp" line="111"/> <location filename="../gui/trayicon.cpp" line="112"/>
<source>Syncthing is idling</source> <source>Syncthing is idling</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/trayicon.cpp" line="115"/> <location filename="../gui/trayicon.cpp" line="116"/>
<source>Syncthing is scanning</source> <source>Syncthing is scanning</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/trayicon.cpp" line="119"/> <location filename="../gui/trayicon.cpp" line="120"/>
<source>Notifications available</source> <source>Notifications available</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/trayicon.cpp" line="123"/> <location filename="../gui/trayicon.cpp" line="124"/>
<source>At least one device is paused</source> <source>At least one device is paused</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/trayicon.cpp" line="127"/> <location filename="../gui/trayicon.cpp" line="128"/>
<source>Synchronization is ongoing</source> <source>Synchronization is ongoing</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/trayicon.cpp" line="137"/> <location filename="../gui/trayicon.cpp" line="138"/>
<source>Synchronization complete</source> <source>Synchronization complete</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -827,7 +858,7 @@
</message> </message>
<message> <message>
<location filename="../gui/traywidget.ui" line="107"/> <location filename="../gui/traywidget.ui" line="107"/>
<location filename="../gui/traywidget.cpp" line="230"/> <location filename="../gui/traywidget.cpp" line="235"/>
<source>Connect</source> <source>Connect</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -857,10 +888,15 @@
For &lt;i&gt;all&lt;/i&gt; notifications, checkout the log</source> For &lt;i&gt;all&lt;/i&gt; notifications, checkout the log</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<location filename="../gui/traywidget.ui" line="385"/>
<source>Downloads</source>
<translation type="unfinished"></translation>
</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.ui" line="250"/>
<location filename="../gui/traywidget.cpp" line="363"/> <location filename="../gui/traywidget.cpp" line="371"/>
<source>unknown</source> <source>unknown</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -875,18 +911,18 @@ For &lt;i&gt;all&lt;/i&gt; notifications, checkout the log</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.ui" line="326"/> <location filename="../gui/traywidget.ui" line="327"/>
<source>Directories</source> <source>Directories</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.ui" line="355"/> <location filename="../gui/traywidget.ui" line="356"/>
<source>Devices</source> <source>Devices</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.ui" line="80"/> <location filename="../gui/traywidget.ui" line="80"/>
<location filename="../gui/traywidget.cpp" line="140"/> <location filename="../gui/traywidget.cpp" line="145"/>
<source>About</source> <source>About</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -901,83 +937,88 @@ For &lt;i&gt;all&lt;/i&gt; notifications, checkout the log</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.cpp" line="70"/> <location filename="../gui/traywidget.cpp" line="72"/>
<source>View own device ID</source> <source>View own device ID</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.cpp" line="85"/> <location filename="../gui/traywidget.cpp" line="87"/>
<source>Rescan all directories</source> <source>Rescan all directories</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.cpp" line="80"/> <location filename="../gui/traywidget.cpp" line="82"/>
<source>Show Syncthing log</source> <source>Show Syncthing log</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.cpp" line="75"/> <location filename="../gui/traywidget.cpp" line="77"/>
<source>Restart Syncthing</source> <source>Restart Syncthing</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.cpp" line="92"/> <location filename="../gui/traywidget.cpp" line="94"/>
<source>Connection</source> <source>Connection</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.cpp" line="180"/> <location filename="../gui/traywidget.cpp" line="185"/>
<source>device ID is unknown</source> <source>device ID is unknown</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.cpp" line="188"/> <location filename="../gui/traywidget.cpp" line="193"/>
<source>Copy to clipboard</source> <source>Copy to clipboard</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.ui" line="276"/> <location filename="../gui/traywidget.ui" line="276"/>
<location filename="../gui/traywidget.cpp" line="216"/> <location filename="../gui/traywidget.cpp" line="221"/>
<source>New notifications</source> <source>New notifications</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.cpp" line="231"/> <location filename="../gui/traywidget.cpp" line="236"/>
<source>Not connected to Syncthing, click to connect</source> <source>Not connected to Syncthing, click to connect</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.cpp" line="243"/> <location filename="../gui/traywidget.cpp" line="248"/>
<source>Pause</source> <source>Pause</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.cpp" line="244"/> <location filename="../gui/traywidget.cpp" line="249"/>
<source>Syncthing is running, click to pause all devices</source> <source>Syncthing is running, click to pause all devices</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.cpp" line="250"/> <location filename="../gui/traywidget.cpp" line="255"/>
<source>At least one device is paused, click to resume</source> <source>At least one device is paused, click to resume</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.cpp" line="315"/> <location filename="../gui/traywidget.cpp" line="319"/>
<source>The directory &lt;i&gt;%1&lt;/i&gt; does not exist on the local machine.</source> <source>The directory &lt;i&gt;%1&lt;/i&gt; does not exist on the local machine.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.cpp" line="249"/> <location filename="../gui/traywidget.cpp" line="328"/>
<source>The file &lt;i&gt;%1&lt;/i&gt; does not exist on the local machine.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/traywidget.cpp" line="254"/>
<source>Continue</source> <source>Continue</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.cpp" line="170"/> <location filename="../gui/traywidget.cpp" line="175"/>
<source>Own device ID</source> <source>Own device ID</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.cpp" line="202"/> <location filename="../gui/traywidget.cpp" line="207"/>
<source>Log</source> <source>Log</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>

View File

@ -4,145 +4,145 @@
<context> <context>
<name>Data::SyncthingConnection</name> <name>Data::SyncthingConnection</name>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="148"/> <location filename="../data/syncthingconnection.cpp" line="172"/>
<source>disconnected</source> <source>disconnected</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="150"/> <location filename="../data/syncthingconnection.cpp" line="174"/>
<source>reconnecting</source> <source>reconnecting</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="152"/> <location filename="../data/syncthingconnection.cpp" line="176"/>
<source>connected</source> <source>connected</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="154"/> <location filename="../data/syncthingconnection.cpp" line="178"/>
<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="156"/> <location filename="../data/syncthingconnection.cpp" line="180"/>
<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="158"/> <location filename="../data/syncthingconnection.cpp" line="182"/>
<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="160"/> <location filename="../data/syncthingconnection.cpp" line="184"/>
<source>unknown</source> <source>unknown</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="172"/> <location filename="../data/syncthingconnection.cpp" line="196"/>
<location filename="../data/syncthingconnection.cpp" line="252"/> <location filename="../data/syncthingconnection.cpp" line="276"/>
<source>Connection configuration is insufficient.</source> <source>Connection configuration is insufficient.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="532"/> <location filename="../data/syncthingconnection.cpp" line="556"/>
<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="536"/> <location filename="../data/syncthingconnection.cpp" line="560"/>
<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="558"/> <location filename="../data/syncthingconnection.cpp" line="582"/>
<source>Unable to locate certificate used by Syncthing GUI.</source> <source>Unable to locate certificate used by Syncthing GUI.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="564"/> <location filename="../data/syncthingconnection.cpp" line="588"/>
<source>Unable to load certificate used by Syncthing GUI.</source> <source>Unable to load certificate used by Syncthing GUI.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="597"/> <location filename="../data/syncthingconnection.cpp" line="621"/>
<location filename="../data/syncthingconnection.cpp" line="699"/> <location filename="../data/syncthingconnection.cpp" line="723"/>
<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="603"/> <location filename="../data/syncthingconnection.cpp" line="627"/>
<location filename="../data/syncthingconnection.cpp" line="705"/> <location filename="../data/syncthingconnection.cpp" line="729"/>
<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="780"/> <location filename="../data/syncthingconnection.cpp" line="804"/>
<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="786"/> <location filename="../data/syncthingconnection.cpp" line="810"/>
<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="841"/> <location filename="../data/syncthingconnection.cpp" line="865"/>
<source>Unable to parse directory statistics: </source> <source>Unable to parse directory statistics: </source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="847"/> <location filename="../data/syncthingconnection.cpp" line="871"/>
<source>Unable to request directory statistics: </source> <source>Unable to request directory statistics: </source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="884"/> <location filename="../data/syncthingconnection.cpp" line="908"/>
<source>Unable to parse device statistics: </source> <source>Unable to parse device statistics: </source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="890"/> <location filename="../data/syncthingconnection.cpp" line="914"/>
<source>Unable to request device statistics: </source> <source>Unable to request device statistics: </source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="925"/> <location filename="../data/syncthingconnection.cpp" line="949"/>
<source>Unable to parse errors: </source> <source>Unable to parse errors: </source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="936"/> <location filename="../data/syncthingconnection.cpp" line="960"/>
<source>Unable to request errors: </source> <source>Unable to request errors: </source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="987"/> <location filename="../data/syncthingconnection.cpp" line="1011"/>
<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="1006"/> <location filename="../data/syncthingconnection.cpp" line="1030"/>
<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="1218"/> <location filename="../data/syncthingconnection.cpp" line="1272"/>
<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="1233"/> <location filename="../data/syncthingconnection.cpp" line="1287"/>
<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="1248"/> <location filename="../data/syncthingconnection.cpp" line="1302"/>
<source>Unable to request restart: </source> <source>Unable to request restart: </source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../data/syncthingconnection.cpp" line="503"/> <location filename="../data/syncthingconnection.cpp" line="527"/>
<source>Unable to request QR-Code: </source> <source>Unable to request QR-Code: </source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -361,6 +361,19 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
</context> </context>
<context>
<name>Data::SyncthingDownloadModel</name>
<message>
<location filename="../data/syncthingdownloadmodel.cpp" line="70"/>
<source>Dir/item</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../data/syncthingdownloadmodel.cpp" line="71"/>
<source>Progress</source>
<translation type="unfinished"></translation>
</message>
</context>
<context> <context>
<name>Data::Utils</name> <name>Data::Utils</name>
<message> <message>
@ -488,77 +501,77 @@
<context> <context>
<name>QtGui::ConnectionOptionPage</name> <name>QtGui::ConnectionOptionPage</name>
<message> <message>
<location filename="../gui/connectionoptionpage.ui" line="14"/> <location filename="../gui/connectionoptionpage.ui" line="6"/>
<source>Connection</source> <source>Connection</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/connectionoptionpage.ui" line="30"/> <location filename="../gui/connectionoptionpage.ui" line="22"/>
<source>Config label</source> <source>Config label</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/connectionoptionpage.ui" line="80"/> <location filename="../gui/connectionoptionpage.ui" line="72"/>
<source>Add secondary instance</source> <source>Add secondary instance</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/connectionoptionpage.ui" line="97"/> <location filename="../gui/connectionoptionpage.ui" line="89"/>
<source>Remove currently selected secondary instance</source> <source>Remove currently selected secondary instance</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/connectionoptionpage.ui" line="111"/> <location filename="../gui/connectionoptionpage.ui" line="103"/>
<source>Syncthing URL</source> <source>Syncthing URL</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/connectionoptionpage.ui" line="121"/> <location filename="../gui/connectionoptionpage.ui" line="113"/>
<source>Authentication</source> <source>Authentication</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/connectionoptionpage.ui" line="134"/> <location filename="../gui/connectionoptionpage.ui" line="126"/>
<source>User</source> <source>User</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/connectionoptionpage.ui" line="212"/> <location filename="../gui/connectionoptionpage.ui" line="204"/>
<source>disconnected</source> <source>disconnected</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/connectionoptionpage.ui" line="219"/> <location filename="../gui/connectionoptionpage.ui" line="211"/>
<source>Apply connection settings and try to reconnect with the currently selected config</source> <source>Apply connection settings and try to reconnect with the currently selected config</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/connectionoptionpage.ui" line="255"/> <location filename="../gui/connectionoptionpage.ui" line="247"/>
<source>It is possible to save multiple configurations. This allows switching quickly between multiple Syncthing instances using the arrow in the right corner of the tray menu. The config label is an arbitrary name to identify a configuration and must not match the name of the corresponding Syncthing device.</source> <source>It is possible to save multiple configurations. This allows switching quickly between multiple Syncthing instances using the connection button in the right corner of the tray menu. The config label is an arbitrary name to identify a configuration and does not have to match the name of the corresponding Syncthing device.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/connectionoptionpage.ui" line="265"/> <location filename="../gui/connectionoptionpage.ui" line="257"/>
<source>HTTPS certificate</source> <source>HTTPS certificate</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/connectionoptionpage.ui" line="205"/> <location filename="../gui/connectionoptionpage.ui" line="197"/>
<source>Status</source> <source>Status</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/connectionoptionpage.ui" line="168"/> <location filename="../gui/connectionoptionpage.ui" line="160"/>
<source>API key</source> <source>API key</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/connectionoptionpage.ui" line="181"/> <location filename="../gui/connectionoptionpage.ui" line="173"/>
<source>Insert values from local Syncthing configuration</source> <source>Insert values from local Syncthing configuration</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/connectionoptionpage.ui" line="151"/> <location filename="../gui/connectionoptionpage.ui" line="143"/>
<source>Password</source> <source>Password</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -591,17 +604,17 @@
<context> <context>
<name>QtGui::DevView</name> <name>QtGui::DevView</name>
<message> <message>
<location filename="../gui/devview.cpp" line="45"/> <location filename="../gui/devview.cpp" line="49"/>
<source>Copy value</source> <source>Copy value</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/devview.cpp" line="47"/> <location filename="../gui/devview.cpp" line="51"/>
<source>Copy name</source> <source>Copy name</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/devview.cpp" line="48"/> <location filename="../gui/devview.cpp" line="52"/>
<source>Copy ID</source> <source>Copy ID</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -609,21 +622,34 @@
<context> <context>
<name>QtGui::DirView</name> <name>QtGui::DirView</name>
<message> <message>
<location filename="../gui/dirview.cpp" line="45"/> <location filename="../gui/dirview.cpp" line="53"/>
<source>Copy value</source> <source>Copy value</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/dirview.cpp" line="47"/> <location filename="../gui/dirview.cpp" line="55"/>
<source>Copy label/ID</source> <source>Copy label/ID</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/dirview.cpp" line="48"/> <location filename="../gui/dirview.cpp" line="56"/>
<source>Copy path</source> <source>Copy path</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
</context> </context>
<context>
<name>QtGui::DownloadView</name>
<message>
<location filename="../gui/downloadview.cpp" line="53"/>
<source>Copy value</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/downloadview.cpp" line="55"/>
<source>Copy label/ID</source>
<translation type="unfinished"></translation>
</message>
</context>
<context> <context>
<name>QtGui::LauncherOptionPage</name> <name>QtGui::LauncherOptionPage</name>
<message> <message>
@ -753,67 +779,72 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/trayicon.cpp" line="37"/> <location filename="../gui/trayicon.cpp" line="36"/>
<source>Rescan all</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/trayicon.cpp" line="38"/>
<source>About</source> <source>About</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/trayicon.cpp" line="39"/> <location filename="../gui/trayicon.cpp" line="40"/>
<source>Close</source> <source>Close</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/trayicon.cpp" line="84"/> <location filename="../gui/trayicon.cpp" line="85"/>
<source>Error</source> <source>Error</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/trayicon.cpp" line="91"/> <location filename="../gui/trayicon.cpp" line="92"/>
<source>Syncthing notification - click to dismiss</source> <source>Syncthing notification - click to dismiss</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/trayicon.cpp" line="100"/> <location filename="../gui/trayicon.cpp" line="101"/>
<source>Not connected to Syncthing</source> <source>Not connected to Syncthing</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/trayicon.cpp" line="102"/> <location filename="../gui/trayicon.cpp" line="103"/>
<source>Disconnected from Syncthing</source> <source>Disconnected from Syncthing</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/trayicon.cpp" line="107"/> <location filename="../gui/trayicon.cpp" line="108"/>
<source>Reconnecting ...</source> <source>Reconnecting ...</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/trayicon.cpp" line="111"/> <location filename="../gui/trayicon.cpp" line="112"/>
<source>Syncthing is idling</source> <source>Syncthing is idling</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/trayicon.cpp" line="115"/> <location filename="../gui/trayicon.cpp" line="116"/>
<source>Syncthing is scanning</source> <source>Syncthing is scanning</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/trayicon.cpp" line="119"/> <location filename="../gui/trayicon.cpp" line="120"/>
<source>Notifications available</source> <source>Notifications available</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/trayicon.cpp" line="123"/> <location filename="../gui/trayicon.cpp" line="124"/>
<source>At least one device is paused</source> <source>At least one device is paused</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/trayicon.cpp" line="127"/> <location filename="../gui/trayicon.cpp" line="128"/>
<source>Synchronization is ongoing</source> <source>Synchronization is ongoing</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/trayicon.cpp" line="137"/> <location filename="../gui/trayicon.cpp" line="138"/>
<source>Synchronization complete</source> <source>Synchronization complete</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -827,7 +858,7 @@
</message> </message>
<message> <message>
<location filename="../gui/traywidget.ui" line="107"/> <location filename="../gui/traywidget.ui" line="107"/>
<location filename="../gui/traywidget.cpp" line="230"/> <location filename="../gui/traywidget.cpp" line="235"/>
<source>Connect</source> <source>Connect</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -857,10 +888,15 @@
For &lt;i&gt;all&lt;/i&gt; notifications, checkout the log</source> For &lt;i&gt;all&lt;/i&gt; notifications, checkout the log</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<location filename="../gui/traywidget.ui" line="385"/>
<source>Downloads</source>
<translation type="unfinished"></translation>
</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.ui" line="250"/>
<location filename="../gui/traywidget.cpp" line="363"/> <location filename="../gui/traywidget.cpp" line="371"/>
<source>unknown</source> <source>unknown</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -875,18 +911,18 @@ For &lt;i&gt;all&lt;/i&gt; notifications, checkout the log</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.ui" line="326"/> <location filename="../gui/traywidget.ui" line="327"/>
<source>Directories</source> <source>Directories</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.ui" line="355"/> <location filename="../gui/traywidget.ui" line="356"/>
<source>Devices</source> <source>Devices</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.ui" line="80"/> <location filename="../gui/traywidget.ui" line="80"/>
<location filename="../gui/traywidget.cpp" line="140"/> <location filename="../gui/traywidget.cpp" line="145"/>
<source>About</source> <source>About</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -901,83 +937,88 @@ For &lt;i&gt;all&lt;/i&gt; notifications, checkout the log</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.cpp" line="70"/> <location filename="../gui/traywidget.cpp" line="72"/>
<source>View own device ID</source> <source>View own device ID</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.cpp" line="85"/> <location filename="../gui/traywidget.cpp" line="87"/>
<source>Rescan all directories</source> <source>Rescan all directories</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.cpp" line="80"/> <location filename="../gui/traywidget.cpp" line="82"/>
<source>Show Syncthing log</source> <source>Show Syncthing log</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.cpp" line="75"/> <location filename="../gui/traywidget.cpp" line="77"/>
<source>Restart Syncthing</source> <source>Restart Syncthing</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.cpp" line="92"/> <location filename="../gui/traywidget.cpp" line="94"/>
<source>Connection</source> <source>Connection</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.cpp" line="180"/> <location filename="../gui/traywidget.cpp" line="185"/>
<source>device ID is unknown</source> <source>device ID is unknown</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.cpp" line="188"/> <location filename="../gui/traywidget.cpp" line="193"/>
<source>Copy to clipboard</source> <source>Copy to clipboard</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.ui" line="276"/> <location filename="../gui/traywidget.ui" line="276"/>
<location filename="../gui/traywidget.cpp" line="216"/> <location filename="../gui/traywidget.cpp" line="221"/>
<source>New notifications</source> <source>New notifications</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.cpp" line="231"/> <location filename="../gui/traywidget.cpp" line="236"/>
<source>Not connected to Syncthing, click to connect</source> <source>Not connected to Syncthing, click to connect</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.cpp" line="243"/> <location filename="../gui/traywidget.cpp" line="248"/>
<source>Pause</source> <source>Pause</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.cpp" line="244"/> <location filename="../gui/traywidget.cpp" line="249"/>
<source>Syncthing is running, click to pause all devices</source> <source>Syncthing is running, click to pause all devices</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.cpp" line="250"/> <location filename="../gui/traywidget.cpp" line="255"/>
<source>At least one device is paused, click to resume</source> <source>At least one device is paused, click to resume</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.cpp" line="315"/> <location filename="../gui/traywidget.cpp" line="319"/>
<source>The directory &lt;i&gt;%1&lt;/i&gt; does not exist on the local machine.</source> <source>The directory &lt;i&gt;%1&lt;/i&gt; does not exist on the local machine.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.cpp" line="249"/> <location filename="../gui/traywidget.cpp" line="328"/>
<source>The file &lt;i&gt;%1&lt;/i&gt; does not exist on the local machine.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/traywidget.cpp" line="254"/>
<source>Continue</source> <source>Continue</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.cpp" line="170"/> <location filename="../gui/traywidget.cpp" line="175"/>
<source>Own device ID</source> <source>Own device ID</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui/traywidget.cpp" line="202"/> <location filename="../gui/traywidget.cpp" line="207"/>
<source>Log</source> <source>Log</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>