Setting PinState to Excluded ensures the syncing icon is not shown for ignored items.
If the PinState is not set to Excluded, also all parent directories are shown as being synced, which is very inconvenient for the end user as it seems that some folder are never fully synced by Nextcloud which isn't the case.
As long as .lnk files are not converted to placeholder files, also set them to Excluded to hide the syncing icon.
Closes #5524
Closes #5594
Co-authored-by: Matthieu Gallien <matthieu_gallien@yahoo.fr>
Signed-off-by: Dries Mys <dries.mys@my-dreams.be>
* dehydrated (which is an arbitrary decision).
*/
Unspecified = 3,
+
+ /** The file will never be synced to the cloud.
+ *
+ * Usefull for ignored files to indicate to the OS the file will never be
+ * synced
+ */
+ Excluded = 4,
};
Q_ENUM_NS(PinState)
auto relativePath = path.midRef(this->path().size());
+ if (pathIsIgnored(path)) {
+ const auto pinState = _vfs->pinState(relativePath.toString());
+ if (!pinState || *pinState != PinState::Excluded) {
+ if (!_vfs->setPinState(relativePath.toString(), PinState::Excluded))
+ qCWarning(lcFolder) << "Could not set pin state of" << relativePath << "to excluded";
+ }
+ return;
+ } else {
+ const auto pinState = _vfs->pinState(relativePath.toString());
+ if (pinState && *pinState == PinState::Excluded) {
+ if (!_vfs->setPinState(relativePath.toString(), PinState::Inherited))
+ qCWarning(lcFolder) << "Could not switch pin state of" << relativePath << "from" << *pinState << "to inherited";
+ }
+ }
+
// Add to list of locally modified paths
//
// We do this before checking for our own sync-related changes to make
settings->remove(FolderMan::escapeAlias(_definition.alias));
}
+bool Folder::pathIsIgnored(const QString &path) const
+{
+ if (path.isEmpty()) {
+ return true;
+ }
+
+#ifndef OWNCLOUD_TEST
+ if (isFileExcludedAbsolute(path) && !Utility::isConflictFile(path)) {
+ qCDebug(lcFolder) << "* Ignoring file" << path;
+ return true;
+ }
+#endif
+ return false;
+}
+
bool Folder::isFileExcludedAbsolute(const QString &fullPath) const
{
return _engine->excludedFiles().isExcluded(fullPath, path(), _definition.ignoreHiddenFiles);
/// Removes the folder from the account's settings.
void removeFromSettings() const;
+ /* Check if the path is ignored. */
+ [[nodiscard]] bool pathIsIgnored(const QString &path) const;
+
/**
* Returns whether a file inside this folder should be excluded.
*/
_timer.start();
}
-bool FolderWatcher::pathIsIgnored(const QString &path)
+bool FolderWatcher::pathIsIgnored(const QString &path) const
{
- if (path.isEmpty())
- return true;
- if (!_folder)
- return false;
-
-#ifndef OWNCLOUD_TEST
- if (_folder->isFileExcludedAbsolute(path) && !Utility::isConflictFile(path)) {
- qCDebug(lcFolderWatcher) << "* Ignoring file" << path;
- return true;
- }
-#endif
- return false;
+ return path.isEmpty();
}
bool FolderWatcher::isReliable() const
*/
void init(const QString &root);
- /* Check if the path is ignored. */
- bool pathIsIgnored(const QString &path);
-
/**
* Returns false if the folder watcher can't be trusted to capture all
* notifications.
QString possiblyAddUnlockedFilePath(const QString &path);
QString findMatchingUnlockedFileInDir(const QString &dirPath, const QString &lockFileName);
+ /* Check if the path should be igored by the FolderWatcher. */
+ [[nodiscard]] bool pathIsIgnored(const QString &path) const;
+
/** Path of the expected test notification */
QString _testNotificationPath;
return OCC::PinState::OnlineOnly;
case CF_PIN_STATE_INHERIT:
return OCC::PinState::Inherited;
+ case CF_PIN_STATE_EXCLUDED:
+ return OCC::PinState::Excluded;
default:
Q_UNREACHABLE();
return OCC::PinState::Inherited;
return CF_PIN_STATE_UNPINNED;
case OCC::PinState::Unspecified:
return CF_PIN_STATE_UNSPECIFIED;
+ case OCC::PinState::Excluded:
+ return CF_PIN_STATE_EXCLUDED;
default:
Q_UNREACHABLE();
return CF_PIN_STATE_UNSPECIFIED;
Result<Vfs::ConvertToPlaceholderResult, QString> VfsCfApi::convertToPlaceholder(const QString &filename, const SyncFileItem &item, const QString &replacesFile)
{
+ const auto localPath = QDir::toNativeSeparators(filename);
+
if (item._type != ItemTypeDirectory && OCC::FileSystem::isLnkFile(filename)) {
qCInfo(lcCfApi) << "File \"" << filename << "\" is a Windows shortcut. Not converting it to a placeholder.";
+ const auto pinState = pinStateLocal(localPath);
+ if (!pinState || *pinState != PinState::Excluded)
+ setPinStateLocal(localPath, PinState::Excluded);
return Vfs::ConvertToPlaceholderResult::Ok;
}
- const auto localPath = QDir::toNativeSeparators(filename);
const auto replacesPath = QDir::toNativeSeparators(replacesFile);
if (cfapi::findPlaceholderInfo(localPath)) {
const auto localPath = QDir::toNativeSeparators(params().filesystemPath + folderPath);
+ return setPinStateLocal(localPath, state);
+}
+
+bool VfsCfApi::setPinStateLocal(const QString &localPath, PinState state)
+{
if (cfapi::setPinState(localPath, state, cfapi::Recurse)) {
return true;
} else {
{
const auto localPath = QDir::toNativeSeparators(params().filesystemPath + folderPath);
+ return pinStateLocal(localPath);
+}
+
+Optional<PinState> VfsCfApi::pinStateLocal(const QString &localPath) const
+{
const auto info = cfapi::findPlaceholderInfo(localPath);
if (!info) {
qCWarning(lcCfApi) << "Couldn't find pin state for regular non-placeholder file" << localPath;
void onHydrationJobFinished(HydrationJob *job);
HydrationJob *findHydrationJob(const QString &requestId) const;
+ bool setPinStateLocal(const QString &localPath, PinState state);
+ [[nodiscard]] Optional<PinState> pinStateLocal(const QString &localPath) const;
+
struct HasHydratedDehydrated {
bool hasHydrated = false;
bool hasDehydrated = false;