ac = menu->addAction(tr("Edit Ignored Files"));
connect(ac, &QAction::triggered, this, &AccountSettings::slotEditCurrentIgnoredFiles);
- if (!_ui->_folderList->isExpanded(index) && !folder->useVirtualFiles()) {
+ if (!_ui->_folderList->isExpanded(index) && !folder->newFilesAreVirtual()) {
ac = menu->addAction(tr("Choose what to sync"));
ac->setEnabled(folderConnected);
connect(ac, &QAction::triggered, this, &AccountSettings::doExpand);
ac = menu->addAction(tr("Remove folder sync connection"));
connect(ac, &QAction::triggered, this, &AccountSettings::slotRemoveCurrentFolder);
- if (Theme::instance()->showVirtualFilesOption() || folder->useVirtualFiles()) {
+ if (Theme::instance()->showVirtualFilesOption() || folder->newFilesAreVirtual()) {
ac = menu->addAction(tr("Create virtual files for new files (Experimental)"));
ac->setCheckable(true);
- ac->setChecked(folder->useVirtualFiles());
+ ac->setChecked(folder->newFilesAreVirtual());
connect(ac, &QAction::toggled, this, [folder, this](bool checked) {
if (!checked) {
if (folder)
- folder->setUseVirtualFiles(false);
+ folder->setNewFilesAreVirtual(false);
// Make sure the size is recomputed as the virtual file indicator changes
_ui->_folderList->doItemsLayout();
return;
}
OwncloudWizard::askExperimentalVirtualFilesFeature([folder, this](bool enable) {
if (enable && folder)
- folder->setUseVirtualFiles(enable);
+ folder->setNewFilesAreVirtual(enable);
// Also wipe selective sync settings
bool ok = false;
if (folderWizard->property("useVirtualFiles").toBool()) {
definition.virtualFilesMode = bestAvailableVfsMode();
+ if (definition.virtualFilesMode != Vfs::Off)
+ definition.newFilesAreVirtual = true;
}
{
// Potentially upgrade suffix vfs to windows vfs
ENFORCE(_vfs);
- if (_definition.virtualFilesMode == Vfs::WithSuffix && _definition.upgradeVfsMode) {
+ if (_definition.virtualFilesMode == Vfs::WithSuffix
+ && _definition.upgradeVfsMode
+ && isVfsPluginAvailable(Vfs::WindowsCfApi)) {
if (auto winvfs = createVfsFromPlugin(Vfs::WindowsCfApi)) {
// Wipe the existing suffix files from fs and journal
SyncEngine::wipeVirtualFiles(path(), _journal, *_vfs);
slotScheduleThisFolder();
}
-void Folder::setUseVirtualFiles(bool enabled)
+void Folder::setSupportsVirtualFiles(bool enabled)
{
Vfs::Mode newMode = _definition.virtualFilesMode;
if (enabled && _definition.virtualFilesMode == Vfs::Off) {
}
}
+bool Folder::newFilesAreVirtual() const
+{
+ return _definition.newFilesAreVirtual;
+}
+
+void Folder::setNewFilesAreVirtual(bool enabled)
+{
+ _definition.newFilesAreVirtual = enabled;
+ saveToSettings();
+}
+
void Folder::saveToSettings() const
{
// Remove first to make sure we don't get duplicates
return other != this && other->cleanPath() == this->cleanPath();
});
- if (useVirtualFiles() || _saveInFoldersWithPlaceholders) {
+ if (supportsVirtualFiles() || _saveInFoldersWithPlaceholders) {
// If virtual files are enabled or even were enabled at some point,
// save the folder to a group that will not be read by older (<2.5.0) clients.
// The name is from when virtual files were called placeholders.
opt._confirmExternalStorage = cfgFile.confirmExternalStorage();
opt._moveFilesToTrash = cfgFile.moveToTrash();
opt._vfs = _vfs;
+ opt._newFilesAreVirtual = _definition.newFilesAreVirtual;
QByteArray chunkSizeEnv = qgetenv("OWNCLOUD_CHUNK_SIZE");
if (!chunkSizeEnv.isEmpty()) {
_folderWatcher->startNotificatonTest(path() + QLatin1String(".owncloudsync.log"));
}
-bool Folder::useVirtualFiles() const
+bool Folder::supportsVirtualFiles() const
{
return _definition.virtualFilesMode != Vfs::Off;
}
settings.setValue(QLatin1String("paused"), folder.paused);
settings.setValue(QLatin1String("ignoreHiddenFiles"), folder.ignoreHiddenFiles);
settings.setValue(QLatin1String(versionC), maxSettingsVersion());
+ settings.setValue(QLatin1String("usePlaceholders"), folder.newFilesAreVirtual);
settings.setValue(QStringLiteral("virtualFilesMode"), Vfs::modeToString(folder.virtualFilesMode));
- // to support older versions: there usePlaceholders means suffix placeholders
- settings.setValue(QLatin1String("usePlaceholders"), folder.virtualFilesMode == Vfs::WithSuffix);
// Happens only on Windows when the explorer integration is enabled.
if (!folder.navigationPaneClsid.isNull())
folder->paused = settings.value(QLatin1String("paused")).toBool();
folder->ignoreHiddenFiles = settings.value(QLatin1String("ignoreHiddenFiles"), QVariant(true)).toBool();
folder->navigationPaneClsid = settings.value(QLatin1String("navigationPaneClsid")).toUuid();
+ folder->newFilesAreVirtual = settings.value(QLatin1String("usePlaceholders")).toBool();
- folder->virtualFilesMode = Vfs::Off;
+ folder->virtualFilesMode = Vfs::WithSuffix;
QString vfsModeString = settings.value(QStringLiteral("virtualFilesMode")).toString();
if (!vfsModeString.isEmpty()) {
if (auto mode = Vfs::modeFromString(vfsModeString)) {
folder->virtualFilesMode = *mode;
} else {
- qCWarning(lcFolder) << "Unknown virtualFilesMode:" << vfsModeString << "assuming 'off'";
+ qCWarning(lcFolder) << "Unknown virtualFilesMode:" << vfsModeString << "assuming 'suffix'";
}
- } else if (settings.value(QLatin1String("usePlaceholders")).toBool()) {
- folder->virtualFilesMode = Vfs::WithSuffix;
+ } else {
folder->upgradeVfsMode = true;
}
bool ignoreHiddenFiles = false;
/// Which virtual files setting the folder uses
Vfs::Mode virtualFilesMode = Vfs::Off;
+ /// Whether new files are virtual
+ bool newFilesAreVirtual = false;
/// The CLSID where this folder appears in registry for the Explorer navigation pane entry.
QUuid navigationPaneClsid;
- /// Whether this suffix-vfs should be migrated to a better
- /// vfs plugin if possible
+ /// Whether the vfs mode shall silently be updated if possible
bool upgradeVfsMode = false;
/// Saves the folder definition, creating a new settings group.
*/
void registerFolderWatcher();
- /** virtual files of some kind are enabled */
- bool useVirtualFiles() const;
- void setUseVirtualFiles(bool enabled);
+ /** virtual files of some kind are enabled
+ *
+ * This is independent of whether new files will be virtual. It's possible to have this enabled
+ * and never have an automatic virtual file. But when it's on, the shell context menu will allow
+ * users to make existing files virtual.
+ */
+ bool supportsVirtualFiles() const;
+ void setSupportsVirtualFiles(bool enabled);
+
+ /** whether new remote files shall become virtual locally */
+ bool newFilesAreVirtual() const;
+ void setNewFilesAreVirtual(bool enabled);
signals:
void syncStateChange();
case FolderStatusDelegate::FolderErrorMsg:
return f->syncResult().errorStrings();
case FolderStatusDelegate::FolderInfoMsg:
- return f->useVirtualFiles()
+ return f->newFilesAreVirtual()
? QStringList(tr("New files are being created as virtual files."))
: QStringList();
case FolderStatusDelegate::SyncRunning:
auto info = infoForIndex(parent);
if (!info)
return 0;
- if (info->_folder && info->_folder->useVirtualFiles())
+ if (info->_folder && info->_folder->newFilesAreVirtual())
return 0;
if (info->hasLabel())
return 1;
if (!info)
return false;
- if (info->_folder && info->_folder->useVirtualFiles())
+ if (info->_folder && info->_folder->newFilesAreVirtual())
return false;
if (!info->_fetched)
// Keep showing the error to the user, it will be hidden when the account reconnects
return false;
}
- if (info->_folder && info->_folder->useVirtualFiles()) {
+ if (info->_folder && info->_folder->newFilesAreVirtual()) {
// Selective sync is hidden in that case
return false;
}
folderDefinition.ignoreHiddenFiles = folderMan->ignoreHiddenFiles();
if (_ocWizard->useVirtualFileSync()) {
folderDefinition.virtualFilesMode = bestAvailableVfsMode();
+ if (folderDefinition.virtualFilesMode != Vfs::Off)
+ folderDefinition.newFilesAreVirtual = true;
}
if (folderMan->navigationPaneHelper().showInExplorerNavigationPane())
folderDefinition.navigationPaneClsid = QUuid::createUuid();
}
}
}
- if (hasVirtualFile || (hasDir && syncFolder->useVirtualFiles()))
+ if (hasVirtualFile || (hasDir && syncFolder->supportsVirtualFiles()))
listener->sendMessage(QLatin1String("MENU_ITEM:DOWNLOAD_VIRTUAL_FILE::") + tr("Download file(s)", "", files.size()));
- if ((hasNormalFiles || hasDir) && syncFolder->useVirtualFiles())
+ if ((hasNormalFiles || hasDir) && syncFolder->supportsVirtualFiles())
listener->sendMessage(QLatin1String("MENU_ITEM:REPLACE_VIRTUAL_FILE::") + tr("Replace file(s) by virtual file", "", files.size()));
}
return;
}
// Turn new remote files into virtual files if the option is enabled.
- auto &vfs = _discoveryData->_syncOptions._vfs;
- if (!localEntry.isValid() && vfs->mode() != Vfs::Off && item->_type == ItemTypeFile) {
+ auto &opts = _discoveryData->_syncOptions;
+ if (!localEntry.isValid() && opts._vfs->mode() != Vfs::Off && opts._newFilesAreVirtual && item->_type == ItemTypeFile) {
item->_type = ItemTypeVirtualFile;
if (isVfsWithSuffix())
addVirtualFileSuffix(path._original);
}
auto limit = _syncOptions._newBigFolderSizeLimit;
- if (limit < 0 || _syncOptions._vfs->mode() != Vfs::Off) {
+ if (limit < 0 || (_syncOptions._vfs->mode() != Vfs::Off && _syncOptions._newFilesAreVirtual)) {
// no limit, everything is allowed;
return callback(false);
}
/** Create a virtual file for new files instead of downloading. May not be null */
QSharedPointer<Vfs> _vfs;
+ /** True if new files shall be virtual */
+ bool _newFilesAreVirtual = false;
+
/** The initial un-adjusted chunk size in bytes for chunked uploads, both
* for old and new chunking algorithm, which classifies the item to be chunked
*
{
SyncOptions options;
options._vfs.reset(createVfsFromPlugin(Vfs::WithSuffix).release());
+ options._newFilesAreVirtual = true;
return options;
}
QVERIFY(!dbRecord(fakeFolder, "A/a1.nextcloud").isValid());
}
- // Check what happens if vfs mode is disabled
- void testSwitchOfVfs()
+ void testNewFilesNotVirtual()
{
- QSKIP("Does not work with the new discovery because the way we simulate the old client does not work");
FakeFolder fakeFolder{ FileInfo() };
SyncOptions syncOptions = vfsSyncOptions();
fakeFolder.syncEngine().setSyncOptions(syncOptions);
QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
- // Create a virtual file
fakeFolder.remoteModifier().mkdir("A");
fakeFolder.remoteModifier().insert("A/a1");
QVERIFY(fakeFolder.syncOnce());
QVERIFY(fakeFolder.currentLocalState().find("A/a1.nextcloud"));
- // Switch off new files becoming virtual files
- syncOptions._vfs.reset(new VfsOff);
+ syncOptions._newFilesAreVirtual = false;
fakeFolder.syncEngine().setSyncOptions(syncOptions);
- // A sync that doesn't do remote discovery will wipe the placeholder, but not redownload
- QVERIFY(fakeFolder.syncOnce());
- QVERIFY(!fakeFolder.currentLocalState().find("A/a1.nextcloud"));
- QVERIFY(!fakeFolder.currentLocalState().find("A/a1"));
- QVERIFY(fakeFolder.currentRemoteState().find("A/a1"));
- QVERIFY(!fakeFolder.currentRemoteState().find("A/a1.nextcloud"));
-
- // But with a remote discovery the virtual files will be removed and
- // the remote files will be downloaded.
- fakeFolder.syncJournal().forceRemoteDiscoveryNextSync();
- QVERIFY(fakeFolder.syncOnce());
- QVERIFY(fakeFolder.currentLocalState().find("A/a1"));
- QVERIFY(!fakeFolder.currentLocalState().find("A/a1.nextcloud"));
- QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
- }
-
- // Older versions may leave db entries for foo and foo.nextcloud
- void testOldVersion2()
- {
- QSKIP("Does not work with the new discovery because the way we simulate the old client does not work");
- FakeFolder fakeFolder{ FileInfo() };
-
- // Sync a file
- fakeFolder.remoteModifier().mkdir("A");
- fakeFolder.remoteModifier().insert("A/a1");
- QVERIFY(fakeFolder.syncOnce());
- QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
-
- // Create the virtual file too
- // In the wild, the new version would create the virtual file and the db entry
- // while the old version would download the plain file.
- fakeFolder.localModifier().insert("A/a1.nextcloud");
- auto &db = fakeFolder.syncJournal();
- SyncJournalFileRecord rec;
- db.getFileRecord(QByteArray("A/a1"), &rec);
- rec._type = ItemTypeVirtualFile;
- rec._path = "A/a1.nextcloud";
- db.setFileRecord(rec);
-
- fakeFolder.syncEngine().setSyncOptions(vfsSyncOptions());
-
- // Check that a sync removes the virtual file and its db entry
+ // Create a new remote file, it'll not be virtual
+ fakeFolder.remoteModifier().insert("A/a2");
QVERIFY(fakeFolder.syncOnce());
- QVERIFY(!fakeFolder.currentLocalState().find("A/a1.nextcloud"));
- QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
- QVERIFY(!dbRecord(fakeFolder, "A/a1.nextcloud").isValid());
+ QVERIFY(fakeFolder.currentLocalState().find("A/a2"));
+ QVERIFY(!fakeFolder.currentLocalState().find("A/a2.nextcloud"));
}
void testDownloadRecursive()