diff --git a/connector/syncthingconnection.cpp b/connector/syncthingconnection.cpp index 963587b..1633d9d 100644 --- a/connector/syncthingconnection.cpp +++ b/connector/syncthingconnection.cpp @@ -794,19 +794,26 @@ void SyncthingConnection::setStatus(SyncthingStatus status) // reset reconnect tries m_autoReconnectTries = 0; - // check whether at least one directory is scanning or synchronizing + // check whether at least one directory is scanning, preparing to synchronize or synchronizing + // note: We don't distinguish between "preparing to sync" and "synchronizing" for computing the overall + // status at the moment. bool scanning = false; bool synchronizing = false; for (const SyncthingDir &dir : m_dirs) { switch (dir.status) { + case SyncthingDirStatus::PreparingToSync: case SyncthingDirStatus::Synchronizing: synchronizing = true; break; + case SyncthingDirStatus::WaitingToScan: case SyncthingDirStatus::Scanning: scanning = true; break; default:; } + if (synchronizing) { + break; // skip remaining dirs, "synchronizing" overrides "scanning" anyways + } } if (synchronizing) { diff --git a/connector/syncthingconnection_requests.cpp b/connector/syncthingconnection_requests.cpp index 2628c4c..fd20ebe 100644 --- a/connector/syncthingconnection_requests.cpp +++ b/connector/syncthingconnection_requests.cpp @@ -1962,7 +1962,7 @@ void SyncthingConnection::readLocalFolderCompletion(DateTime eventTime, const QJ dirInfo.completionPercentage = globalStats.bytes ? static_cast((globalStats.bytes - neededStats.bytes) * 100 / globalStats.bytes) : 100; emit dirStatusChanged(dirInfo, index); if (neededStats.isNull() && previouslyUpdated && (neededStats != previouslyNeeded || globalStats != previouslyGlobal) - && dirInfo.status != SyncthingDirStatus::Scanning) { + && dirInfo.status != SyncthingDirStatus::WaitingToScan && dirInfo.status != SyncthingDirStatus::Scanning) { emit dirCompleted(eventTime, dirInfo, index); } } diff --git a/connector/syncthingdev.h b/connector/syncthingdev.h index 95ed928..0cb5837 100644 --- a/connector/syncthingdev.h +++ b/connector/syncthingdev.h @@ -11,6 +11,9 @@ namespace Data { +/// \brief The SyncthingDevStatus enum represents a Syncthing device status. +/// \remarks The device status is not directly provided by Syncthing and instead deduced by this library from +/// other information and events. enum class SyncthingDevStatus { Unknown, Disconnected, OwnDevice, Idle, Synchronizing, OutOfSync, Rejected }; QString statusString(SyncthingDevStatus status); diff --git a/connector/syncthingdir.cpp b/connector/syncthingdir.cpp index 2d56850..43ff8bb 100644 --- a/connector/syncthingdir.cpp +++ b/connector/syncthingdir.cpp @@ -17,8 +17,12 @@ QString statusString(SyncthingDirStatus status) return QCoreApplication::translate("SyncthingDirStatus", "unknown"); case SyncthingDirStatus::Idle: return QCoreApplication::translate("SyncthingDirStatus", "idle"); + case SyncthingDirStatus::WaitingToScan: + return QCoreApplication::translate("SyncthingDirStatus", "waiting to scan"); case SyncthingDirStatus::Scanning: return QCoreApplication::translate("SyncthingDirStatus", "scanning"); + case SyncthingDirStatus::PreparingToSync: + return QCoreApplication::translate("SyncthingDirStatus", "preparing to sync"); case SyncthingDirStatus::Synchronizing: return QCoreApplication::translate("SyncthingDirStatus", "synchronizing"); case SyncthingDirStatus::OutOfSync: @@ -55,7 +59,7 @@ bool SyncthingDir::checkWhetherStatusUpdateRelevant(DateTime time) bool SyncthingDir::finalizeStatusUpdate(SyncthingDirStatus newStatus, DateTime time) { // handle obsoletion of out-of-sync items: no FolderErrors are accepted older than the last "sync" state are accepted - if (newStatus == SyncthingDirStatus::Synchronizing) { + if (newStatus == SyncthingDirStatus::PreparingToSync || newStatus == SyncthingDirStatus::Synchronizing) { // update time of last "sync" state and obsolete currently assigned errors lastSyncStarted = time; // used internally and not displayed, hence keep it GMT itemErrors.clear(); @@ -99,8 +103,16 @@ bool SyncthingDir::assignStatus(const QString &statusStr, CppUtilities::DateTime if (statusStr == QLatin1String("idle")) { completionPercentage = 0; newStatus = SyncthingDirStatus::Idle; + } else if (statusStr == QLatin1String("scan-waiting")) { + newStatus = SyncthingDirStatus::WaitingToScan; } else if (statusStr == QLatin1String("scanning")) { newStatus = SyncthingDirStatus::Scanning; + } else if (statusStr == QLatin1String("sync-preparing")) { + // ensure status changed signal is emitted + if (!itemErrors.empty()) { + status = SyncthingDirStatus::Unknown; + } + newStatus = SyncthingDirStatus::PreparingToSync; } else if (statusStr == QLatin1String("syncing")) { // ensure status changed signal is emitted if (!itemErrors.empty()) { diff --git a/connector/syncthingdir.h b/connector/syncthingdir.h index 9dc8bd4..9e75524 100644 --- a/connector/syncthingdir.h +++ b/connector/syncthingdir.h @@ -12,7 +12,9 @@ namespace Data { -enum class SyncthingDirStatus { Unknown, Idle, Scanning, Synchronizing, OutOfSync }; +/// \brief The SyncthingDirStatus enum represents a Syncthing directory status. +/// \remarks It needs to be kept in sync with the states defined in Syncthing's "syncthing/lib/model/folderstate.go". +enum class SyncthingDirStatus { Unknown, Idle, WaitingToScan, Scanning, PreparingToSync, Synchronizing, OutOfSync }; QString LIB_SYNCTHING_CONNECTOR_EXPORT statusString(SyncthingDirStatus status); diff --git a/connector/tests/misctests.cpp b/connector/tests/misctests.cpp index c212f80..348cadd 100644 --- a/connector/tests/misctests.cpp +++ b/connector/tests/misctests.cpp @@ -203,6 +203,10 @@ void MiscTests::testSyncthingDir() const DateTime lastScanTime(DateTime::now()); updateTime += TimeSpan::fromSeconds(5); + CPPUNIT_ASSERT(dir.assignStatus(SyncthingDirStatus::WaitingToScan, updateTime)); + CPPUNIT_ASSERT(dir.lastScanTime.isNull()); + CPPUNIT_ASSERT_EQUAL(QStringLiteral("waiting to scan"), dir.statusString()); + updateTime += TimeSpan::fromSeconds(5); CPPUNIT_ASSERT(dir.assignStatus(SyncthingDirStatus::Scanning, updateTime)); CPPUNIT_ASSERT(dir.lastScanTime.isNull()); CPPUNIT_ASSERT_EQUAL(QStringLiteral("scanning"), dir.statusString()); @@ -221,13 +225,20 @@ void MiscTests::testSyncthingDir() CPPUNIT_ASSERT(!dir.assignStatus(SyncthingDirStatus::Idle, updateTime += TimeSpan::fromMinutes(1.5))); CPPUNIT_ASSERT_EQUAL(updateTime, dir.lastSyncStarted); const auto lastSyncTime(updateTime += TimeSpan::fromMinutes(1.5)); + dir.itemErrors.emplace_back(); CPPUNIT_ASSERT(dir.assignStatus(SyncthingDirStatus::Synchronizing, lastSyncTime)); CPPUNIT_ASSERT_EQUAL(QStringLiteral("synchronizing"), dir.statusString()); CPPUNIT_ASSERT_EQUAL(0_st, dir.itemErrors.size()); CPPUNIT_ASSERT_EQUAL(lastSyncTime, dir.lastSyncStarted); + const auto lastSyncTime2(updateTime += TimeSpan::fromMinutes(2.0)); + dir.itemErrors.emplace_back(); + CPPUNIT_ASSERT(dir.assignStatus(SyncthingDirStatus::PreparingToSync, lastSyncTime2)); + CPPUNIT_ASSERT_EQUAL(QStringLiteral("preparing to sync"), dir.statusString()); + CPPUNIT_ASSERT_EQUAL(0_st, dir.itemErrors.size()); + CPPUNIT_ASSERT_EQUAL(lastSyncTime2, dir.lastSyncStarted); CPPUNIT_ASSERT(dir.assignStatus(SyncthingDirStatus::Idle, updateTime += TimeSpan::fromMinutes(1.5))); - CPPUNIT_ASSERT_EQUAL(lastSyncTime, dir.lastSyncStarted); + CPPUNIT_ASSERT_EQUAL(lastSyncTime2, dir.lastSyncStarted); CPPUNIT_ASSERT(dir.assignStatus(QStringLiteral("syncing"), updateTime += TimeSpan::fromMinutes(1.5))); CPPUNIT_ASSERT_EQUAL(updateTime, dir.lastSyncStarted); diff --git a/fileitemactionplugin/syncthingdiractions.cpp b/fileitemactionplugin/syncthingdiractions.cpp index 667aa3d..5906d19 100644 --- a/fileitemactionplugin/syncthingdiractions.cpp +++ b/fileitemactionplugin/syncthingdiractions.cpp @@ -51,9 +51,11 @@ bool SyncthingDirActions::updateStatus(const SyncthingDir &dir) case SyncthingDirStatus::Idle: m_statusAction.setIcon(statusIcons().idling); break; + case SyncthingDirStatus::WaitingToScan: case SyncthingDirStatus::Scanning: m_statusAction.setIcon(statusIcons().scanninig); break; + case SyncthingDirStatus::PreparingToSync: case SyncthingDirStatus::Synchronizing: m_statusAction.setIcon(statusIcons().sync); break; diff --git a/model/syncthingdirectorymodel.cpp b/model/syncthingdirectorymodel.cpp index 9eab918..ca11311 100644 --- a/model/syncthingdirectorymodel.cpp +++ b/model/syncthingdirectorymodel.cpp @@ -314,8 +314,10 @@ QVariant SyncthingDirectoryModel::data(const QModelIndex &index, int role) const return statusIcons().disconnected; case SyncthingDirStatus::Idle: return statusIcons().idling; + case SyncthingDirStatus::WaitingToScan: case SyncthingDirStatus::Scanning: return statusIcons().scanninig; + case SyncthingDirStatus::PreparingToSync: case SyncthingDirStatus::Synchronizing: return statusIcons().sync; case SyncthingDirStatus::OutOfSync: @@ -458,6 +460,8 @@ QString SyncthingDirectoryModel::dirStatusString(const SyncthingDir &dir) return dir.rawStatus.isEmpty() ? tr("Unknown status") : QString(dir.rawStatus); case SyncthingDirStatus::Idle: return tr("Idle"); + case SyncthingDirStatus::WaitingToScan: + return tr("Waiting to scan"); case SyncthingDirStatus::Scanning: if (dir.scanningPercentage > 0) { if (dir.scanningRate != 0.0) { @@ -466,6 +470,8 @@ QString SyncthingDirectoryModel::dirStatusString(const SyncthingDir &dir) return tr("Scanning (%1 %)").arg(dir.scanningPercentage); } return tr("Scanning"); + case SyncthingDirStatus::PreparingToSync: + return tr("Preparing to sync"); case SyncthingDirStatus::Synchronizing: return dir.completionPercentage > 0 ? tr("Synchronizing (%1 %)").arg(dir.completionPercentage) : tr("Synchronizing"); case SyncthingDirStatus::OutOfSync: @@ -487,7 +493,10 @@ QVariant SyncthingDirectoryModel::dirStatusColor(const SyncthingDir &dir) const break; case SyncthingDirStatus::Idle: return Colors::green(m_brightColors); + case SyncthingDirStatus::WaitingToScan: + return Colors::orange(m_brightColors); case SyncthingDirStatus::Scanning: + case SyncthingDirStatus::PreparingToSync: case SyncthingDirStatus::Synchronizing: return Colors::blue(m_brightColors); case SyncthingDirStatus::OutOfSync: