Split fileitemactionplugin code into multiple files
This commit is contained in:
parent
882a2a5d35
commit
f901386478
|
@ -7,10 +7,18 @@ set(META_QT5_VERSION 5.8)
|
||||||
|
|
||||||
# add project files
|
# add project files
|
||||||
set(HEADER_FILES
|
set(HEADER_FILES
|
||||||
${META_PROJECT_NAME}.h
|
syncthingmenuaction.h
|
||||||
|
syncthinginfoaction.h
|
||||||
|
syncthingdiractions.h
|
||||||
|
syncthingfileitemactionstaticdata.h
|
||||||
|
syncthingfileitemaction.h
|
||||||
)
|
)
|
||||||
set(SRC_FILES
|
set(SRC_FILES
|
||||||
${META_PROJECT_NAME}.cpp
|
syncthingmenuaction.cpp
|
||||||
|
syncthinginfoaction.cpp
|
||||||
|
syncthingdiractions.cpp
|
||||||
|
syncthingfileitemactionstaticdata.cpp
|
||||||
|
syncthingfileitemaction.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set(TS_FILES
|
set(TS_FILES
|
||||||
|
|
|
@ -0,0 +1,79 @@
|
||||||
|
#include "./syncthingdiractions.h"
|
||||||
|
|
||||||
|
#include "../model/syncthingicons.h"
|
||||||
|
|
||||||
|
#include "../connector/syncthingdir.h"
|
||||||
|
#include "../connector/utils.h"
|
||||||
|
|
||||||
|
using namespace Data;
|
||||||
|
|
||||||
|
SyncthingDirActions::SyncthingDirActions(const SyncthingDir &dir, QObject *parent)
|
||||||
|
: QObject(parent)
|
||||||
|
, m_dirId(dir.id)
|
||||||
|
{
|
||||||
|
m_infoAction.setSeparator(true);
|
||||||
|
updateStatus(dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SyncthingDirActions::updateStatus(const std::vector<SyncthingDir> &dirs)
|
||||||
|
{
|
||||||
|
for (const SyncthingDir &dir : dirs) {
|
||||||
|
if (updateStatus(dir)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_statusAction.setText(tr("Status: not available anymore"));
|
||||||
|
m_statusAction.setIcon(statusIcons().disconnected);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SyncthingDirActions::updateStatus(const SyncthingDir &dir)
|
||||||
|
{
|
||||||
|
if (dir.id != m_dirId) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
m_infoAction.setText(tr("Directory info for %1").arg(dir.displayName()));
|
||||||
|
m_infoAction.setIcon(QIcon::fromTheme(QStringLiteral("dialog-information")));
|
||||||
|
m_statusAction.setText(tr("Status: ") + dir.statusString());
|
||||||
|
if (dir.paused && dir.status != SyncthingDirStatus::OutOfSync) {
|
||||||
|
m_statusAction.setIcon(statusIcons().pause);
|
||||||
|
} else if (dir.isUnshared()) {
|
||||||
|
m_statusAction.setIcon(statusIcons().disconnected);
|
||||||
|
} else {
|
||||||
|
switch (dir.status) {
|
||||||
|
case SyncthingDirStatus::Unknown:
|
||||||
|
m_statusAction.setIcon(statusIcons().disconnected);
|
||||||
|
break;
|
||||||
|
case SyncthingDirStatus::Idle:
|
||||||
|
m_statusAction.setIcon(statusIcons().idling);
|
||||||
|
break;
|
||||||
|
case SyncthingDirStatus::Scanning:
|
||||||
|
m_statusAction.setIcon(statusIcons().scanninig);
|
||||||
|
break;
|
||||||
|
case SyncthingDirStatus::Synchronizing:
|
||||||
|
m_statusAction.setIcon(statusIcons().sync);
|
||||||
|
break;
|
||||||
|
case SyncthingDirStatus::OutOfSync:
|
||||||
|
m_statusAction.setIcon(statusIcons().error);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_globalStatusAction.setText(tr("Global: ") + directoryStatusString(dir.globalStats));
|
||||||
|
m_localStatusAction.setText(tr("Local: ") + directoryStatusString(dir.localStats));
|
||||||
|
m_lastScanAction.setText(tr("Last scan time: ") + agoString(dir.lastScanTime));
|
||||||
|
m_lastScanAction.setIcon(QIcon::fromTheme(QStringLiteral("accept_time_event")));
|
||||||
|
m_rescanIntervalAction.setText(tr("Rescan interval: %1 seconds").arg(dir.rescanInterval));
|
||||||
|
if (!dir.pullErrorCount) {
|
||||||
|
m_errorsAction.setVisible(false);
|
||||||
|
} else {
|
||||||
|
m_errorsAction.setVisible(true);
|
||||||
|
m_errorsAction.setIcon(QIcon::fromTheme(QStringLiteral("dialog-error")));
|
||||||
|
m_errorsAction.setText(tr("%1 item(s) out-of-sync", nullptr, trQuandity(dir.pullErrorCount)).arg(dir.pullErrorCount));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<QAction *> &operator<<(QList<QAction *> &actions, SyncthingDirActions &dirActions)
|
||||||
|
{
|
||||||
|
return actions << &dirActions.m_infoAction << &dirActions.m_statusAction << &dirActions.m_globalStatusAction << &dirActions.m_localStatusAction
|
||||||
|
<< &dirActions.m_lastScanAction << &dirActions.m_rescanIntervalAction << &dirActions.m_errorsAction;
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
#ifndef SYNCTHINGDIRACTIONS_H
|
||||||
|
#define SYNCTHINGDIRACTIONS_H
|
||||||
|
|
||||||
|
#include "../connector/syncthingdir.h"
|
||||||
|
|
||||||
|
#include "./syncthinginfoaction.h"
|
||||||
|
|
||||||
|
class SyncthingDirActions : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
friend QList<QAction *> &operator<<(QList<QAction *> &, SyncthingDirActions &);
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit SyncthingDirActions(const Data::SyncthingDir &dir, QObject *parent = nullptr);
|
||||||
|
|
||||||
|
public Q_SLOTS:
|
||||||
|
void updateStatus(const std::vector<Data::SyncthingDir> &dirs);
|
||||||
|
bool updateStatus(const Data::SyncthingDir &dir);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString m_dirId;
|
||||||
|
QAction m_infoAction;
|
||||||
|
SyncthingInfoAction m_statusAction;
|
||||||
|
SyncthingInfoAction m_globalStatusAction;
|
||||||
|
SyncthingInfoAction m_localStatusAction;
|
||||||
|
SyncthingInfoAction m_lastScanAction;
|
||||||
|
SyncthingInfoAction m_rescanIntervalAction;
|
||||||
|
SyncthingInfoAction m_errorsAction;
|
||||||
|
};
|
||||||
|
|
||||||
|
QList<QAction *> &operator<<(QList<QAction *> &actions, SyncthingDirActions &dirActions);
|
||||||
|
|
||||||
|
#endif // SYNCTHINGDIRACTIONS_H
|
|
@ -1,38 +1,19 @@
|
||||||
#include "./syncthingfileitemaction.h"
|
#include "./syncthingfileitemaction.h"
|
||||||
|
#include "./syncthingdiractions.h"
|
||||||
|
#include "./syncthinginfoaction.h"
|
||||||
|
#include "./syncthingmenuaction.h"
|
||||||
|
|
||||||
#include "../model/syncthingicons.h"
|
#include "../model/syncthingicons.h"
|
||||||
|
|
||||||
#include "../connector/syncthingconfig.h"
|
|
||||||
#include "../connector/syncthingconnectionsettings.h"
|
|
||||||
#include "../connector/syncthingdir.h"
|
|
||||||
#include "../connector/utils.h"
|
|
||||||
|
|
||||||
#include <qtutilities/aboutdialog/aboutdialog.h>
|
|
||||||
#include <qtutilities/resources/resources.h>
|
|
||||||
|
|
||||||
#include <c++utilities/application/argumentparser.h>
|
|
||||||
|
|
||||||
#include <KFileItem>
|
#include <KFileItem>
|
||||||
#include <KPluginFactory>
|
#include <KPluginFactory>
|
||||||
#include <KPluginLoader>
|
#include <KPluginLoader>
|
||||||
|
|
||||||
#include <QAction>
|
#include <QAction>
|
||||||
#include <QDir>
|
|
||||||
#include <QEvent>
|
|
||||||
#include <QFileDialog>
|
|
||||||
#include <QHBoxLayout>
|
|
||||||
#include <QLabel>
|
|
||||||
#include <QMenu>
|
|
||||||
#include <QMessageBox>
|
|
||||||
#include <QSettings>
|
|
||||||
#include <QWidget>
|
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#include "resources/config.h"
|
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace Dialogs;
|
|
||||||
using namespace Data;
|
using namespace Data;
|
||||||
|
|
||||||
K_PLUGIN_FACTORY(SyncthingFileItemActionFactory, registerPlugin<SyncthingFileItemAction>();)
|
K_PLUGIN_FACTORY(SyncthingFileItemActionFactory, registerPlugin<SyncthingFileItemAction>();)
|
||||||
|
@ -56,295 +37,6 @@ SyncthingItem::SyncthingItem(const SyncthingDir *dir, const QString &path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SyncthingMenuAction::SyncthingMenuAction(const KFileItemListProperties &properties, const QList<QAction *> &actions, QWidget *parentWidget)
|
|
||||||
: QAction(parentWidget)
|
|
||||||
, m_properties(properties)
|
|
||||||
{
|
|
||||||
if (!actions.isEmpty()) {
|
|
||||||
auto *menu = new QMenu(parentWidget);
|
|
||||||
menu->addActions(actions);
|
|
||||||
setMenu(menu);
|
|
||||||
}
|
|
||||||
updateStatus(SyncthingFileItemAction::staticData().connection().status());
|
|
||||||
}
|
|
||||||
|
|
||||||
void SyncthingMenuAction::updateStatus(SyncthingStatus status)
|
|
||||||
{
|
|
||||||
if (status != SyncthingStatus::Disconnected && status != SyncthingStatus::Reconnecting && status != SyncthingStatus::BeingDestroyed) {
|
|
||||||
setText(tr("Syncthing"));
|
|
||||||
setIcon(statusIcons().scanninig);
|
|
||||||
if (!menu()) {
|
|
||||||
const QList<QAction *> actions = SyncthingFileItemAction::createActions(m_properties, parentWidget());
|
|
||||||
if (!actions.isEmpty()) {
|
|
||||||
auto *menu = new QMenu(parentWidget());
|
|
||||||
menu->addActions(actions);
|
|
||||||
setMenu(menu);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (status != SyncthingStatus::Reconnecting) {
|
|
||||||
SyncthingFileItemAction::staticData().connection().connect();
|
|
||||||
}
|
|
||||||
setText(tr("Syncthing - connecting"));
|
|
||||||
setIcon(statusIcons().disconnected);
|
|
||||||
if (QMenu *menu = this->menu()) {
|
|
||||||
setMenu(nullptr);
|
|
||||||
delete menu;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SyncthingInfoWidget::SyncthingInfoWidget(const SyncthingInfoAction *action, QWidget *parent)
|
|
||||||
: QWidget(parent)
|
|
||||||
, m_textLabel(new QLabel(parent))
|
|
||||||
, m_iconLabel(new QLabel(parent))
|
|
||||||
{
|
|
||||||
auto *const layout = new QHBoxLayout(parent);
|
|
||||||
layout->setMargin(4);
|
|
||||||
layout->setSpacing(5);
|
|
||||||
m_iconLabel->setFixedWidth(16);
|
|
||||||
m_iconLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum);
|
|
||||||
layout->addWidget(m_iconLabel);
|
|
||||||
layout->addWidget(m_textLabel);
|
|
||||||
setLayout(layout);
|
|
||||||
updateFromAction(action);
|
|
||||||
connect(action, &QAction::changed, this, &SyncthingInfoWidget::updateFromSender);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SyncthingInfoWidget::updateFromSender()
|
|
||||||
{
|
|
||||||
updateFromAction(qobject_cast<const SyncthingInfoAction *>(QObject::sender()));
|
|
||||||
}
|
|
||||||
|
|
||||||
void SyncthingInfoWidget::updateFromAction(const SyncthingInfoAction *action)
|
|
||||||
{
|
|
||||||
auto text(action->text());
|
|
||||||
m_textLabel->setText(text.startsWith(QChar('&')) ? text.mid(1) : std::move(text));
|
|
||||||
m_iconLabel->setPixmap(action->icon().pixmap(16));
|
|
||||||
setVisible(action->isVisible());
|
|
||||||
}
|
|
||||||
|
|
||||||
SyncthingInfoAction::SyncthingInfoAction(QObject *parent)
|
|
||||||
: QWidgetAction(parent)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
QWidget *SyncthingInfoAction::createWidget(QWidget *parent)
|
|
||||||
{
|
|
||||||
return new SyncthingInfoWidget(this, parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
SyncthingDirActions::SyncthingDirActions(const SyncthingDir &dir, QObject *parent)
|
|
||||||
: QObject(parent)
|
|
||||||
, m_dirId(dir.id)
|
|
||||||
{
|
|
||||||
m_infoAction.setSeparator(true);
|
|
||||||
updateStatus(dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SyncthingDirActions::updateStatus(const std::vector<SyncthingDir> &dirs)
|
|
||||||
{
|
|
||||||
for (const SyncthingDir &dir : dirs) {
|
|
||||||
if (updateStatus(dir)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m_statusAction.setText(tr("Status: not available anymore"));
|
|
||||||
m_statusAction.setIcon(statusIcons().disconnected);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SyncthingDirActions::updateStatus(const SyncthingDir &dir)
|
|
||||||
{
|
|
||||||
if (dir.id != m_dirId) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
m_infoAction.setText(tr("Directory info for %1").arg(dir.displayName()));
|
|
||||||
m_infoAction.setIcon(QIcon::fromTheme(QStringLiteral("dialog-information")));
|
|
||||||
m_statusAction.setText(tr("Status: ") + dir.statusString());
|
|
||||||
if (dir.paused && dir.status != SyncthingDirStatus::OutOfSync) {
|
|
||||||
m_statusAction.setIcon(statusIcons().pause);
|
|
||||||
} else if (dir.isUnshared()) {
|
|
||||||
m_statusAction.setIcon(statusIcons().disconnected);
|
|
||||||
} else {
|
|
||||||
switch (dir.status) {
|
|
||||||
case SyncthingDirStatus::Unknown:
|
|
||||||
m_statusAction.setIcon(statusIcons().disconnected);
|
|
||||||
break;
|
|
||||||
case SyncthingDirStatus::Idle:
|
|
||||||
m_statusAction.setIcon(statusIcons().idling);
|
|
||||||
break;
|
|
||||||
case SyncthingDirStatus::Scanning:
|
|
||||||
m_statusAction.setIcon(statusIcons().scanninig);
|
|
||||||
break;
|
|
||||||
case SyncthingDirStatus::Synchronizing:
|
|
||||||
m_statusAction.setIcon(statusIcons().sync);
|
|
||||||
break;
|
|
||||||
case SyncthingDirStatus::OutOfSync:
|
|
||||||
m_statusAction.setIcon(statusIcons().error);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m_globalStatusAction.setText(tr("Global: ") + directoryStatusString(dir.globalStats));
|
|
||||||
m_localStatusAction.setText(tr("Local: ") + directoryStatusString(dir.localStats));
|
|
||||||
m_lastScanAction.setText(tr("Last scan time: ") + agoString(dir.lastScanTime));
|
|
||||||
m_lastScanAction.setIcon(QIcon::fromTheme(QStringLiteral("accept_time_event")));
|
|
||||||
m_rescanIntervalAction.setText(tr("Rescan interval: %1 seconds").arg(dir.rescanInterval));
|
|
||||||
if (!dir.pullErrorCount) {
|
|
||||||
m_errorsAction.setVisible(false);
|
|
||||||
} else {
|
|
||||||
m_errorsAction.setVisible(true);
|
|
||||||
m_errorsAction.setIcon(QIcon::fromTheme(QStringLiteral("dialog-error")));
|
|
||||||
m_errorsAction.setText(tr("%1 item(s) out-of-sync", nullptr, trQuandity(dir.pullErrorCount)).arg(dir.pullErrorCount));
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
QList<QAction *> &operator<<(QList<QAction *> &actions, SyncthingDirActions &dirActions)
|
|
||||||
{
|
|
||||||
return actions << &dirActions.m_infoAction << &dirActions.m_statusAction << &dirActions.m_globalStatusAction << &dirActions.m_localStatusAction
|
|
||||||
<< &dirActions.m_lastScanAction << &dirActions.m_rescanIntervalAction << &dirActions.m_errorsAction;
|
|
||||||
}
|
|
||||||
|
|
||||||
SyncthingFileItemActionStaticData::SyncthingFileItemActionStaticData()
|
|
||||||
: m_initialized(false)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
SyncthingFileItemActionStaticData::~SyncthingFileItemActionStaticData()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void SyncthingFileItemActionStaticData::initialize()
|
|
||||||
{
|
|
||||||
if (m_initialized) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
LOAD_QT_TRANSLATIONS;
|
|
||||||
|
|
||||||
// load settings
|
|
||||||
const QSettings settingsFile(QSettings::IniFormat, QSettings::UserScope, QStringLiteral(PROJECT_NAME));
|
|
||||||
|
|
||||||
// determine path of Syncthing config file
|
|
||||||
m_configFilePath = [&] {
|
|
||||||
const QByteArray configPathFromEnv(qgetenv("KIO_SYNCTHING_CONFIG_PATH"));
|
|
||||||
if (!configPathFromEnv.isEmpty()) {
|
|
||||||
return QString::fromLocal8Bit(configPathFromEnv);
|
|
||||||
}
|
|
||||||
const QString configPathFromSettings = settingsFile.value(QStringLiteral("syncthingConfigPath")).toString();
|
|
||||||
if (!configPathFromSettings.isEmpty()) {
|
|
||||||
return configPathFromSettings;
|
|
||||||
}
|
|
||||||
return SyncthingConfig::locateConfigFile();
|
|
||||||
}();
|
|
||||||
applySyncthingConfiguration(m_configFilePath);
|
|
||||||
|
|
||||||
// prevent unnecessary API calls (for the purpose of the context menu)
|
|
||||||
m_connection.disablePolling();
|
|
||||||
|
|
||||||
// connect Signals & Slots for logging
|
|
||||||
connect(&m_connection, &SyncthingConnection::error, this, &SyncthingFileItemActionStaticData::logConnectionError);
|
|
||||||
if (qEnvironmentVariableIsSet("KIO_SYNCTHING_LOG_STATUS")) {
|
|
||||||
connect(&m_connection, &SyncthingConnection::statusChanged, this, &SyncthingFileItemActionStaticData::logConnectionStatus);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_initialized = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SyncthingFileItemActionStaticData::logConnectionStatus()
|
|
||||||
{
|
|
||||||
cerr << "Syncthing connection status changed to: " << m_connection.statusText().toLocal8Bit().data() << endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SyncthingFileItemActionStaticData::logConnectionError(const QString &errorMessage, SyncthingErrorCategory errorCategory)
|
|
||||||
{
|
|
||||||
switch (errorCategory) {
|
|
||||||
case SyncthingErrorCategory::Parsing:
|
|
||||||
case SyncthingErrorCategory::SpecificRequest:
|
|
||||||
QMessageBox::critical(nullptr, tr("Syncthing connection error"), errorMessage);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
cerr << "Syncthing connection error: " << errorMessage.toLocal8Bit().data() << endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SyncthingFileItemActionStaticData::rescanDir(const QString &dirId, const QString &relpath)
|
|
||||||
{
|
|
||||||
m_connection.rescan(dirId, relpath);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SyncthingFileItemActionStaticData::showAboutDialog()
|
|
||||||
{
|
|
||||||
auto *aboutDialog = new AboutDialog(nullptr, QStringLiteral(APP_NAME), QStringLiteral(APP_AUTHOR "\nSyncthing icons from Syncthing project"),
|
|
||||||
QStringLiteral(APP_VERSION), ApplicationUtilities::dependencyVersions2, QStringLiteral(APP_URL), QStringLiteral(APP_DESCRIPTION),
|
|
||||||
QImage(statusIcons().scanninig.pixmap(128).toImage()));
|
|
||||||
aboutDialog->setWindowTitle(tr("About") + QStringLiteral(" - " APP_NAME));
|
|
||||||
aboutDialog->setWindowIcon(QIcon::fromTheme(QStringLiteral("syncthingtray")));
|
|
||||||
aboutDialog->setAttribute(Qt::WA_DeleteOnClose);
|
|
||||||
aboutDialog->show();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SyncthingFileItemActionStaticData::selectSyncthingConfig()
|
|
||||||
{
|
|
||||||
const auto configFilePath = QFileDialog::getOpenFileName(nullptr, tr("Select Syncthing config file") + QStringLiteral(" - " APP_NAME));
|
|
||||||
if (!configFilePath.isEmpty() && applySyncthingConfiguration(configFilePath)) {
|
|
||||||
QSettings(QSettings::IniFormat, QSettings::UserScope, QStringLiteral(PROJECT_NAME))
|
|
||||||
.setValue(QStringLiteral("syncthingConfigPath"), m_configFilePath = configFilePath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SyncthingFileItemActionStaticData::applySyncthingConfiguration(const QString &syncthingConfigFilePath)
|
|
||||||
{
|
|
||||||
clearCurrentError();
|
|
||||||
|
|
||||||
// check for empty path
|
|
||||||
if (syncthingConfigFilePath.isEmpty()) {
|
|
||||||
setCurrentError(tr("Syncthing config file can not be automatically located"));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// load Syncthing config
|
|
||||||
SyncthingConfig config;
|
|
||||||
if (!config.restore(syncthingConfigFilePath)) {
|
|
||||||
auto errorMessage = tr("Unable to load Syncthing config from \"%1\"").arg(syncthingConfigFilePath);
|
|
||||||
if (!m_configFilePath.isEmpty() && m_configFilePath != syncthingConfigFilePath) {
|
|
||||||
errorMessage += QChar('\n');
|
|
||||||
errorMessage += tr("(still using config from \"%1\")").arg(m_configFilePath);
|
|
||||||
}
|
|
||||||
setCurrentError(errorMessage);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
cerr << "Syncthing config loaded from \"" << syncthingConfigFilePath.toLocal8Bit().data() << "\"" << endl;
|
|
||||||
|
|
||||||
// make connection settings
|
|
||||||
SyncthingConnectionSettings settings;
|
|
||||||
settings.syncthingUrl = config.syncthingUrl();
|
|
||||||
settings.apiKey.append(config.guiApiKey);
|
|
||||||
|
|
||||||
// establish connection
|
|
||||||
bool ok;
|
|
||||||
int reconnectInterval = qEnvironmentVariableIntValue("KIO_SYNCTHING_RECONNECT_INTERVAL", &ok);
|
|
||||||
if (!ok || reconnectInterval < 0) {
|
|
||||||
reconnectInterval = 10000;
|
|
||||||
}
|
|
||||||
m_connection.setAutoReconnectInterval(reconnectInterval);
|
|
||||||
m_connection.reconnect(settings);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SyncthingFileItemActionStaticData::setCurrentError(const QString ¤tError)
|
|
||||||
{
|
|
||||||
if (m_currentError == currentError) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const bool hadError = hasError();
|
|
||||||
m_currentError = currentError;
|
|
||||||
if (hadError != hasError()) {
|
|
||||||
emit hasErrorChanged(hasError());
|
|
||||||
}
|
|
||||||
emit currentErrorChanged(m_currentError);
|
|
||||||
}
|
|
||||||
|
|
||||||
SyncthingFileItemActionStaticData SyncthingFileItemAction::s_data;
|
SyncthingFileItemActionStaticData SyncthingFileItemAction::s_data;
|
||||||
|
|
||||||
SyncthingFileItemAction::SyncthingFileItemAction(QObject *parent, const QVariantList &)
|
SyncthingFileItemAction::SyncthingFileItemAction(QObject *parent, const QVariantList &)
|
||||||
|
|
|
@ -1,158 +1,12 @@
|
||||||
#ifndef SYNCTHINGFILEITEMACTION_H
|
#ifndef SYNCTHINGFILEITEMACTION_H
|
||||||
#define SYNCTHINGFILEITEMACTION_H
|
#define SYNCTHINGFILEITEMACTION_H
|
||||||
|
|
||||||
#include "../connector/syncthingconnection.h"
|
#include "./syncthingfileitemactionstaticdata.h"
|
||||||
|
|
||||||
#include <KAbstractFileItemActionPlugin>
|
#include <KAbstractFileItemActionPlugin>
|
||||||
#include <KFileItemListProperties>
|
|
||||||
|
|
||||||
#include <QAction>
|
|
||||||
#include <QWidget>
|
|
||||||
#include <QWidgetAction>
|
|
||||||
|
|
||||||
QT_FORWARD_DECLARE_CLASS(QLabel)
|
|
||||||
|
|
||||||
class KFileItemListProperties;
|
class KFileItemListProperties;
|
||||||
|
|
||||||
class SyncthingMenuAction : public QAction {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit SyncthingMenuAction(const KFileItemListProperties &properties = KFileItemListProperties(),
|
|
||||||
const QList<QAction *> &actions = QList<QAction *>(), QWidget *parentWidget = nullptr);
|
|
||||||
|
|
||||||
public Q_SLOTS:
|
|
||||||
void updateStatus(Data::SyncthingStatus status);
|
|
||||||
|
|
||||||
private:
|
|
||||||
KFileItemListProperties m_properties;
|
|
||||||
};
|
|
||||||
|
|
||||||
class SyncthingInfoAction;
|
|
||||||
|
|
||||||
class SyncthingInfoWidget : public QWidget {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit SyncthingInfoWidget(const SyncthingInfoAction *action, QWidget *parent = nullptr);
|
|
||||||
|
|
||||||
private Q_SLOTS:
|
|
||||||
void updateFromSender();
|
|
||||||
void updateFromAction(const SyncthingInfoAction *action);
|
|
||||||
|
|
||||||
private:
|
|
||||||
QLabel *const m_textLabel;
|
|
||||||
QLabel *const m_iconLabel;
|
|
||||||
};
|
|
||||||
|
|
||||||
class SyncthingInfoAction : public QWidgetAction {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit SyncthingInfoAction(QObject *parent = nullptr);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
QWidget *createWidget(QWidget *parent) override;
|
|
||||||
};
|
|
||||||
|
|
||||||
class SyncthingDirActions : public QObject {
|
|
||||||
Q_OBJECT
|
|
||||||
friend QList<QAction *> &operator<<(QList<QAction *> &, SyncthingDirActions &);
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit SyncthingDirActions(const Data::SyncthingDir &dir, QObject *parent = nullptr);
|
|
||||||
|
|
||||||
public Q_SLOTS:
|
|
||||||
void updateStatus(const std::vector<Data::SyncthingDir> &dirs);
|
|
||||||
bool updateStatus(const Data::SyncthingDir &dir);
|
|
||||||
|
|
||||||
private:
|
|
||||||
QString m_dirId;
|
|
||||||
QAction m_infoAction;
|
|
||||||
SyncthingInfoAction m_statusAction;
|
|
||||||
SyncthingInfoAction m_globalStatusAction;
|
|
||||||
SyncthingInfoAction m_localStatusAction;
|
|
||||||
SyncthingInfoAction m_lastScanAction;
|
|
||||||
SyncthingInfoAction m_rescanIntervalAction;
|
|
||||||
SyncthingInfoAction m_errorsAction;
|
|
||||||
};
|
|
||||||
|
|
||||||
QList<QAction *> &operator<<(QList<QAction *> &actions, SyncthingDirActions &dirActions);
|
|
||||||
|
|
||||||
class SyncthingFileItemActionStaticData : public QObject {
|
|
||||||
Q_OBJECT
|
|
||||||
Q_PROPERTY(QString configPath READ configPath)
|
|
||||||
Q_PROPERTY(QString currentError READ currentError WRITE setCurrentError NOTIFY currentErrorChanged RESET clearCurrentError)
|
|
||||||
Q_PROPERTY(bool hasError READ hasError NOTIFY hasErrorChanged)
|
|
||||||
Q_PROPERTY(bool initialized READ isInitialized)
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit SyncthingFileItemActionStaticData();
|
|
||||||
~SyncthingFileItemActionStaticData();
|
|
||||||
Data::SyncthingConnection &connection();
|
|
||||||
const Data::SyncthingConnection &connection() const;
|
|
||||||
const QString &configPath() const;
|
|
||||||
const QString ¤tError() const;
|
|
||||||
bool hasError() const;
|
|
||||||
bool isInitialized() const;
|
|
||||||
|
|
||||||
public Q_SLOTS:
|
|
||||||
void initialize();
|
|
||||||
bool applySyncthingConfiguration(const QString &syncthingConfigFilePath);
|
|
||||||
void logConnectionStatus();
|
|
||||||
void logConnectionError(const QString &errorMessage, Data::SyncthingErrorCategory errorCategory);
|
|
||||||
void rescanDir(const QString &dirId, const QString &relpath = QString());
|
|
||||||
static void showAboutDialog();
|
|
||||||
void selectSyncthingConfig();
|
|
||||||
void setCurrentError(const QString ¤tError);
|
|
||||||
void clearCurrentError();
|
|
||||||
|
|
||||||
Q_SIGNALS:
|
|
||||||
void currentErrorChanged(const QString &error);
|
|
||||||
void hasErrorChanged(bool hasError);
|
|
||||||
|
|
||||||
private:
|
|
||||||
Data::SyncthingConnection m_connection;
|
|
||||||
QString m_configFilePath;
|
|
||||||
QString m_currentError;
|
|
||||||
bool m_initialized;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline Data::SyncthingConnection &SyncthingFileItemActionStaticData::connection()
|
|
||||||
{
|
|
||||||
return m_connection;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const Data::SyncthingConnection &SyncthingFileItemActionStaticData::connection() const
|
|
||||||
{
|
|
||||||
return m_connection;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const QString &SyncthingFileItemActionStaticData::configPath() const
|
|
||||||
{
|
|
||||||
return m_configFilePath;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const QString &SyncthingFileItemActionStaticData::currentError() const
|
|
||||||
{
|
|
||||||
return m_currentError;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool SyncthingFileItemActionStaticData::hasError() const
|
|
||||||
{
|
|
||||||
return !currentError().isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool SyncthingFileItemActionStaticData::isInitialized() const
|
|
||||||
{
|
|
||||||
return m_initialized;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void SyncthingFileItemActionStaticData::clearCurrentError()
|
|
||||||
{
|
|
||||||
m_currentError.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
class SyncthingFileItemAction : public KAbstractFileItemActionPlugin {
|
class SyncthingFileItemAction : public KAbstractFileItemActionPlugin {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,160 @@
|
||||||
|
#include "./syncthingfileitemactionstaticdata.h"
|
||||||
|
|
||||||
|
#include "../model/syncthingicons.h"
|
||||||
|
|
||||||
|
#include "../connector/syncthingconfig.h"
|
||||||
|
#include "../connector/syncthingconnection.h"
|
||||||
|
#include "../connector/syncthingconnectionsettings.h"
|
||||||
|
|
||||||
|
#include <c++utilities/application/argumentparser.h>
|
||||||
|
|
||||||
|
#include <qtutilities/aboutdialog/aboutdialog.h>
|
||||||
|
#include <qtutilities/resources/resources.h>
|
||||||
|
|
||||||
|
#include <QFileDialog>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <QSettings>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "resources/config.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace Dialogs;
|
||||||
|
using namespace Data;
|
||||||
|
|
||||||
|
SyncthingFileItemActionStaticData::SyncthingFileItemActionStaticData()
|
||||||
|
: m_initialized(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void SyncthingFileItemActionStaticData::initialize()
|
||||||
|
{
|
||||||
|
if (m_initialized) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOAD_QT_TRANSLATIONS;
|
||||||
|
|
||||||
|
// load settings
|
||||||
|
const QSettings settingsFile(QSettings::IniFormat, QSettings::UserScope, QStringLiteral(PROJECT_NAME));
|
||||||
|
|
||||||
|
// determine path of Syncthing config file
|
||||||
|
m_configFilePath = [&] {
|
||||||
|
const QByteArray configPathFromEnv(qgetenv("KIO_SYNCTHING_CONFIG_PATH"));
|
||||||
|
if (!configPathFromEnv.isEmpty()) {
|
||||||
|
return QString::fromLocal8Bit(configPathFromEnv);
|
||||||
|
}
|
||||||
|
const QString configPathFromSettings = settingsFile.value(QStringLiteral("syncthingConfigPath")).toString();
|
||||||
|
if (!configPathFromSettings.isEmpty()) {
|
||||||
|
return configPathFromSettings;
|
||||||
|
}
|
||||||
|
return SyncthingConfig::locateConfigFile();
|
||||||
|
}();
|
||||||
|
applySyncthingConfiguration(m_configFilePath);
|
||||||
|
|
||||||
|
// prevent unnecessary API calls (for the purpose of the context menu)
|
||||||
|
m_connection.disablePolling();
|
||||||
|
|
||||||
|
// connect Signals & Slots for logging
|
||||||
|
connect(&m_connection, &SyncthingConnection::error, this, &SyncthingFileItemActionStaticData::logConnectionError);
|
||||||
|
if (qEnvironmentVariableIsSet("KIO_SYNCTHING_LOG_STATUS")) {
|
||||||
|
connect(&m_connection, &SyncthingConnection::statusChanged, this, &SyncthingFileItemActionStaticData::logConnectionStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SyncthingFileItemActionStaticData::logConnectionStatus()
|
||||||
|
{
|
||||||
|
cerr << "Syncthing connection status changed to: " << m_connection.statusText().toLocal8Bit().data() << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SyncthingFileItemActionStaticData::logConnectionError(const QString &errorMessage, SyncthingErrorCategory errorCategory)
|
||||||
|
{
|
||||||
|
switch (errorCategory) {
|
||||||
|
case SyncthingErrorCategory::Parsing:
|
||||||
|
case SyncthingErrorCategory::SpecificRequest:
|
||||||
|
QMessageBox::critical(nullptr, tr("Syncthing connection error"), errorMessage);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
cerr << "Syncthing connection error: " << errorMessage.toLocal8Bit().data() << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SyncthingFileItemActionStaticData::rescanDir(const QString &dirId, const QString &relpath)
|
||||||
|
{
|
||||||
|
m_connection.rescan(dirId, relpath);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SyncthingFileItemActionStaticData::showAboutDialog()
|
||||||
|
{
|
||||||
|
auto *aboutDialog = new AboutDialog(nullptr, QStringLiteral(APP_NAME), QStringLiteral(APP_AUTHOR "\nSyncthing icons from Syncthing project"),
|
||||||
|
QStringLiteral(APP_VERSION), ApplicationUtilities::dependencyVersions2, QStringLiteral(APP_URL), QStringLiteral(APP_DESCRIPTION),
|
||||||
|
QImage(statusIcons().scanninig.pixmap(128).toImage()));
|
||||||
|
aboutDialog->setWindowTitle(tr("About") + QStringLiteral(" - " APP_NAME));
|
||||||
|
aboutDialog->setWindowIcon(QIcon::fromTheme(QStringLiteral("syncthingtray")));
|
||||||
|
aboutDialog->setAttribute(Qt::WA_DeleteOnClose);
|
||||||
|
aboutDialog->show();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SyncthingFileItemActionStaticData::selectSyncthingConfig()
|
||||||
|
{
|
||||||
|
const auto configFilePath = QFileDialog::getOpenFileName(nullptr, tr("Select Syncthing config file") + QStringLiteral(" - " APP_NAME));
|
||||||
|
if (!configFilePath.isEmpty() && applySyncthingConfiguration(configFilePath)) {
|
||||||
|
QSettings(QSettings::IniFormat, QSettings::UserScope, QStringLiteral(PROJECT_NAME))
|
||||||
|
.setValue(QStringLiteral("syncthingConfigPath"), m_configFilePath = configFilePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SyncthingFileItemActionStaticData::applySyncthingConfiguration(const QString &syncthingConfigFilePath)
|
||||||
|
{
|
||||||
|
clearCurrentError();
|
||||||
|
|
||||||
|
// check for empty path
|
||||||
|
if (syncthingConfigFilePath.isEmpty()) {
|
||||||
|
setCurrentError(tr("Syncthing config file can not be automatically located"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// load Syncthing config
|
||||||
|
SyncthingConfig config;
|
||||||
|
if (!config.restore(syncthingConfigFilePath)) {
|
||||||
|
auto errorMessage = tr("Unable to load Syncthing config from \"%1\"").arg(syncthingConfigFilePath);
|
||||||
|
if (!m_configFilePath.isEmpty() && m_configFilePath != syncthingConfigFilePath) {
|
||||||
|
errorMessage += QChar('\n');
|
||||||
|
errorMessage += tr("(still using config from \"%1\")").arg(m_configFilePath);
|
||||||
|
}
|
||||||
|
setCurrentError(errorMessage);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
cerr << "Syncthing config loaded from \"" << syncthingConfigFilePath.toLocal8Bit().data() << "\"" << endl;
|
||||||
|
|
||||||
|
// make connection settings
|
||||||
|
SyncthingConnectionSettings settings;
|
||||||
|
settings.syncthingUrl = config.syncthingUrl();
|
||||||
|
settings.apiKey.append(config.guiApiKey);
|
||||||
|
|
||||||
|
// establish connection
|
||||||
|
bool ok;
|
||||||
|
int reconnectInterval = qEnvironmentVariableIntValue("KIO_SYNCTHING_RECONNECT_INTERVAL", &ok);
|
||||||
|
if (!ok || reconnectInterval < 0) {
|
||||||
|
reconnectInterval = 10000;
|
||||||
|
}
|
||||||
|
m_connection.setAutoReconnectInterval(reconnectInterval);
|
||||||
|
m_connection.reconnect(settings);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SyncthingFileItemActionStaticData::setCurrentError(const QString ¤tError)
|
||||||
|
{
|
||||||
|
if (m_currentError == currentError) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const bool hadError = hasError();
|
||||||
|
m_currentError = currentError;
|
||||||
|
if (hadError != hasError()) {
|
||||||
|
emit hasErrorChanged(hasError());
|
||||||
|
}
|
||||||
|
emit currentErrorChanged(m_currentError);
|
||||||
|
}
|
|
@ -0,0 +1,79 @@
|
||||||
|
#ifndef SYNCTHINGFILEITEMACTIONSTATICDATA_H
|
||||||
|
#define SYNCTHINGFILEITEMACTIONSTATICDATA_H
|
||||||
|
|
||||||
|
#include "../connector/syncthingconnection.h"
|
||||||
|
|
||||||
|
class SyncthingFileItemActionStaticData : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(QString configPath READ configPath)
|
||||||
|
Q_PROPERTY(QString currentError READ currentError WRITE setCurrentError NOTIFY currentErrorChanged RESET clearCurrentError)
|
||||||
|
Q_PROPERTY(bool hasError READ hasError NOTIFY hasErrorChanged)
|
||||||
|
Q_PROPERTY(bool initialized READ isInitialized)
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit SyncthingFileItemActionStaticData();
|
||||||
|
Data::SyncthingConnection &connection();
|
||||||
|
const Data::SyncthingConnection &connection() const;
|
||||||
|
const QString &configPath() const;
|
||||||
|
const QString ¤tError() const;
|
||||||
|
bool hasError() const;
|
||||||
|
bool isInitialized() const;
|
||||||
|
|
||||||
|
public Q_SLOTS:
|
||||||
|
void initialize();
|
||||||
|
bool applySyncthingConfiguration(const QString &syncthingConfigFilePath);
|
||||||
|
void logConnectionStatus();
|
||||||
|
void logConnectionError(const QString &errorMessage, Data::SyncthingErrorCategory errorCategory);
|
||||||
|
void rescanDir(const QString &dirId, const QString &relpath = QString());
|
||||||
|
static void showAboutDialog();
|
||||||
|
void selectSyncthingConfig();
|
||||||
|
void setCurrentError(const QString ¤tError);
|
||||||
|
void clearCurrentError();
|
||||||
|
|
||||||
|
Q_SIGNALS:
|
||||||
|
void currentErrorChanged(const QString &error);
|
||||||
|
void hasErrorChanged(bool hasError);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Data::SyncthingConnection m_connection;
|
||||||
|
QString m_configFilePath;
|
||||||
|
QString m_currentError;
|
||||||
|
bool m_initialized;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline Data::SyncthingConnection &SyncthingFileItemActionStaticData::connection()
|
||||||
|
{
|
||||||
|
return m_connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const Data::SyncthingConnection &SyncthingFileItemActionStaticData::connection() const
|
||||||
|
{
|
||||||
|
return m_connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const QString &SyncthingFileItemActionStaticData::configPath() const
|
||||||
|
{
|
||||||
|
return m_configFilePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const QString &SyncthingFileItemActionStaticData::currentError() const
|
||||||
|
{
|
||||||
|
return m_currentError;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool SyncthingFileItemActionStaticData::hasError() const
|
||||||
|
{
|
||||||
|
return !currentError().isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool SyncthingFileItemActionStaticData::isInitialized() const
|
||||||
|
{
|
||||||
|
return m_initialized;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SyncthingFileItemActionStaticData::clearCurrentError()
|
||||||
|
{
|
||||||
|
m_currentError.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // SYNCTHINGFILEITEMACTIONSTATICDATA_H
|
|
@ -0,0 +1,45 @@
|
||||||
|
#include "./syncthinginfoaction.h"
|
||||||
|
|
||||||
|
#include <QAction>
|
||||||
|
#include <QHBoxLayout>
|
||||||
|
#include <QLabel>
|
||||||
|
|
||||||
|
SyncthingInfoWidget::SyncthingInfoWidget(const SyncthingInfoAction *action, QWidget *parent)
|
||||||
|
: QWidget(parent)
|
||||||
|
, m_textLabel(new QLabel(parent))
|
||||||
|
, m_iconLabel(new QLabel(parent))
|
||||||
|
{
|
||||||
|
auto *const layout = new QHBoxLayout(parent);
|
||||||
|
layout->setMargin(4);
|
||||||
|
layout->setSpacing(5);
|
||||||
|
m_iconLabel->setFixedWidth(16);
|
||||||
|
m_iconLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum);
|
||||||
|
layout->addWidget(m_iconLabel);
|
||||||
|
layout->addWidget(m_textLabel);
|
||||||
|
setLayout(layout);
|
||||||
|
updateFromAction(action);
|
||||||
|
connect(action, &QAction::changed, this, &SyncthingInfoWidget::updateFromSender);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SyncthingInfoWidget::updateFromSender()
|
||||||
|
{
|
||||||
|
updateFromAction(qobject_cast<const SyncthingInfoAction *>(QObject::sender()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SyncthingInfoWidget::updateFromAction(const SyncthingInfoAction *action)
|
||||||
|
{
|
||||||
|
auto text(action->text());
|
||||||
|
m_textLabel->setText(text.startsWith(QChar('&')) ? text.mid(1) : std::move(text));
|
||||||
|
m_iconLabel->setPixmap(action->icon().pixmap(16));
|
||||||
|
setVisible(action->isVisible());
|
||||||
|
}
|
||||||
|
|
||||||
|
SyncthingInfoAction::SyncthingInfoAction(QObject *parent)
|
||||||
|
: QWidgetAction(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QWidget *SyncthingInfoAction::createWidget(QWidget *parent)
|
||||||
|
{
|
||||||
|
return new SyncthingInfoWidget(this, parent);
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
#ifndef SYNCTHINGINFOACTION_H
|
||||||
|
#define SYNCTHINGINFOACTION_H
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
#include <QWidgetAction>
|
||||||
|
|
||||||
|
QT_FORWARD_DECLARE_CLASS(QLabel)
|
||||||
|
|
||||||
|
class SyncthingInfoAction;
|
||||||
|
|
||||||
|
class SyncthingInfoWidget : public QWidget {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit SyncthingInfoWidget(const SyncthingInfoAction *action, QWidget *parent = nullptr);
|
||||||
|
|
||||||
|
private Q_SLOTS:
|
||||||
|
void updateFromSender();
|
||||||
|
void updateFromAction(const SyncthingInfoAction *action);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QLabel *const m_textLabel;
|
||||||
|
QLabel *const m_iconLabel;
|
||||||
|
};
|
||||||
|
|
||||||
|
class SyncthingInfoAction : public QWidgetAction {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit SyncthingInfoAction(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
QWidget *createWidget(QWidget *parent) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SYNCTHINGINFOACTION_H
|
|
@ -0,0 +1,49 @@
|
||||||
|
#include "./syncthingmenuaction.h"
|
||||||
|
#include "./syncthingfileitemaction.h"
|
||||||
|
|
||||||
|
#include "../model/syncthingicons.h"
|
||||||
|
|
||||||
|
#include "../connector/syncthingconnection.h"
|
||||||
|
|
||||||
|
#include <QAction>
|
||||||
|
#include <QMenu>
|
||||||
|
|
||||||
|
using namespace Data;
|
||||||
|
|
||||||
|
SyncthingMenuAction::SyncthingMenuAction(const KFileItemListProperties &properties, const QList<QAction *> &actions, QWidget *parentWidget)
|
||||||
|
: QAction(parentWidget)
|
||||||
|
, m_properties(properties)
|
||||||
|
{
|
||||||
|
if (!actions.isEmpty()) {
|
||||||
|
auto *menu = new QMenu(parentWidget);
|
||||||
|
menu->addActions(actions);
|
||||||
|
setMenu(menu);
|
||||||
|
}
|
||||||
|
updateStatus(SyncthingFileItemAction::staticData().connection().status());
|
||||||
|
}
|
||||||
|
|
||||||
|
void SyncthingMenuAction::updateStatus(SyncthingStatus status)
|
||||||
|
{
|
||||||
|
if (status != SyncthingStatus::Disconnected && status != SyncthingStatus::Reconnecting && status != SyncthingStatus::BeingDestroyed) {
|
||||||
|
setText(tr("Syncthing"));
|
||||||
|
setIcon(statusIcons().scanninig);
|
||||||
|
if (!menu()) {
|
||||||
|
const QList<QAction *> actions = SyncthingFileItemAction::createActions(m_properties, parentWidget());
|
||||||
|
if (!actions.isEmpty()) {
|
||||||
|
auto *menu = new QMenu(parentWidget());
|
||||||
|
menu->addActions(actions);
|
||||||
|
setMenu(menu);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (status != SyncthingStatus::Reconnecting) {
|
||||||
|
SyncthingFileItemAction::staticData().connection().connect();
|
||||||
|
}
|
||||||
|
setText(tr("Syncthing - connecting"));
|
||||||
|
setIcon(statusIcons().disconnected);
|
||||||
|
if (QMenu *menu = this->menu()) {
|
||||||
|
setMenu(nullptr);
|
||||||
|
delete menu;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
#ifndef SYNCTHINGMENUACTION_H
|
||||||
|
#define SYNCTHINGMENUACTION_H
|
||||||
|
|
||||||
|
#include <KFileItemListProperties>
|
||||||
|
|
||||||
|
#include <QAction>
|
||||||
|
|
||||||
|
namespace Data {
|
||||||
|
enum class SyncthingStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
class SyncthingMenuAction : public QAction {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit SyncthingMenuAction(const KFileItemListProperties &properties = KFileItemListProperties(),
|
||||||
|
const QList<QAction *> &actions = QList<QAction *>(), QWidget *parentWidget = nullptr);
|
||||||
|
|
||||||
|
public Q_SLOTS:
|
||||||
|
void updateStatus(Data::SyncthingStatus status);
|
||||||
|
|
||||||
|
private:
|
||||||
|
KFileItemListProperties m_properties;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SYNCTHINGMENUACTION_H
|
Loading…
Reference in New Issue