diff options
author | Christian Kamm <mail@ckamm.de> | 2019-04-16 11:17:21 +0300 |
---|---|---|
committer | Christian Kamm <mail@ckamm.de> | 2019-04-23 10:21:17 +0300 |
commit | 96831247e24118018b4ccfca70253cd47996e3e4 (patch) | |
tree | 746c6e3857a026ca736c95ab2414c5b6da4b02cd /src | |
parent | ac19fab71aaee448a3f588ba01f06b2f5dca26b8 (diff) |
Vfs: "free space" only shows when it has an effect #7143
To do this, introduce AllDehydrated availability and rename
SomeDehydrated to Mixed - it now guarantees there are also hydrated
items.
Diffstat (limited to 'src')
-rw-r--r-- | src/common/pinstate.h | 16 | ||||
-rw-r--r-- | src/common/syncjournaldb.cpp | 25 | ||||
-rw-r--r-- | src/common/syncjournaldb.h | 9 | ||||
-rw-r--r-- | src/common/vfs.cpp | 10 | ||||
-rw-r--r-- | src/gui/accountsettings.cpp | 6 | ||||
-rw-r--r-- | src/gui/guiutility.cpp | 12 | ||||
-rw-r--r-- | src/gui/guiutility.h | 2 | ||||
-rw-r--r-- | src/gui/socketapi.cpp | 27 |
8 files changed, 64 insertions, 43 deletions
diff --git a/src/common/pinstate.h b/src/common/pinstate.h index 44ee12417..c86d11ae5 100644 --- a/src/common/pinstate.h +++ b/src/common/pinstate.h @@ -83,13 +83,15 @@ enum class PinState { * * Note that this is only about *intent*. The file could still be out of date, * or not have been synced for other reasons, like errors. + * + * NOTE: The numerical values and ordering of this enum are relevant. */ enum class VfsItemAvailability { /** The item and all its subitems are hydrated and pinned AlwaysLocal. * * This guarantees that all contents will be kept in sync. */ - AlwaysLocal, + AlwaysLocal = 0, /** The item and all its subitems are hydrated. * @@ -98,20 +100,24 @@ enum class VfsItemAvailability { * * A folder with no file contents will have this availability. */ - AllHydrated, + AllHydrated = 1, - /** There are dehydrated items but the pin state isn't all OnlineOnly. + /** There are dehydrated and hydrated items. * * This would happen if a dehydration happens to a Unspecified item that * used to be hydrated. */ - SomeDehydrated, + Mixed = 2, + + /** There are only dehydrated items but the pin state isn't all OnlineOnly. + */ + AllDehydrated = 3, /** The item and all its subitems are dehydrated and OnlineOnly. * * This guarantees that contents will not take up space. */ - OnlineOnly, + OnlineOnly = 4, }; } diff --git a/src/common/syncjournaldb.cpp b/src/common/syncjournaldb.cpp index 09b7471a8..1ff231641 100644 --- a/src/common/syncjournaldb.cpp +++ b/src/common/syncjournaldb.cpp @@ -1261,18 +1261,16 @@ bool SyncJournalDb::updateLocalMetadata(const QString &filename, return _setFileRecordLocalMetadataQuery.exec(); } -Optional<bool> SyncJournalDb::hasDehydratedFiles(const QByteArray &filename) +Optional<SyncJournalDb::HasHydratedDehydrated> SyncJournalDb::hasHydratedOrDehydratedFiles(const QByteArray &filename) { QMutexLocker locker(&_mutex); if (!checkConnect()) return {}; auto &query = _countDehydratedFilesQuery; - static_assert(ItemTypeVirtualFile == 4 && ItemTypeVirtualFileDownload == 5, ""); if (!query.initOrReset(QByteArrayLiteral( - "SELECT count(*) FROM metadata" - " WHERE (" IS_PREFIX_PATH_OR_EQUAL("?1", "path") " OR ?1 == '')" - " AND (type == 4 OR type == 5);"), _db)) { + "SELECT DISTINCT type FROM metadata" + " WHERE (" IS_PREFIX_PATH_OR_EQUAL("?1", "path") " OR ?1 == '');"), _db)) { return {}; } @@ -1280,10 +1278,21 @@ Optional<bool> SyncJournalDb::hasDehydratedFiles(const QByteArray &filename) if (!query.exec()) return {}; - if (!query.next().hasData) - return {}; + HasHydratedDehydrated result; + forever { + auto next = query.next(); + if (!next.ok) + return {}; + if (!next.hasData) + break; + auto type = static_cast<ItemType>(query.intValue(0)); + if (type == ItemTypeFile || type == ItemTypeVirtualFileDehydration) + result.hasHydrated = true; + if (type == ItemTypeVirtualFile || type == ItemTypeVirtualFileDownload) + result.hasDehydrated = true; + } - return query.intValue(0) > 0; + return result; } static void toDownloadInfo(SqlQuery &query, SyncJournalDb::DownloadInfo *res) diff --git a/src/common/syncjournaldb.h b/src/common/syncjournaldb.h index 5aab475f1..d1daefb2a 100644 --- a/src/common/syncjournaldb.h +++ b/src/common/syncjournaldb.h @@ -72,8 +72,15 @@ public: bool updateLocalMetadata(const QString &filename, qint64 modtime, qint64 size, quint64 inode); + /// Return value for hasHydratedOrDehydratedFiles() + struct HasHydratedDehydrated + { + bool hasHydrated = false; + bool hasDehydrated = false; + }; + /** Returns whether the item or any subitems are dehydrated */ - Optional<bool> hasDehydratedFiles(const QByteArray &filename); + Optional<HasHydratedDehydrated> hasHydratedOrDehydratedFiles(const QByteArray &filename); bool exists(); void walCheckpoint(); diff --git a/src/common/vfs.cpp b/src/common/vfs.cpp index 54f6cb6bd..c24c11cd6 100644 --- a/src/common/vfs.cpp +++ b/src/common/vfs.cpp @@ -83,15 +83,17 @@ Optional<VfsItemAvailability> Vfs::availabilityInDb(const QString &folderPath, c { auto pin = _setupParams.journal->internalPinStates().effectiveForPathRecursive(pinPath.toUtf8()); // not being able to retrieve the pin state isn't too bad - Optional<bool> hasDehydrated = _setupParams.journal->hasDehydratedFiles(folderPath.toUtf8()); - if (!hasDehydrated) + auto hydrationStatus = _setupParams.journal->hasHydratedOrDehydratedFiles(folderPath.toUtf8()); + if (!hydrationStatus) return {}; - if (*hasDehydrated) { + if (hydrationStatus->hasDehydrated) { + if (hydrationStatus->hasHydrated) + return VfsItemAvailability::Mixed; if (pin && *pin == PinState::OnlineOnly) return VfsItemAvailability::OnlineOnly; else - return VfsItemAvailability::SomeDehydrated; + return VfsItemAvailability::AllDehydrated; } else { if (pin && *pin == PinState::AlwaysLocal) return VfsItemAvailability::AlwaysLocal; diff --git a/src/gui/accountsettings.cpp b/src/gui/accountsettings.cpp index 775b916ce..cd9274ea3 100644 --- a/src/gui/accountsettings.cpp +++ b/src/gui/accountsettings.cpp @@ -342,7 +342,7 @@ void AccountSettings::slotCustomContextMenuRequested(const QPoint &pos) auto availabilityMenu = menu->addMenu(tr("Availability")); auto availability = folder->vfs().availability(QString()); if (availability) { - ac = availabilityMenu->addAction(Utility::vfsCurrentAvailabilityText(*availability, true)); + ac = availabilityMenu->addAction(Utility::vfsCurrentAvailabilityText(*availability)); ac->setEnabled(false); } @@ -351,7 +351,9 @@ void AccountSettings::slotCustomContextMenuRequested(const QPoint &pos) connect(ac, &QAction::triggered, this, [this]() { slotSetCurrentFolderAvailability(PinState::AlwaysLocal); }); ac = availabilityMenu->addAction(Utility::vfsFreeSpaceActionText()); - ac->setEnabled(!availability || *availability != VfsItemAvailability::OnlineOnly); + ac->setEnabled(!availability + || !(*availability == VfsItemAvailability::OnlineOnly + || *availability == VfsItemAvailability::AllDehydrated)); connect(ac, &QAction::triggered, this, [this]() { slotSetCurrentFolderAvailability(PinState::OnlineOnly); }); ac = menu->addAction(tr("Disable virtual file support...")); diff --git a/src/gui/guiutility.cpp b/src/gui/guiutility.cpp index 545f56bff..10e5bbf2c 100644 --- a/src/gui/guiutility.cpp +++ b/src/gui/guiutility.cpp @@ -69,19 +69,17 @@ bool Utility::openEmailComposer(const QString &subject, const QString &body, QWi return true; } -QString Utility::vfsCurrentAvailabilityText(VfsItemAvailability availability, bool forFolder) +QString Utility::vfsCurrentAvailabilityText(VfsItemAvailability availability) { switch(availability) { case VfsItemAvailability::AlwaysLocal: return QCoreApplication::translate("utility", "Currently always available locally"); case VfsItemAvailability::AllHydrated: return QCoreApplication::translate("utility", "Currently available locally"); - case VfsItemAvailability::SomeDehydrated: - if (forFolder) { - return QCoreApplication::translate("utility", "Currently some available online only"); - } else { - return QCoreApplication::translate("utility", "Currently available online only"); - } + case VfsItemAvailability::Mixed: + return QCoreApplication::translate("utility", "Currently some available online only"); + case VfsItemAvailability::AllDehydrated: + return QCoreApplication::translate("utility", "Currently available online only"); case VfsItemAvailability::OnlineOnly: return QCoreApplication::translate("utility", "Currently available online only"); } diff --git a/src/gui/guiutility.h b/src/gui/guiutility.h index b25ecc937..6e2c5f163 100644 --- a/src/gui/guiutility.h +++ b/src/gui/guiutility.h @@ -41,7 +41,7 @@ namespace Utility { * * This will be used in context menus to describe the current state. */ - QString vfsCurrentAvailabilityText(VfsItemAvailability availability, bool forFolder); + QString vfsCurrentAvailabilityText(VfsItemAvailability availability); /** Translated text for "making items always available locally" */ QString vfsPinActionText(); diff --git a/src/gui/socketapi.cpp b/src/gui/socketapi.cpp index baf9473e9..69192f700 100644 --- a/src/gui/socketapi.cpp +++ b/src/gui/socketapi.cpp @@ -750,7 +750,7 @@ void SocketApi::emailPrivateLink(const QString &link) Utility::openEmailComposer( tr("I shared something with you"), link, - 0); + nullptr); } void OCC::SocketApi::openPrivateLink(const QString &link) @@ -953,19 +953,19 @@ void SocketApi::command_GET_MENU_ITEMS(const QString &argument, OCC::SocketListe auto merge = [](VfsItemAvailability lhs, VfsItemAvailability rhs) { if (lhs == rhs) return lhs; - if (lhs == VfsItemAvailability::SomeDehydrated || rhs == VfsItemAvailability::SomeDehydrated - || lhs == VfsItemAvailability::OnlineOnly || rhs == VfsItemAvailability::OnlineOnly) { - return VfsItemAvailability::SomeDehydrated; - } - return VfsItemAvailability::AllHydrated; + auto l = int(lhs) < int(rhs) ? lhs : rhs; // reduce cases by sorting + auto r = int(lhs) < int(rhs) ? rhs : lhs; + if (l == VfsItemAvailability::AlwaysLocal && r == VfsItemAvailability::AllHydrated) + return VfsItemAvailability::AllHydrated; + if (l == VfsItemAvailability::AllDehydrated && r == VfsItemAvailability::OnlineOnly) + return VfsItemAvailability::AllDehydrated; + return VfsItemAvailability::Mixed; }; - bool isFolderOrMultiple = false; for (const auto &file : files) { auto fileData = FileData::get(file); - isFolderOrMultiple = QFileInfo(fileData.localPath).isDir(); auto availability = folder->vfs().availability(fileData.folderRelativePath); if (!availability) - availability = VfsItemAvailability::SomeDehydrated; // db error + availability = VfsItemAvailability::Mixed; // db error if (!combined) { combined = availability; } else { @@ -973,13 +973,11 @@ void SocketApi::command_GET_MENU_ITEMS(const QString &argument, OCC::SocketListe } } ENFORCE(combined); - if (files.size() > 1) - isFolderOrMultiple = true; // TODO: Should be a submenu, should use icons auto makePinContextMenu = [&](bool makeAvailableLocally, bool freeSpace) { listener->sendMessage(QLatin1String("MENU_ITEM:CURRENT_PIN:d:") - + Utility::vfsCurrentAvailabilityText(*combined, isFolderOrMultiple)); + + Utility::vfsCurrentAvailabilityText(*combined)); listener->sendMessage(QLatin1String("MENU_ITEM:MAKE_AVAILABLE_LOCALLY:") + (makeAvailableLocally ? QLatin1String(":") : QLatin1String("d:")) + Utility::vfsPinActionText()); @@ -993,11 +991,10 @@ void SocketApi::command_GET_MENU_ITEMS(const QString &argument, OCC::SocketListe makePinContextMenu(false, true); break; case VfsItemAvailability::AllHydrated: + case VfsItemAvailability::Mixed: makePinContextMenu(true, true); break; - case VfsItemAvailability::SomeDehydrated: - makePinContextMenu(true, true); - break; + case VfsItemAvailability::AllDehydrated: case VfsItemAvailability::OnlineOnly: makePinContextMenu(true, false); break; |