Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 18 additions & 6 deletions src/foldermodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -431,11 +431,22 @@ void FolderModel::summarize(Entry &entry, bool showHidden) {
}
}

int FolderModel::itemCount(const QString &folder, bool showHidden) {
int FolderModel::itemCount(const QString &folder, bool showHidden, const std::function<bool()> &stop) {
if (stop && stop())
return -1;
int count = 0;
for (QDirIterator it(folder, entryFilters(showHidden)); it.hasNext(); it.next())
++count;
return count;
// Let hidden entries through too: filtering a long run inside Qt would
// give this loop no chance to notice cancellation. On Linux a dot name
// is hidden, as in listRecent(). The iterator still excludes . and ...
QDirIterator it(folder, entryFilters(true));
while (it.hasNext()) {
if (stop && stop())
return -1;
it.next();
if (showHidden || !it.fileName().startsWith('.'))
++count;
}
return stop && stop() ? -1 : count;
}

void FolderModel::reload() {
Expand Down Expand Up @@ -527,10 +538,11 @@ void FolderModel::countFolders(quint64 generation) {
watcher->setFuture(QtConcurrent::run([folders, showHidden, latest, generation]() mutable {
// Overtaken (another folder, or a re-read), the counts would be
// thrown away, so it stops instead of listing every subfolder.
const auto overtaken = [&] { return *latest != generation; };
for (auto &folder : folders) {
if (*latest != generation)
if (overtaken())
break;
folder.second.itemCount = itemCount(folder.second.path, showHidden);
folder.second.itemCount = itemCount(folder.second.path, showHidden, overtaken);
}
return folders;
}));
Expand Down
3 changes: 2 additions & 1 deletion src/foldermodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,8 @@ class FolderModel : public QAbstractListModel {
static void summarize(Entry &entry, bool showHidden);
// Only how many items a folder holds, for the folder counts, which have
// no use for its pictures or their order.
static int itemCount(const QString &folder, bool showHidden);
// Returns -1 (unknown) if stopped, never a partially counted folder.
static int itemCount(const QString &folder, bool showHidden, const std::function<bool()> &stop = {});
static QStringList sortModes();
static void sortEntries(QVector<Entry> &entries, const QString &sort, const QLocale &locale = QLocale());
// The Recents view: a path that isn't a folder, listing recently used files.
Expand Down
29 changes: 29 additions & 0 deletions tests/folio_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,35 @@ private slots:
QCOMPARE(FolderModel::itemCount(dir.path(), true), 5);
}

void folderCountStopsInsideTheFolderAndCanBeRetried()
{
QTemporaryDir dir;
for (int i = 0; i < 64; ++i)
write(dir.filePath(QString::number(i) + ".txt"), "x");
int checks = 0;
// Cancellation arrives during one folder, rather than between folders.
const int count = FolderModel::itemCount(dir.path(), false, [&] { return ++checks >= 4; });
QCOMPARE(count, -1); // Unknown, never a partial count.
QVERIFY(checks >= 4);
QVERIFY(checks < 64);
QCOMPARE(FolderModel::itemCount(dir.path(), false), 64);

// An empty or not-yet-started folder is unknown too once cancelled.
QTemporaryDir empty;
QCOMPARE(FolderModel::itemCount(empty.path(), false, [] { return true; }), -1);
QCOMPARE(FolderModel::itemCount(dir.path(), true, [] { return true; }), -1);
QCOMPARE(FolderModel::itemCount(empty.path(), false), 0);

// Hidden entries still take work to enumerate, even when not counted.
QTemporaryDir hidden;
for (int i = 0; i < 64; ++i)
write(hidden.filePath("." + QString::number(i) + ".txt"), "x");
checks = 0;
QCOMPARE(FolderModel::itemCount(hidden.path(), false, [&] { return ++checks >= 4; }), -1);
QCOMPARE(FolderModel::itemCount(hidden.path(), false), 0);
QCOMPARE(FolderModel::itemCount(hidden.path(), true), 64);
}

void folderModelLoadsInTheBackground()
{
QTemporaryDir dir;
Expand Down