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_VERSION_MAJOR 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})
# add project files
@ -19,6 +19,7 @@ set(HEADER_FILES
data/syncthingconnection.h
data/syncthingdirectorymodel.h
data/syncthingdevicemodel.h
data/syncthingdownloadmodel.h
data/syncthingconfig.h
data/syncthingprocess.h
data/utils.h
@ -27,6 +28,7 @@ set(SRC_FILES
data/syncthingconnection.cpp
data/syncthingdirectorymodel.cpp
data/syncthingdevicemodel.cpp
data/syncthingdownloadmodel.cpp
data/syncthingconfig.cpp
data/syncthingprocess.cpp
data/utils.cpp
@ -43,8 +45,10 @@ set(WIDGETS_HEADER_FILES
gui/webviewprovider.h
gui/dirbuttonsitemdelegate.h
gui/devbuttonsitemdelegate.h
gui/downloaditemdelegate.h
gui/dirview.h
gui/devview.h
gui/downloadview.h
gui/textviewdialog.h
)
set(WIDGETS_SRC_FILES
@ -58,8 +62,10 @@ set(WIDGETS_SRC_FILES
gui/webviewdialog.cpp
gui/dirbuttonsitemdelegate.cpp
gui/devbuttonsitemdelegate.cpp
gui/downloaditemdelegate.cpp
gui/dirview.cpp
gui/devview.cpp
gui/downloadview.cpp
gui/textviewdialog.cpp
resources/icons.qrc
)
@ -100,6 +106,7 @@ set(REQUIRED_ICONS
edit-copy
edit-paste
folder
folder-download
folder-open
folder-sync
help-about

View File

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

View File

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

View File

@ -4,6 +4,7 @@
#include "../application/settings.h"
#include <c++utilities/conversion/conversionexception.h>
#include <c++utilities/conversion/stringconversion.h>
#include <QNetworkAccessManager>
#include <QNetworkReply>
@ -99,6 +100,27 @@ bool SyncthingDir::assignStatus(DirStatus newStatus, DateTime time)
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
* \brief The SyncthingConnection class allows Qt applications to access Syncthing.
@ -972,7 +994,7 @@ void SyncthingConnection::readEvents()
} else if(eventType == QLatin1String("StateChanged")) {
readStatusChangedEvent(eventTime, eventData);
} else if(eventType == QLatin1String("DownloadProgress")) {
readDownloadProgressEvent(eventData);
readDownloadProgressEvent(eventTime, eventData);
} else if(eventType.startsWith(QLatin1String("Folder"))) {
readDirEvent(eventTime, eventType, eventData);
} else if(eventType.startsWith(QLatin1String("Device"))) {
@ -1053,9 +1075,34 @@ void SyncthingConnection::readStatusChangedEvent(DateTime eventTime, const QJson
* \brief Reads results of requestEvents().
* \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 <QList>
#include <QSslError>
#include <QFileInfo>
#include <functional>
#include <vector>
@ -56,8 +57,27 @@ struct DirErrors
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
{
{
QString id;
QString label;
QString path;
@ -79,6 +99,11 @@ struct SyncthingDir
ChronoUtilities::DateTime lastFileTime;
QString lastFileName;
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(DirStatus newStatus, ChronoUtilities::DateTime time);
@ -215,6 +240,11 @@ Q_SIGNALS:
*/
void devStatusChanged(const SyncthingDev &dev, int index);
/*!
* \brief Indicates the download progress changed.
*/
void downloadProgressChanged();
/*!
* \brief Indicates a new Syncthing notification is available.
*/
@ -266,7 +296,7 @@ private Q_SLOTS:
void readEvents();
void readStartingEvent(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 readDeviceEvent(ChronoUtilities::DateTime eventTime, const QString &eventType, 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:
switch(index.column()) {
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()) {
case 2:
if(dev.lastSeen.isNull()) {
@ -128,7 +128,7 @@ QVariant SyncthingDeviceModel::data(const QModelIndex &index, int role) const
case 1:
switch(index.row()) {
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()) {
return agoString(dev.lastSeen);
}

View File

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

View File

@ -35,12 +35,12 @@ QModelIndex SyncthingDirectoryModel::index(int row, int column, const QModelInde
if(!parent.isValid()) {
// top-level: all dir labels/IDs
if(row < rowCount(parent)) {
return createIndex(row, column, -1);
return createIndex(row, column, static_cast<quintptr>(-1));
}
} else if(!parent.parent().isValid()) {
// dir-level: dir attributes
if(row < rowCount(parent)) {
return createIndex(row, column, parent.row());
return createIndex(row, column, static_cast<quintptr>(parent.row()));
}
}
return QModelIndex();
@ -48,7 +48,7 @@ QModelIndex SyncthingDirectoryModel::index(int row, int column, const QModelInde
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
@ -94,7 +94,7 @@ QVariant SyncthingDirectoryModel::data(const QModelIndex &index, int role) const
}
break;
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()) {
case 0: return dir.id;
case 1: return dir.path;
@ -110,7 +110,7 @@ QVariant SyncthingDirectoryModel::data(const QModelIndex &index, int role) const
case Qt::ForegroundRole:
switch(index.column()) {
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()) {
case 5:
if(dir.lastScanTime.isNull()) {
@ -130,7 +130,7 @@ QVariant SyncthingDirectoryModel::data(const QModelIndex &index, int role) const
case Qt::ToolTipRole:
switch(index.column()) {
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()) {
case 5:
if(!dir.lastScanTime.isNull()) {

View File

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

View File

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

View File

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

View File

@ -3,6 +3,10 @@
#include <QTreeView>
namespace Data {
struct SyncthingDir;
}
namespace QtGui {
class DirView : public QTreeView
@ -12,8 +16,8 @@ public:
DirView(QWidget *parent = nullptr);
Q_SIGNALS:
void openDir(const QModelIndex &index);
void scanDir(const QModelIndex &index);
void openDir(const Data::SyncthingDir &dir);
void scanDir(const Data::SyncthingDir &dir);
protected:
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
m_dirModel(m_connection),
m_devModel(m_connection),
m_dlModel(m_connection),
m_selectedConnection(nullptr)
{
m_ui->setupUi(this);
@ -59,6 +60,7 @@ TrayWidget::TrayWidget(TrayMenu *parent) :
// setup model and view
m_ui->dirsTreeView->setModel(&m_dirModel);
m_ui->devsTreeView->setModel(&m_devModel);
m_ui->downloadsTreeView->setModel(&m_dlModel);
// setup sync-all button
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::scanDir, this, &TrayWidget::scanDir);
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(viewIdButton, &QPushButton::clicked, this, &TrayWidget::showOwnDeviceId);
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()) {
DesktopUtils::openLocalFileOrDir(dir->path);
} else {
QMessageBox::warning(this, QCoreApplication::applicationName(), tr("The directory <i>%1</i> does not exist on the local machine.").arg(dir->path));
}
if(QDir(dir.path).exists()) {
DesktopUtils::openLocalFileOrDir(dir.path);
} else {
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)) {
m_connection.rescan(dir->id);
if(item.fileInfo.exists()) {
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)) {
if(dev->paused) {
m_connection.resume(dev->id);
} else {
m_connection.pause(dev->id);
}
m_connection.rescan(dir.id);
}
void TrayWidget::pauseResumeDev(const SyncthingDev &dev)
{
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/syncthingdirectorymodel.h"
#include "../data/syncthingdevicemodel.h"
#include "../data/syncthingdownloadmodel.h"
#include "../data/syncthingprocess.h"
#include "../application/settings.h"
@ -57,9 +58,10 @@ public slots:
private slots:
void handleStatusChanged(Data::SyncthingStatus status);
void applySettings();
void openDir(const QModelIndex &dirIndex);
void scanDir(const QModelIndex &dirIndex);
void pauseResumeDev(const QModelIndex &devIndex);
void openDir(const Data::SyncthingDir &dir);
void openItemDir(const Data::SyncthingItemDownloadProgress &item);
void scanDir(const Data::SyncthingDir &dir);
void pauseResumeDev(const Data::SyncthingDev &dev);
void changeStatus();
void updateTraffic();
#ifndef SYNCTHINGTRAY_NO_WEBVIEW
@ -81,6 +83,7 @@ private:
Data::SyncthingConnection m_connection;
Data::SyncthingDirectoryModel m_dirModel;
Data::SyncthingDeviceModel m_devModel;
Data::SyncthingDownloadModel m_dlModel;
QMenu *m_connectionsMenu;
QActionGroup *m_connectionsActionGroup;
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>
</property>
<property name="icon">
<iconset theme="dialog-warning"/>
<iconset theme="dialog-warning">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="flat">
<bool>true</bool>
@ -375,6 +376,35 @@ For &lt;i&gt;all&lt;/i&gt; notifications, checkout the log</string>
</item>
</layout>
</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>
</item>
</layout>
@ -390,6 +420,11 @@ For &lt;i&gt;all&lt;/i&gt; notifications, checkout the log</string>
<extends>QTreeView</extends>
<header>./gui/devview.h</header>
</customwidget>
<customwidget>
<class>QtGui::DownloadView</class>
<extends>QTreeView</extends>
<header>./gui/downloadview.h</header>
</customwidget>
</customwidgets>
<resources>
<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>
<name>Data::SyncthingConnection</name>
<message>
<location filename="../data/syncthingconnection.cpp" line="148"/>
<location filename="../data/syncthingconnection.cpp" line="172"/>
<source>disconnected</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../data/syncthingconnection.cpp" line="150"/>
<location filename="../data/syncthingconnection.cpp" line="174"/>
<source>reconnecting</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../data/syncthingconnection.cpp" line="152"/>
<location filename="../data/syncthingconnection.cpp" line="176"/>
<source>connected</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../data/syncthingconnection.cpp" line="154"/>
<location filename="../data/syncthingconnection.cpp" line="178"/>
<source>connected, notifications available</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../data/syncthingconnection.cpp" line="156"/>
<location filename="../data/syncthingconnection.cpp" line="180"/>
<source>connected, paused</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../data/syncthingconnection.cpp" line="158"/>
<location filename="../data/syncthingconnection.cpp" line="182"/>
<source>connected, synchronizing</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../data/syncthingconnection.cpp" line="160"/>
<location filename="../data/syncthingconnection.cpp" line="184"/>
<source>unknown</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../data/syncthingconnection.cpp" line="172"/>
<location filename="../data/syncthingconnection.cpp" line="252"/>
<location filename="../data/syncthingconnection.cpp" line="196"/>
<location filename="../data/syncthingconnection.cpp" line="276"/>
<source>Connection configuration is insufficient.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../data/syncthingconnection.cpp" line="532"/>
<location filename="../data/syncthingconnection.cpp" line="556"/>
<source>Unable to parse Syncthing log: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../data/syncthingconnection.cpp" line="536"/>
<location filename="../data/syncthingconnection.cpp" line="560"/>
<source>Unable to request system log: </source>
<translation type="unfinished"></translation>
</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>
<translation type="unfinished"></translation>
</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>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../data/syncthingconnection.cpp" line="597"/>
<location filename="../data/syncthingconnection.cpp" line="699"/>
<location filename="../data/syncthingconnection.cpp" line="621"/>
<location filename="../data/syncthingconnection.cpp" line="723"/>
<source>Unable to parse Syncthing config: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../data/syncthingconnection.cpp" line="603"/>
<location filename="../data/syncthingconnection.cpp" line="705"/>
<location filename="../data/syncthingconnection.cpp" line="627"/>
<location filename="../data/syncthingconnection.cpp" line="729"/>
<source>Unable to request Syncthing config: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../data/syncthingconnection.cpp" line="780"/>
<location filename="../data/syncthingconnection.cpp" line="804"/>
<source>Unable to parse connections: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../data/syncthingconnection.cpp" line="786"/>
<location filename="../data/syncthingconnection.cpp" line="810"/>
<source>Unable to request connections: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../data/syncthingconnection.cpp" line="841"/>
<location filename="../data/syncthingconnection.cpp" line="865"/>
<source>Unable to parse directory statistics: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../data/syncthingconnection.cpp" line="847"/>
<location filename="../data/syncthingconnection.cpp" line="871"/>
<source>Unable to request directory statistics: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../data/syncthingconnection.cpp" line="884"/>
<location filename="../data/syncthingconnection.cpp" line="908"/>
<source>Unable to parse device statistics: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../data/syncthingconnection.cpp" line="890"/>
<location filename="../data/syncthingconnection.cpp" line="914"/>
<source>Unable to request device statistics: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../data/syncthingconnection.cpp" line="925"/>
<location filename="../data/syncthingconnection.cpp" line="949"/>
<source>Unable to parse errors: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../data/syncthingconnection.cpp" line="936"/>
<location filename="../data/syncthingconnection.cpp" line="960"/>
<source>Unable to request errors: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../data/syncthingconnection.cpp" line="987"/>
<location filename="../data/syncthingconnection.cpp" line="1011"/>
<source>Unable to parse Syncthing events: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../data/syncthingconnection.cpp" line="1006"/>
<location filename="../data/syncthingconnection.cpp" line="1030"/>
<source>Unable to request Syncthing events: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../data/syncthingconnection.cpp" line="1218"/>
<location filename="../data/syncthingconnection.cpp" line="1272"/>
<source>Unable to request rescan: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../data/syncthingconnection.cpp" line="1233"/>
<location filename="../data/syncthingconnection.cpp" line="1287"/>
<source>Unable to request pause/resume: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../data/syncthingconnection.cpp" line="1248"/>
<location filename="../data/syncthingconnection.cpp" line="1302"/>
<source>Unable to request restart: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../data/syncthingconnection.cpp" line="503"/>
<location filename="../data/syncthingconnection.cpp" line="527"/>
<source>Unable to request QR-Code: </source>
<translation type="unfinished"></translation>
</message>
@ -361,6 +361,19 @@
<translation type="unfinished"></translation>
</message>
</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>
<name>Data::Utils</name>
<message>
@ -488,77 +501,77 @@
<context>
<name>QtGui::ConnectionOptionPage</name>
<message>
<location filename="../gui/connectionoptionpage.ui" line="14"/>
<location filename="../gui/connectionoptionpage.ui" line="6"/>
<source>Connection</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/connectionoptionpage.ui" line="30"/>
<location filename="../gui/connectionoptionpage.ui" line="22"/>
<source>Config label</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/connectionoptionpage.ui" line="80"/>
<location filename="../gui/connectionoptionpage.ui" line="72"/>
<source>Add secondary instance</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/connectionoptionpage.ui" line="97"/>
<location filename="../gui/connectionoptionpage.ui" line="89"/>
<source>Remove currently selected secondary instance</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/connectionoptionpage.ui" line="111"/>
<location filename="../gui/connectionoptionpage.ui" line="103"/>
<source>Syncthing URL</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/connectionoptionpage.ui" line="121"/>
<location filename="../gui/connectionoptionpage.ui" line="113"/>
<source>Authentication</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/connectionoptionpage.ui" line="134"/>
<location filename="../gui/connectionoptionpage.ui" line="126"/>
<source>User</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/connectionoptionpage.ui" line="212"/>
<location filename="../gui/connectionoptionpage.ui" line="204"/>
<source>disconnected</source>
<translation type="unfinished"></translation>
</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>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/connectionoptionpage.ui" line="255"/>
<source>It is possible to save multiple configurations. This allows switching quickly between multiple Syncthing instances using the arrow in the right corner of the tray menu. The config label is an arbitrary name to identify a configuration and must not match the name of the corresponding Syncthing device.</source>
<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 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>
</message>
<message>
<location filename="../gui/connectionoptionpage.ui" line="265"/>
<location filename="../gui/connectionoptionpage.ui" line="257"/>
<source>HTTPS certificate</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/connectionoptionpage.ui" line="205"/>
<location filename="../gui/connectionoptionpage.ui" line="197"/>
<source>Status</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/connectionoptionpage.ui" line="168"/>
<location filename="../gui/connectionoptionpage.ui" line="160"/>
<source>API key</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/connectionoptionpage.ui" line="181"/>
<location filename="../gui/connectionoptionpage.ui" line="173"/>
<source>Insert values from local Syncthing configuration</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/connectionoptionpage.ui" line="151"/>
<location filename="../gui/connectionoptionpage.ui" line="143"/>
<source>Password</source>
<translation type="unfinished"></translation>
</message>
@ -591,17 +604,17 @@
<context>
<name>QtGui::DevView</name>
<message>
<location filename="../gui/devview.cpp" line="45"/>
<location filename="../gui/devview.cpp" line="49"/>
<source>Copy value</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/devview.cpp" line="47"/>
<location filename="../gui/devview.cpp" line="51"/>
<source>Copy name</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/devview.cpp" line="48"/>
<location filename="../gui/devview.cpp" line="52"/>
<source>Copy ID</source>
<translation type="unfinished"></translation>
</message>
@ -609,21 +622,34 @@
<context>
<name>QtGui::DirView</name>
<message>
<location filename="../gui/dirview.cpp" line="45"/>
<location filename="../gui/dirview.cpp" line="53"/>
<source>Copy value</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/dirview.cpp" line="47"/>
<location filename="../gui/dirview.cpp" line="55"/>
<source>Copy label/ID</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/dirview.cpp" line="48"/>
<location filename="../gui/dirview.cpp" line="56"/>
<source>Copy path</source>
<translation type="unfinished"></translation>
</message>
</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>
<name>QtGui::LauncherOptionPage</name>
<message>
@ -753,67 +779,72 @@
<translation type="unfinished"></translation>
</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>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/trayicon.cpp" line="39"/>
<location filename="../gui/trayicon.cpp" line="40"/>
<source>Close</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/trayicon.cpp" line="84"/>
<location filename="../gui/trayicon.cpp" line="85"/>
<source>Error</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/trayicon.cpp" line="91"/>
<location filename="../gui/trayicon.cpp" line="92"/>
<source>Syncthing notification - click to dismiss</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/trayicon.cpp" line="100"/>
<location filename="../gui/trayicon.cpp" line="101"/>
<source>Not connected to Syncthing</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/trayicon.cpp" line="102"/>
<location filename="../gui/trayicon.cpp" line="103"/>
<source>Disconnected from Syncthing</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/trayicon.cpp" line="107"/>
<location filename="../gui/trayicon.cpp" line="108"/>
<source>Reconnecting ...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/trayicon.cpp" line="111"/>
<location filename="../gui/trayicon.cpp" line="112"/>
<source>Syncthing is idling</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/trayicon.cpp" line="115"/>
<location filename="../gui/trayicon.cpp" line="116"/>
<source>Syncthing is scanning</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/trayicon.cpp" line="119"/>
<location filename="../gui/trayicon.cpp" line="120"/>
<source>Notifications available</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/trayicon.cpp" line="123"/>
<location filename="../gui/trayicon.cpp" line="124"/>
<source>At least one device is paused</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/trayicon.cpp" line="127"/>
<location filename="../gui/trayicon.cpp" line="128"/>
<source>Synchronization is ongoing</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/trayicon.cpp" line="137"/>
<location filename="../gui/trayicon.cpp" line="138"/>
<source>Synchronization complete</source>
<translation type="unfinished"></translation>
</message>
@ -827,7 +858,7 @@
</message>
<message>
<location filename="../gui/traywidget.ui" line="107"/>
<location filename="../gui/traywidget.cpp" line="230"/>
<location filename="../gui/traywidget.cpp" line="235"/>
<source>Connect</source>
<translation type="unfinished"></translation>
</message>
@ -857,10 +888,15 @@
For &lt;i&gt;all&lt;/i&gt; notifications, checkout the log</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/traywidget.ui" line="385"/>
<source>Downloads</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/traywidget.ui" line="230"/>
<location filename="../gui/traywidget.ui" line="250"/>
<location filename="../gui/traywidget.cpp" line="363"/>
<location filename="../gui/traywidget.cpp" line="371"/>
<source>unknown</source>
<translation type="unfinished"></translation>
</message>
@ -875,18 +911,18 @@ For &lt;i&gt;all&lt;/i&gt; notifications, checkout the log</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/traywidget.ui" line="326"/>
<location filename="../gui/traywidget.ui" line="327"/>
<source>Directories</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/traywidget.ui" line="355"/>
<location filename="../gui/traywidget.ui" line="356"/>
<source>Devices</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/traywidget.ui" line="80"/>
<location filename="../gui/traywidget.cpp" line="140"/>
<location filename="../gui/traywidget.cpp" line="145"/>
<source>About</source>
<translation type="unfinished"></translation>
</message>
@ -901,83 +937,88 @@ For &lt;i&gt;all&lt;/i&gt; notifications, checkout the log</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/traywidget.cpp" line="70"/>
<location filename="../gui/traywidget.cpp" line="72"/>
<source>View own device ID</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/traywidget.cpp" line="85"/>
<location filename="../gui/traywidget.cpp" line="87"/>
<source>Rescan all directories</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/traywidget.cpp" line="80"/>
<location filename="../gui/traywidget.cpp" line="82"/>
<source>Show Syncthing log</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/traywidget.cpp" line="75"/>
<location filename="../gui/traywidget.cpp" line="77"/>
<source>Restart Syncthing</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/traywidget.cpp" line="92"/>
<location filename="../gui/traywidget.cpp" line="94"/>
<source>Connection</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/traywidget.cpp" line="180"/>
<location filename="../gui/traywidget.cpp" line="185"/>
<source>device ID is unknown</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/traywidget.cpp" line="188"/>
<location filename="../gui/traywidget.cpp" line="193"/>
<source>Copy to clipboard</source>
<translation type="unfinished"></translation>
</message>
<message>
<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>
<translation type="unfinished"></translation>
</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>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/traywidget.cpp" line="243"/>
<location filename="../gui/traywidget.cpp" line="248"/>
<source>Pause</source>
<translation type="unfinished"></translation>
</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>
<translation type="unfinished"></translation>
</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>
<translation type="unfinished"></translation>
</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>
<translation type="unfinished"></translation>
</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>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/traywidget.cpp" line="170"/>
<location filename="../gui/traywidget.cpp" line="175"/>
<source>Own device ID</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui/traywidget.cpp" line="202"/>
<location filename="../gui/traywidget.cpp" line="207"/>
<source>Log</source>
<translation type="unfinished"></translation>
</message>

View File

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