Show recent changes
This commit is contained in:
parent
e76d4afff5
commit
6026339c83
|
@ -218,6 +218,7 @@ Q_SIGNALS:
|
||||||
void newEvents(const QJsonArray &events);
|
void newEvents(const QJsonArray &events);
|
||||||
void dirStatusChanged(const SyncthingDir &dir, int index);
|
void dirStatusChanged(const SyncthingDir &dir, int index);
|
||||||
void devStatusChanged(const SyncthingDev &dev, int index);
|
void devStatusChanged(const SyncthingDev &dev, int index);
|
||||||
|
void fileChanged(const SyncthingDir &dir, int index, const SyncthingFileChange &fileChange);
|
||||||
void downloadProgressChanged();
|
void downloadProgressChanged();
|
||||||
void dirStatisticsChanged();
|
void dirStatisticsChanged();
|
||||||
void dirCompleted(CppUtilities::DateTime when, const SyncthingDir &dir, int index, const SyncthingDev *remoteDev = nullptr);
|
void dirCompleted(CppUtilities::DateTime when, const SyncthingDir &dir, int index, const SyncthingDev *remoteDev = nullptr);
|
||||||
|
|
|
@ -1488,6 +1488,7 @@ void SyncthingConnection::readChangeEvent(DateTime eventTime, const QString &eve
|
||||||
change.path = eventData.value(QLatin1String("path")).toString();
|
change.path = eventData.value(QLatin1String("path")).toString();
|
||||||
dirInfo->recentChanges.emplace_back(move(change));
|
dirInfo->recentChanges.emplace_back(move(change));
|
||||||
emit dirStatusChanged(*dirInfo, index);
|
emit dirStatusChanged(*dirInfo, index);
|
||||||
|
emit fileChanged(*dirInfo, index, dirInfo->recentChanges.back());
|
||||||
}
|
}
|
||||||
|
|
||||||
// events / long polling API
|
// events / long polling API
|
||||||
|
|
|
@ -14,11 +14,18 @@ set(HEADER_FILES
|
||||||
syncthingdirectorymodel.h
|
syncthingdirectorymodel.h
|
||||||
syncthingdevicemodel.h
|
syncthingdevicemodel.h
|
||||||
syncthingdownloadmodel.h
|
syncthingdownloadmodel.h
|
||||||
|
syncthingrecentchangesmodel.h
|
||||||
syncthingstatusselectionmodel.h
|
syncthingstatusselectionmodel.h
|
||||||
syncthingicons.h
|
syncthingicons.h
|
||||||
colors.h)
|
colors.h)
|
||||||
set(SRC_FILES syncthingmodel.cpp syncthingdirectorymodel.cpp syncthingdevicemodel.cpp syncthingdownloadmodel.cpp
|
set(SRC_FILES
|
||||||
syncthingstatusselectionmodel.cpp syncthingicons.cpp)
|
syncthingmodel.cpp
|
||||||
|
syncthingdirectorymodel.cpp
|
||||||
|
syncthingdevicemodel.cpp
|
||||||
|
syncthingdownloadmodel.cpp
|
||||||
|
syncthingrecentchangesmodel.cpp
|
||||||
|
syncthingstatusselectionmodel.cpp
|
||||||
|
syncthingicons.cpp)
|
||||||
set(RES_FILES resources/${META_PROJECT_NAME}icons.qrc)
|
set(RES_FILES resources/${META_PROJECT_NAME}icons.qrc)
|
||||||
|
|
||||||
set(TS_FILES translations/${META_PROJECT_NAME}_cs_CZ.ts translations/${META_PROJECT_NAME}_de_DE.ts
|
set(TS_FILES translations/${META_PROJECT_NAME}_cs_CZ.ts translations/${META_PROJECT_NAME}_de_DE.ts
|
||||||
|
|
|
@ -14,7 +14,7 @@ using namespace CppUtilities;
|
||||||
|
|
||||||
namespace Data {
|
namespace Data {
|
||||||
|
|
||||||
int computeDirectoryRowCount(const SyncthingDir &dir)
|
static int computeDirectoryRowCount(const SyncthingDir &dir)
|
||||||
{
|
{
|
||||||
return dir.paused ? 8 : 10;
|
return dir.paused ? 8 : 10;
|
||||||
}
|
}
|
||||||
|
@ -260,10 +260,10 @@ QVariant SyncthingDirectoryModel::data(const QModelIndex &index, int role) const
|
||||||
if (!dir.lastFileTime.isNull()) {
|
if (!dir.lastFileTime.isNull()) {
|
||||||
if (dir.lastFileDeleted) {
|
if (dir.lastFileDeleted) {
|
||||||
return tr("Deleted at %1")
|
return tr("Deleted at %1")
|
||||||
.arg(QString::fromLatin1(dir.lastFileTime.toString(DateTimeOutputFormat::DateAndTime, true).data()));
|
.arg(QString::fromStdString(dir.lastFileTime.toString(DateTimeOutputFormat::DateAndTime, true)));
|
||||||
} else {
|
} else {
|
||||||
return tr("Updated at %1")
|
return tr("Updated at %1")
|
||||||
.arg(QString::fromLatin1(dir.lastFileTime.toString(DateTimeOutputFormat::DateAndTime, true).data()));
|
.arg(QString::fromStdString(dir.lastFileTime.toString(DateTimeOutputFormat::DateAndTime, true)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -0,0 +1,205 @@
|
||||||
|
#include "./syncthingrecentchangesmodel.h"
|
||||||
|
#include "./colors.h"
|
||||||
|
#include "./syncthingicons.h"
|
||||||
|
|
||||||
|
#include "../connector/syncthingconnection.h"
|
||||||
|
#include "../connector/utils.h"
|
||||||
|
|
||||||
|
#include <c++utilities/conversion/stringconversion.h>
|
||||||
|
|
||||||
|
#include <QStringBuilder>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace CppUtilities;
|
||||||
|
|
||||||
|
namespace Data {
|
||||||
|
|
||||||
|
SyncthingRecentChangesModel::SyncthingRecentChangesModel(SyncthingConnection &connection, QObject *parent)
|
||||||
|
: SyncthingModel(connection, parent)
|
||||||
|
{
|
||||||
|
for (const auto &dir : connection.dirInfo()) {
|
||||||
|
for (const auto &fileChange : dir.recentChanges) {
|
||||||
|
fileChanged(dir, -1, fileChange);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
connect(&m_connection, &SyncthingConnection::fileChanged, this, &SyncthingRecentChangesModel::fileChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
QHash<int, QByteArray> SyncthingRecentChangesModel::roleNames() const
|
||||||
|
{
|
||||||
|
const static QHash<int, QByteArray> roles{
|
||||||
|
{ Action, "action" },
|
||||||
|
{ ActionIcon, "actionIcon" },
|
||||||
|
{ ModifiedBy, "modifiedBy" },
|
||||||
|
{ DirectoryId, "directoryId" },
|
||||||
|
{ DirectoryName, "directoryName" },
|
||||||
|
{ Path, "path" },
|
||||||
|
{ EventTime, "eventTime" },
|
||||||
|
{ ExtendedAction, "extendedAction" },
|
||||||
|
{ ItemType, "itemType" },
|
||||||
|
};
|
||||||
|
return roles;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QVector<int> &SyncthingRecentChangesModel::colorRoles() const
|
||||||
|
{
|
||||||
|
static const QVector<int> colorRoles({ Qt::DecorationRole, Qt::ForegroundRole });
|
||||||
|
return colorRoles;
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex SyncthingRecentChangesModel::index(int row, int column, const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
if (static_cast<size_t>(row) >= m_changes.size() || parent.isValid()) {
|
||||||
|
return QModelIndex();
|
||||||
|
}
|
||||||
|
return createIndex(row, column, static_cast<quintptr>(-1));
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex SyncthingRecentChangesModel::parent(const QModelIndex &child) const
|
||||||
|
{
|
||||||
|
return QModelIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant SyncthingRecentChangesModel::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("Action");
|
||||||
|
case 1:
|
||||||
|
return tr("Device");
|
||||||
|
case 2:
|
||||||
|
return tr("Directory");
|
||||||
|
case 3:
|
||||||
|
return tr("Path");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:;
|
||||||
|
}
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant SyncthingRecentChangesModel::data(const QModelIndex &index, int role) const
|
||||||
|
{
|
||||||
|
if (!index.isValid() || index.parent().isValid() || static_cast<size_t>(index.row()) >= m_changes.size()) {
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
const SyncthingRecentChange &change = m_changes[m_changes.size() - static_cast<size_t>(index.row()) - 1];
|
||||||
|
switch (role) {
|
||||||
|
case Qt::DisplayRole:
|
||||||
|
case Qt::EditRole:
|
||||||
|
switch (index.column()) {
|
||||||
|
case 0:
|
||||||
|
return change.fileChange.action;
|
||||||
|
case 1:
|
||||||
|
return change.fileChange.modifiedBy;
|
||||||
|
case 2:
|
||||||
|
return change.directoryId;
|
||||||
|
case 3:
|
||||||
|
return change.fileChange.path;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Qt::DecorationRole:
|
||||||
|
case ActionIcon:
|
||||||
|
switch (index.column()) {
|
||||||
|
case 0:
|
||||||
|
if (change.fileChange.local) {
|
||||||
|
return m_brightColors ? fontAwesomeIconsForDarkTheme().home : fontAwesomeIconsForLightTheme().home;
|
||||||
|
} else {
|
||||||
|
return m_brightColors ? fontAwesomeIconsForDarkTheme().globe : fontAwesomeIconsForLightTheme().globe;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Qt::ToolTipRole:
|
||||||
|
switch (index.column()) {
|
||||||
|
case 0:
|
||||||
|
return QString((change.fileChange.local ? tr("Locally") : tr("Remotely")) % QChar(' ') % change.fileChange.action % QStringLiteral(", ")
|
||||||
|
% QString::fromStdString(change.fileChange.eventTime.toString(DateTimeOutputFormat::DateAndTime, true)));
|
||||||
|
case 3:
|
||||||
|
return change.fileChange.path; // usually too long so add a tooltip
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Action:
|
||||||
|
return change.fileChange.action;
|
||||||
|
case ModifiedBy:
|
||||||
|
return change.fileChange.modifiedBy;
|
||||||
|
case DirectoryId:
|
||||||
|
return change.directoryId;
|
||||||
|
case DirectoryName:
|
||||||
|
return change.directoryName;
|
||||||
|
case Path:
|
||||||
|
return change.fileChange.path;
|
||||||
|
case EventTime:
|
||||||
|
return QString::fromStdString(change.fileChange.eventTime.toString(DateTimeOutputFormat::DateAndTime, true));
|
||||||
|
case ExtendedAction: {
|
||||||
|
auto extendedAction = change.fileChange.action;
|
||||||
|
extendedAction[0] = extendedAction[0].toUpper();
|
||||||
|
return QVariant(move(extendedAction));
|
||||||
|
}
|
||||||
|
case ItemType:
|
||||||
|
return change.fileChange.type;
|
||||||
|
default:;
|
||||||
|
}
|
||||||
|
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SyncthingRecentChangesModel::setData(const QModelIndex &index, const QVariant &value, int role)
|
||||||
|
{
|
||||||
|
Q_UNUSED(index)
|
||||||
|
Q_UNUSED(value)
|
||||||
|
Q_UNUSED(role)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SyncthingRecentChangesModel::rowCount(const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
if (!parent.isValid()) {
|
||||||
|
return static_cast<int>(m_changes.size());
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int SyncthingRecentChangesModel::columnCount(const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
if (!parent.isValid()) {
|
||||||
|
return 4; // action, device, folder, path
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SyncthingRecentChangesModel::fileChanged(const SyncthingDir &dir, int index, const SyncthingFileChange &change)
|
||||||
|
{
|
||||||
|
Q_UNUSED(index)
|
||||||
|
|
||||||
|
if (index >= 0) {
|
||||||
|
beginInsertRows(QModelIndex(), 0, 0);
|
||||||
|
}
|
||||||
|
m_changes.emplace_back(SyncthingRecentChange{
|
||||||
|
.directoryId = dir.id,
|
||||||
|
.directoryName = dir.displayName(),
|
||||||
|
.fileChange = change,
|
||||||
|
});
|
||||||
|
if (index >= 0) {
|
||||||
|
endInsertRows();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SyncthingRecentChangesModel::handleConfigInvalidated()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void SyncthingRecentChangesModel::handleNewConfigAvailable()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Data
|
|
@ -0,0 +1,59 @@
|
||||||
|
#ifndef DATA_SYNCTHINGRECENTCHANGESMODEL_H
|
||||||
|
#define DATA_SYNCTHINGRECENTCHANGESMODEL_H
|
||||||
|
|
||||||
|
#include "./syncthingmodel.h"
|
||||||
|
|
||||||
|
#include "../connector/syncthingdir.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace Data {
|
||||||
|
|
||||||
|
struct LIB_SYNCTHING_MODEL_EXPORT SyncthingRecentChange {
|
||||||
|
QString directoryId;
|
||||||
|
QString directoryName;
|
||||||
|
SyncthingFileChange fileChange;
|
||||||
|
};
|
||||||
|
|
||||||
|
class LIB_SYNCTHING_MODEL_EXPORT SyncthingRecentChangesModel : public SyncthingModel {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
enum SyncthingRecentChangesModelRole {
|
||||||
|
Action = Qt::UserRole + 1,
|
||||||
|
ActionIcon,
|
||||||
|
ModifiedBy,
|
||||||
|
DirectoryId,
|
||||||
|
DirectoryName,
|
||||||
|
Path,
|
||||||
|
EventTime,
|
||||||
|
ExtendedAction,
|
||||||
|
ItemType,
|
||||||
|
};
|
||||||
|
|
||||||
|
explicit SyncthingRecentChangesModel(SyncthingConnection &connection, QObject *parent = nullptr);
|
||||||
|
|
||||||
|
public Q_SLOTS:
|
||||||
|
QHash<int, QByteArray> roleNames() const override;
|
||||||
|
const QVector<int> &colorRoles() const override;
|
||||||
|
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
QModelIndex parent(const QModelIndex &child) const override;
|
||||||
|
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||||
|
QVariant data(const QModelIndex &index, int role) const override;
|
||||||
|
bool setData(const QModelIndex &index, const QVariant &value, int role) override;
|
||||||
|
int rowCount(const QModelIndex &parent) const override;
|
||||||
|
int columnCount(const QModelIndex &parent) const override;
|
||||||
|
|
||||||
|
private Q_SLOTS:
|
||||||
|
void fileChanged(const SyncthingDir &dir, int index, const SyncthingFileChange &change);
|
||||||
|
void handleConfigInvalidated() override;
|
||||||
|
void handleNewConfigAvailable() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<SyncthingRecentChange> m_changes;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Data
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE(Data::SyncthingRecentChange)
|
||||||
|
|
||||||
|
#endif // DATA_SYNCTHINGRECENTCHANGESMODEL_H
|
|
@ -9,6 +9,7 @@ set(PLASMOID_FILES
|
||||||
../package/contents/ui/DirectoriesPage.qml
|
../package/contents/ui/DirectoriesPage.qml
|
||||||
../package/contents/ui/DevicesPage.qml
|
../package/contents/ui/DevicesPage.qml
|
||||||
../package/contents/ui/DownloadsPage.qml
|
../package/contents/ui/DownloadsPage.qml
|
||||||
|
../package/contents/ui/RecentChangesPage.qml
|
||||||
../package/contents/ui/TopLevelView.qml
|
../package/contents/ui/TopLevelView.qml
|
||||||
../package/contents/ui/TopLevelItem.qml
|
../package/contents/ui/TopLevelItem.qml
|
||||||
../package/contents/ui/DetailView.qml
|
../package/contents/ui/DetailView.qml
|
||||||
|
|
|
@ -55,6 +55,7 @@ SyncthingApplet::SyncthingApplet(QObject *parent, const QVariantList &data)
|
||||||
, m_dirModel(m_connection)
|
, m_dirModel(m_connection)
|
||||||
, m_devModel(m_connection)
|
, m_devModel(m_connection)
|
||||||
, m_downloadModel(m_connection)
|
, m_downloadModel(m_connection)
|
||||||
|
, m_recentChangesModel(m_connection)
|
||||||
, m_settingsDlg(nullptr)
|
, m_settingsDlg(nullptr)
|
||||||
#ifndef SYNCTHINGWIDGETS_NO_WEBVIEW
|
#ifndef SYNCTHINGWIDGETS_NO_WEBVIEW
|
||||||
, m_webViewDlg(nullptr)
|
, m_webViewDlg(nullptr)
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include "../../model/syncthingdevicemodel.h"
|
#include "../../model/syncthingdevicemodel.h"
|
||||||
#include "../../model/syncthingdirectorymodel.h"
|
#include "../../model/syncthingdirectorymodel.h"
|
||||||
#include "../../model/syncthingdownloadmodel.h"
|
#include "../../model/syncthingdownloadmodel.h"
|
||||||
|
#include "../../model/syncthingrecentchangesmodel.h"
|
||||||
#include "../../model/syncthingstatusselectionmodel.h"
|
#include "../../model/syncthingstatusselectionmodel.h"
|
||||||
|
|
||||||
#include "../../connector/syncthingconnection.h"
|
#include "../../connector/syncthingconnection.h"
|
||||||
|
@ -22,13 +23,7 @@
|
||||||
#include <QSize>
|
#include <QSize>
|
||||||
|
|
||||||
namespace Data {
|
namespace Data {
|
||||||
class SyncthingConnection;
|
|
||||||
struct SyncthingConnectionSettings;
|
struct SyncthingConnectionSettings;
|
||||||
class SyncthingDirectoryModel;
|
|
||||||
class SyncthingDeviceModel;
|
|
||||||
class SyncthingDownloadModel;
|
|
||||||
class SyncthingService;
|
|
||||||
enum class SyncthingErrorCategory;
|
|
||||||
} // namespace Data
|
} // namespace Data
|
||||||
|
|
||||||
namespace QtGui {
|
namespace QtGui {
|
||||||
|
@ -45,6 +40,7 @@ class SyncthingApplet : public Plasma::Applet {
|
||||||
Q_PROPERTY(Data::SyncthingDirectoryModel *dirModel READ dirModel NOTIFY dirModelChanged)
|
Q_PROPERTY(Data::SyncthingDirectoryModel *dirModel READ dirModel NOTIFY dirModelChanged)
|
||||||
Q_PROPERTY(Data::SyncthingDeviceModel *devModel READ devModel NOTIFY devModelChanged)
|
Q_PROPERTY(Data::SyncthingDeviceModel *devModel READ devModel NOTIFY devModelChanged)
|
||||||
Q_PROPERTY(Data::SyncthingDownloadModel *downloadModel READ downloadModel NOTIFY downloadModelChanged)
|
Q_PROPERTY(Data::SyncthingDownloadModel *downloadModel READ downloadModel NOTIFY downloadModelChanged)
|
||||||
|
Q_PROPERTY(Data::SyncthingRecentChangesModel *recentChangesModel READ recentChangesModel NOTIFY recentChangesModelChanged)
|
||||||
Q_PROPERTY(Data::SyncthingStatusSelectionModel *passiveSelectionModel READ passiveSelectionModel NOTIFY passiveSelectionModelChanged)
|
Q_PROPERTY(Data::SyncthingStatusSelectionModel *passiveSelectionModel READ passiveSelectionModel NOTIFY passiveSelectionModelChanged)
|
||||||
Q_PROPERTY(Data::SyncthingService *service READ service NOTIFY serviceChanged)
|
Q_PROPERTY(Data::SyncthingService *service READ service NOTIFY serviceChanged)
|
||||||
Q_PROPERTY(bool local READ isLocal NOTIFY localChanged)
|
Q_PROPERTY(bool local READ isLocal NOTIFY localChanged)
|
||||||
|
@ -76,6 +72,7 @@ public:
|
||||||
Data::SyncthingDirectoryModel *dirModel() const;
|
Data::SyncthingDirectoryModel *dirModel() const;
|
||||||
Data::SyncthingDeviceModel *devModel() const;
|
Data::SyncthingDeviceModel *devModel() const;
|
||||||
Data::SyncthingDownloadModel *downloadModel() const;
|
Data::SyncthingDownloadModel *downloadModel() const;
|
||||||
|
Data::SyncthingRecentChangesModel *recentChangesModel() const;
|
||||||
Data::SyncthingStatusSelectionModel *passiveSelectionModel() const;
|
Data::SyncthingStatusSelectionModel *passiveSelectionModel() const;
|
||||||
Data::SyncthingService *service() const;
|
Data::SyncthingService *service() const;
|
||||||
bool isLocal() const;
|
bool isLocal() const;
|
||||||
|
@ -128,6 +125,8 @@ Q_SIGNALS:
|
||||||
/// \remarks Never emitted, just to silence "... depends on non-NOTIFYable ..."
|
/// \remarks Never emitted, just to silence "... depends on non-NOTIFYable ..."
|
||||||
void downloadModelChanged();
|
void downloadModelChanged();
|
||||||
/// \remarks Never emitted, just to silence "... depends on non-NOTIFYable ..."
|
/// \remarks Never emitted, just to silence "... depends on non-NOTIFYable ..."
|
||||||
|
void recentChangesModelChanged();
|
||||||
|
/// \remarks Never emitted, just to silence "... depends on non-NOTIFYable ..."
|
||||||
void passiveSelectionModelChanged();
|
void passiveSelectionModelChanged();
|
||||||
/// \remarks Never emitted, just to silence "... depends on non-NOTIFYable ..."
|
/// \remarks Never emitted, just to silence "... depends on non-NOTIFYable ..."
|
||||||
void serviceChanged();
|
void serviceChanged();
|
||||||
|
@ -172,6 +171,7 @@ private:
|
||||||
Data::SyncthingDirectoryModel m_dirModel;
|
Data::SyncthingDirectoryModel m_dirModel;
|
||||||
Data::SyncthingDeviceModel m_devModel;
|
Data::SyncthingDeviceModel m_devModel;
|
||||||
Data::SyncthingDownloadModel m_downloadModel;
|
Data::SyncthingDownloadModel m_downloadModel;
|
||||||
|
Data::SyncthingRecentChangesModel m_recentChangesModel;
|
||||||
Data::SyncthingStatusSelectionModel m_passiveSelectionModel;
|
Data::SyncthingStatusSelectionModel m_passiveSelectionModel;
|
||||||
SettingsDialog *m_settingsDlg;
|
SettingsDialog *m_settingsDlg;
|
||||||
QtGui::DBusStatusNotifier m_dbusNotifier;
|
QtGui::DBusStatusNotifier m_dbusNotifier;
|
||||||
|
@ -204,6 +204,11 @@ inline Data::SyncthingDownloadModel *SyncthingApplet::downloadModel() const
|
||||||
return const_cast<Data::SyncthingDownloadModel *>(&m_downloadModel);
|
return const_cast<Data::SyncthingDownloadModel *>(&m_downloadModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline Data::SyncthingRecentChangesModel *SyncthingApplet::recentChangesModel() const
|
||||||
|
{
|
||||||
|
return const_cast<Data::SyncthingRecentChangesModel *>(&m_recentChangesModel);
|
||||||
|
}
|
||||||
|
|
||||||
inline Data::SyncthingStatusSelectionModel *SyncthingApplet::passiveSelectionModel() const
|
inline Data::SyncthingStatusSelectionModel *SyncthingApplet::passiveSelectionModel() const
|
||||||
{
|
{
|
||||||
return const_cast<Data::SyncthingStatusSelectionModel *>(&m_passiveSelectionModel);
|
return const_cast<Data::SyncthingStatusSelectionModel *>(&m_passiveSelectionModel);
|
||||||
|
|
|
@ -523,6 +523,13 @@ ColumnLayout {
|
||||||
iconSource: "folder-download-symbolic"
|
iconSource: "folder-download-symbolic"
|
||||||
tab: downloadsPage
|
tab: downloadsPage
|
||||||
}
|
}
|
||||||
|
PlasmaComponents.TabButton {
|
||||||
|
id: recentChangesTabButton
|
||||||
|
//text: qsTr("Recent changes")
|
||||||
|
iconSource: "document-open-recent-symbolic"
|
||||||
|
tab: recentChangesPage
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
Item {
|
Item {
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
|
@ -577,6 +584,11 @@ ColumnLayout {
|
||||||
when: mainTabGroup.currentTab === downloadsPage
|
when: mainTabGroup.currentTab === downloadsPage
|
||||||
source: Qt.resolvedUrl("DownloadsPage.qml")
|
source: Qt.resolvedUrl("DownloadsPage.qml")
|
||||||
}
|
}
|
||||||
|
PlasmaExtras.ConditionalLoader {
|
||||||
|
id: recentChangesPage
|
||||||
|
when: mainTabGroup.currentTab === recentChangesPage
|
||||||
|
source: Qt.resolvedUrl("RecentChangesPage.qml")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,110 @@
|
||||||
|
import QtQuick 2.3
|
||||||
|
import QtQuick.Layouts 1.1
|
||||||
|
import QtQml.Models 2.2
|
||||||
|
import org.kde.plasma.plasmoid 2.0
|
||||||
|
import org.kde.plasma.components 2.0 as PlasmaComponents
|
||||||
|
import org.kde.plasma.core 2.0 as PlasmaCore
|
||||||
|
import org.kde.plasma.extras 2.0 as PlasmaExtras
|
||||||
|
|
||||||
|
Item {
|
||||||
|
property alias view: recentChangesView
|
||||||
|
anchors.fill: parent
|
||||||
|
objectName: "RecentChangesPage"
|
||||||
|
|
||||||
|
PlasmaExtras.ScrollArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
TopLevelView {
|
||||||
|
id: recentChangesView
|
||||||
|
model: plasmoid.nativeInterface.recentChangesModel
|
||||||
|
delegate: TopLevelItem {
|
||||||
|
ColumnLayout {
|
||||||
|
width: parent.width
|
||||||
|
spacing: 0
|
||||||
|
RowLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
PlasmaCore.IconItem {
|
||||||
|
Layout.preferredWidth: units.iconSizes.small
|
||||||
|
Layout.preferredHeight: units.iconSizes.small
|
||||||
|
Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
|
||||||
|
source: actionIcon
|
||||||
|
}
|
||||||
|
PlasmaComponents.Label {
|
||||||
|
Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
|
||||||
|
Layout.fillWidth: true
|
||||||
|
elide: Text.ElideRight
|
||||||
|
text: extendedAction
|
||||||
|
}
|
||||||
|
Item {
|
||||||
|
width: units.smallSpacing
|
||||||
|
}
|
||||||
|
PlasmaCore.IconItem {
|
||||||
|
Layout.preferredWidth: units.iconSizes.small
|
||||||
|
Layout.preferredHeight: units.iconSizes.small
|
||||||
|
Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
|
||||||
|
source: "change-date-symbolic"
|
||||||
|
}
|
||||||
|
PlasmaComponents.Label {
|
||||||
|
Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
|
||||||
|
elide: Text.ElideRight
|
||||||
|
text: eventTime
|
||||||
|
}
|
||||||
|
Item {
|
||||||
|
width: units.smallSpacing
|
||||||
|
}
|
||||||
|
PlasmaCore.IconItem {
|
||||||
|
Layout.preferredWidth: units.iconSizes.small
|
||||||
|
Layout.preferredHeight: units.iconSizes.small
|
||||||
|
Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
|
||||||
|
source: "network-server-symbolic"
|
||||||
|
}
|
||||||
|
PlasmaComponents.Label {
|
||||||
|
Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
|
||||||
|
elide: Text.ElideRight
|
||||||
|
text: modifiedBy
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RowLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
PlasmaCore.IconItem {
|
||||||
|
Layout.preferredWidth: units.iconSizes.small
|
||||||
|
Layout.preferredHeight: units.iconSizes.small
|
||||||
|
Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
|
||||||
|
source: itemType === "file" ? "view-refresh-symbolic" : "folder-sync"
|
||||||
|
}
|
||||||
|
PlasmaComponents.Label {
|
||||||
|
text: directoryId + ": "
|
||||||
|
font.weight: Font.DemiBold
|
||||||
|
}
|
||||||
|
PlasmaComponents.Label {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: path
|
||||||
|
elide: Text.ElideRight
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function copyPath() {
|
||||||
|
plasmoid.nativeInterface.copyToClipboard(path)
|
||||||
|
}
|
||||||
|
function copyDeviceId() {
|
||||||
|
plasmoid.nativeInterface.copyToClipboard(modifiedBy)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PlasmaComponents.Menu {
|
||||||
|
id: contextMenu
|
||||||
|
PlasmaComponents.MenuItem {
|
||||||
|
text: qsTr("Copy path")
|
||||||
|
icon: "edit-copy"
|
||||||
|
onClicked: recentChangesView.currentItem.copyPath()
|
||||||
|
}
|
||||||
|
PlasmaComponents.MenuItem {
|
||||||
|
text: qsTr("Copy device ID")
|
||||||
|
icon: "network-server-symbolic"
|
||||||
|
onClicked: recentChangesView.currentItem.copyDeviceId()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -46,6 +46,7 @@ set(REQUIRED_ICONS
|
||||||
dialog-cancel
|
dialog-cancel
|
||||||
dialog-ok
|
dialog-ok
|
||||||
dialog-ok-apply
|
dialog-ok-apply
|
||||||
|
document-open-recent-symbolic
|
||||||
edit-copy
|
edit-copy
|
||||||
edit-clear
|
edit-clear
|
||||||
edit-cut
|
edit-cut
|
||||||
|
|
|
@ -76,6 +76,7 @@ TrayWidget::TrayWidget(TrayMenu *parent)
|
||||||
, m_dirModel(m_connection)
|
, m_dirModel(m_connection)
|
||||||
, m_devModel(m_connection)
|
, m_devModel(m_connection)
|
||||||
, m_dlModel(m_connection)
|
, m_dlModel(m_connection)
|
||||||
|
, m_recentChangesModel(m_connection)
|
||||||
, m_selectedConnection(nullptr)
|
, m_selectedConnection(nullptr)
|
||||||
, m_startStopButtonTarget(StartStopButtonTarget::None)
|
, m_startStopButtonTarget(StartStopButtonTarget::None)
|
||||||
{
|
{
|
||||||
|
@ -87,6 +88,7 @@ TrayWidget::TrayWidget(TrayMenu *parent)
|
||||||
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);
|
m_ui->downloadsTreeView->setModel(&m_dlModel);
|
||||||
|
m_ui->recentChangesTreeView->setModel(&m_recentChangesModel);
|
||||||
|
|
||||||
// setup sync-all button
|
// setup sync-all button
|
||||||
m_cornerFrame = new QFrame(this);
|
m_cornerFrame = new QFrame(this);
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include "../../model/syncthingdevicemodel.h"
|
#include "../../model/syncthingdevicemodel.h"
|
||||||
#include "../../model/syncthingdirectorymodel.h"
|
#include "../../model/syncthingdirectorymodel.h"
|
||||||
#include "../../model/syncthingdownloadmodel.h"
|
#include "../../model/syncthingdownloadmodel.h"
|
||||||
|
#include "../../model/syncthingrecentchangesmodel.h"
|
||||||
|
|
||||||
#include "../../connector/syncthingconnection.h"
|
#include "../../connector/syncthingconnection.h"
|
||||||
#include "../../connector/syncthingnotifier.h"
|
#include "../../connector/syncthingnotifier.h"
|
||||||
|
@ -117,6 +118,7 @@ private:
|
||||||
Data::SyncthingDirectoryModel m_dirModel;
|
Data::SyncthingDirectoryModel m_dirModel;
|
||||||
Data::SyncthingDeviceModel m_devModel;
|
Data::SyncthingDeviceModel m_devModel;
|
||||||
Data::SyncthingDownloadModel m_dlModel;
|
Data::SyncthingDownloadModel m_dlModel;
|
||||||
|
Data::SyncthingRecentChangesModel m_recentChangesModel;
|
||||||
QMenu *m_connectionsMenu;
|
QMenu *m_connectionsMenu;
|
||||||
QActionGroup *m_connectionsActionGroup;
|
QActionGroup *m_connectionsActionGroup;
|
||||||
Data::SyncthingConnectionSettings *m_selectedConnection;
|
Data::SyncthingConnectionSettings *m_selectedConnection;
|
||||||
|
|
|
@ -469,6 +469,35 @@ For <i>all</i> notifications, checkout the log</string>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
|
<widget class="QWidget" name="recentChangesTab">
|
||||||
|
<attribute name="icon">
|
||||||
|
<iconset theme="document-open-recent-symbolic">
|
||||||
|
<normaloff>.</normaloff>.</iconset>
|
||||||
|
</attribute>
|
||||||
|
<attribute name="title">
|
||||||
|
<string>Recent changes</string>
|
||||||
|
</attribute>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||||
|
<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="QTreeView" name="recentChangesTreeView"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
|
Loading…
Reference in New Issue