diff --git a/tray/gui/trayicon.cpp b/tray/gui/trayicon.cpp index 182ce37..b61c7cc 100644 --- a/tray/gui/trayicon.cpp +++ b/tray/gui/trayicon.cpp @@ -105,8 +105,8 @@ TrayIcon::TrayIcon(const QString &connectionConfig, QObject *parent) #endif // apply settings, this also establishes the connection to Syncthing (according to settings) - // note: It is important to apply settings only after all Signals & Slots have been connected (eg. to handle SyncthingConnection::error()). - // note: This weirdly call updateStatusIconAndText(). So there is not need to call it again within this constructor. + // note: It is important to apply settings only after all Signals & Slots have been connected (e.g. to handle SyncthingConnection::error()). + // note: This weirdly calls updateStatusIconAndText(). So there is not need to call it again within this constructor. trayMenu().widget().applySettings(connectionConfig); } diff --git a/widgets/misc/syncthinglauncher.cpp b/widgets/misc/syncthinglauncher.cpp index d168aea..48aa30e 100644 --- a/widgets/misc/syncthinglauncher.cpp +++ b/widgets/misc/syncthinglauncher.cpp @@ -30,6 +30,7 @@ SyncthingLauncher *SyncthingLauncher::s_mainInstance = nullptr; SyncthingLauncher::SyncthingLauncher(QObject *parent) : QObject(parent) , m_manuallyStopped(true) + , m_emittingOutput(false) { connect(&m_process, &SyncthingProcess::readyRead, this, &SyncthingLauncher::handleProcessReadyRead); connect(&m_process, static_cast(&SyncthingProcess::finished), this, @@ -39,6 +40,19 @@ SyncthingLauncher::SyncthingLauncher(QObject *parent) connect(&m_process, &SyncthingProcess::confirmKill, this, &SyncthingLauncher::confirmKill); } +/*! + * \brief Sets whether the output/log should be emitted via outputAvailable() signal. + */ +void SyncthingLauncher::setEmittingOutput(bool emittingOutput) +{ + if (m_emittingOutput == emittingOutput || !(m_emittingOutput = emittingOutput) || m_outputBuffer.isEmpty()) { + return; + } + QByteArray data; + m_outputBuffer.swap(data); + emit outputAvailable(move(data)); +} + /*! * \brief Returns whether the built-in Syncthing library is available. */ @@ -156,7 +170,7 @@ void SyncthingLauncher::tearDownLibSyncthing() void SyncthingLauncher::handleProcessReadyRead() { - emit outputAvailable(m_process.readAll()); + handleOutputAvailable(m_process.readAll()); } void SyncthingLauncher::handleProcessStateChanged(QProcess::ProcessState newState) @@ -200,7 +214,7 @@ void SyncthingLauncher::handleLoggingCallback(LibSyncthing::LogLevel level, cons messageData.append(message, static_cast(messageSize)); messageData.append('\n'); - emit outputAvailable(move(messageData)); + handleOutputAvailable(move(messageData)); #else CPP_UTILITIES_UNUSED(level) CPP_UTILITIES_UNUSED(message) @@ -208,6 +222,15 @@ void SyncthingLauncher::handleLoggingCallback(LibSyncthing::LogLevel level, cons #endif } +void SyncthingLauncher::handleOutputAvailable(QByteArray &&data) +{ + if (isEmittingOutput()) { + emit outputAvailable(data); + } else { + m_outputBuffer += data; + } +} + void SyncthingLauncher::runLibSyncthing(const LibSyncthing::RuntimeOptions &runtimeOptions) { #ifdef SYNCTHINGWIDGETS_USE_LIBSYNCTHING @@ -218,7 +241,7 @@ void SyncthingLauncher::runLibSyncthing(const LibSyncthing::RuntimeOptions &runt emit runningChanged(false); #else CPP_UTILITIES_UNUSED(runtimeOptions) - emit outputAvailable("libsyncthing support not enabled"); + handleOutputAvailable(QByteArray("libsyncthing support not enabled")); emit exited(-1, QProcess::CrashExit); #endif } diff --git a/widgets/misc/syncthinglauncher.h b/widgets/misc/syncthinglauncher.h index d7362a2..d9425d3 100644 --- a/widgets/misc/syncthinglauncher.h +++ b/widgets/misc/syncthinglauncher.h @@ -6,6 +6,7 @@ #include "../../connector/syncthingprocess.h" #include "../../libsyncthing/interface.h" +#include #include namespace LibSyncthing { @@ -23,6 +24,7 @@ class SYNCTHINGWIDGETS_EXPORT SyncthingLauncher : public QObject { Q_PROPERTY(bool running READ isRunning NOTIFY runningChanged) Q_PROPERTY(CppUtilities::DateTime activeSince READ activeSince) Q_PROPERTY(bool manuallyStopped READ isManuallyStopped) + Q_PROPERTY(bool emittingOutput READ isEmittingOutput WRITE setEmittingOutput) public: explicit SyncthingLauncher(QObject *parent = nullptr); @@ -31,6 +33,8 @@ public: CppUtilities::DateTime activeSince() const; bool isActiveFor(unsigned int atLeastSeconds) const; bool isManuallyStopped() const; + bool isEmittingOutput() const; + void setEmittingOutput(bool emittingOutput); static bool isLibSyncthingAvailable(); static SyncthingLauncher *mainInstance(); static void setMainInstance(SyncthingLauncher *mainInstance); @@ -60,10 +64,14 @@ private Q_SLOTS: void stopLibSyncthing(); private: + void handleOutputAvailable(QByteArray &&data); + SyncthingProcess m_process; QFuture m_future; + QByteArray m_outputBuffer; CppUtilities::DateTime m_futureStarted; bool m_manuallyStopped; + bool m_emittingOutput; bool m_useLibSyncthing; static SyncthingLauncher *s_mainInstance; }; @@ -100,6 +108,12 @@ inline bool SyncthingLauncher::isManuallyStopped() const return m_manuallyStopped; } +/// \brief Returns whether the output/log should be emitted via outputAvailable() signal. +inline bool SyncthingLauncher::isEmittingOutput() const +{ + return m_emittingOutput; +} + /// \brief Returns the SyncthingLauncher instance previously assigned via SyncthingLauncher::setMainInstance(). inline SyncthingLauncher *SyncthingLauncher::mainInstance() { diff --git a/widgets/settings/settingsdialog.cpp b/widgets/settings/settingsdialog.cpp index d887962..dce41a6 100644 --- a/widgets/settings/settingsdialog.cpp +++ b/widgets/settings/settingsdialog.cpp @@ -891,6 +891,7 @@ QWidget *LauncherOptionPage::setupWidget() connect(m_launcher, &SyncthingLauncher::outputAvailable, this, &LauncherOptionPage::handleSyncthingOutputAvailable, Qt::QueuedConnection); connect(m_launcher, &SyncthingLauncher::exited, this, &LauncherOptionPage::handleSyncthingExited, Qt::QueuedConnection); connect(m_launcher, &SyncthingLauncher::errorOccurred, this, &LauncherOptionPage::handleSyncthingError, Qt::QueuedConnection); + m_launcher->setEmittingOutput(true); } connect(ui()->launchNowPushButton, &QPushButton::clicked, this, &LauncherOptionPage::launch); connect(ui()->stopPushButton, &QPushButton::clicked, this, &LauncherOptionPage::stop);