qtdoc/examples/demos/documentviewer/app/recentfiles.cpp

170 lines
4.2 KiB
C++

// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "recentfiles.h"
#include <QFileInfo>
#include <QSettings>
RecentFiles::RecentFiles(QObject *parent) : QObject(parent)
{
}
void RecentFiles::clear()
{
if (isEmpty())
return;
QStringList::clear();
emit countChanged(0);
emit listCleared();
}
void RecentFiles::addFile(const QString &fileName, EmitPolicy policy)
{
if (!testFileAccess(fileName))
return;
// Remember size, as cleanup can result in a change without size change
const qsizetype c = count();
// Clean dangling and duplicate files
bool duplicateFound = false;
for (const QString &file : *this) {
if (!testFileAccess(file)) {
removeFile(file, RemoveReason::Dangling);
} else if (file == fileName) {
removeFile(file, RemoveReason::Duplicate);
duplicateFound = true;
}
}
// Cut tail
while (count() > m_maxFiles)
removeFile((count() - 1), RemoveReason::TailCut);
prepend(fileName);
switch (policy) {
case EmitPolicy::NeverEmit:
return;
case EmitPolicy::AllwaysEmit:
emit changed();
emit fileAdded(fileName);
emit countChanged(count());
return;
case EmitPolicy::EmitWhenChanged:
emit changed();
if (!duplicateFound)
emit fileAdded(fileName);
if (c != count())
emit countChanged(count());
return;
}
}
void RecentFiles::addFiles(const QStringList &files)
{
if (files.isEmpty())
return;
if (files.count() == 1) {
addFile(files.at(0));
return;
}
const auto &c = count();
for (const auto &file : files)
addFile(file, EmitPolicy::NeverEmit);
emit filesAdded(files);
emit changed();
if (count() != c)
emit countChanged(count());
}
// Test if file exists and can be opened
bool RecentFiles::testFileAccess(const QString &fileName) const
{
QFileInfo info(fileName);
if (!info.isFile())
return false;
switch (m_openMode) {
case QIODevice::ReadOnly:
if (!info.isReadable())
return false;
break;
case QIODevice::ReadWrite:
if (!(info.isReadable() && info.isWritable()))
return false;
break;
case QIODevice::WriteOnly:
if (!info.isWritable())
return false;
break;
}
return true;
}
void RecentFiles::removeFile(qsizetype index, RemoveReason reason)
{
if (index < 0 || index >= count())
return;
const QString &fileName = at(index);
remove(index);
// No emit for duplicate removal, add emits changed later.
if (reason == RemoveReason::Duplicate)
return;
emit fileRemoved(fileName, reason);
emit changed();
}
void RecentFiles::saveSettings(QSettings &settings, const QString &key) const
{
settings.beginGroup(key);
settings.setValue(s_maxFiles, maxFiles());
settings.setValue(s_openMode, static_cast<int>(openMode()));
if (!isEmpty()) {
settings.beginWriteArray(s_fileNames, count());
for (int index = 0; index < count(); ++index) {
settings.setArrayIndex(index);
settings.setValue(s_file, at(index));
}
settings.endArray();
}
settings.endGroup();
}
bool RecentFiles::restoreFromSettings(QSettings &settings, const QString &key)
{
settings.beginGroup(key);
const qsizetype mxFiles = settings.value(s_maxFiles, maxFiles()).toLongLong();
const auto mode = qvariant_cast<QIODevice::OpenMode>(settings.value(s_openMode,
static_cast<int>(openMode())).toInt());
setMaxFiles(mxFiles);
setOpenMode(mode);
QStringList::clear(); // clear list without emitting
const int numberFiles = settings.beginReadArray(s_fileNames);
for (int index = 0; index < numberFiles; ++index) {
settings.setArrayIndex(index);
const QString absoluteFilePath = settings.value(s_file).toString();
addFile(absoluteFilePath, EmitPolicy::NeverEmit);
}
settings.endArray();
settings.endGroup();
if (count() > 0) {
emit settingsRestored(count());
emit changed();
}
return true;
}