2023-03-23 15:25:43 +00:00
|
|
|
// Copyright (C) 2023 The Qt Company Ltd.
|
|
|
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
|
|
|
|
|
|
|
#include "recentfiles.h"
|
|
|
|
#include <QFileInfo>
|
|
|
|
#include <QSettings>
|
|
|
|
|
|
|
|
void RecentFiles::clear()
|
|
|
|
{
|
|
|
|
if (isEmpty())
|
|
|
|
return;
|
|
|
|
|
2023-07-03 08:49:46 +00:00
|
|
|
m_files.clear();
|
2023-03-23 15:25:43 +00:00
|
|
|
emit countChanged(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void RecentFiles::addFile(const QString &fileName, EmitPolicy policy)
|
|
|
|
{
|
|
|
|
if (!testFileAccess(fileName))
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Remember size, as cleanup can result in a change without size change
|
2023-07-03 08:49:46 +00:00
|
|
|
const qsizetype c = m_files.count();
|
2023-03-23 15:25:43 +00:00
|
|
|
|
|
|
|
// Clean dangling and duplicate files
|
2023-07-03 08:49:46 +00:00
|
|
|
for (qsizetype i = 0; i < m_files.size(); ) {
|
|
|
|
const QString &file = m_files.at(i);
|
2023-03-23 15:25:43 +00:00
|
|
|
if (!testFileAccess(file)) {
|
|
|
|
removeFile(file, RemoveReason::Dangling);
|
|
|
|
} else if (file == fileName) {
|
|
|
|
removeFile(file, RemoveReason::Duplicate);
|
2023-07-03 08:49:46 +00:00
|
|
|
} else {
|
|
|
|
++i;
|
2023-03-23 15:25:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Cut tail
|
2023-07-03 08:49:46 +00:00
|
|
|
while (m_files.count() > m_maxFiles)
|
|
|
|
removeFile((m_files.count() - 1), RemoveReason::TailCut);
|
2023-03-23 15:25:43 +00:00
|
|
|
|
2023-07-03 08:49:46 +00:00
|
|
|
m_files.prepend(fileName);
|
2023-03-23 15:25:43 +00:00
|
|
|
|
|
|
|
switch (policy) {
|
|
|
|
case EmitPolicy::NeverEmit:
|
|
|
|
return;
|
|
|
|
|
|
|
|
case EmitPolicy::AllwaysEmit:
|
|
|
|
emit changed();
|
2023-07-03 08:49:46 +00:00
|
|
|
emit countChanged(m_files.count());
|
2023-03-23 15:25:43 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
case EmitPolicy::EmitWhenChanged:
|
|
|
|
emit changed();
|
|
|
|
|
2023-07-03 08:49:46 +00:00
|
|
|
if (c != m_files.count())
|
|
|
|
emit countChanged(m_files.count());
|
2023-03-23 15:25:43 +00:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void RecentFiles::addFiles(const QStringList &files)
|
|
|
|
{
|
|
|
|
if (files.isEmpty())
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (files.count() == 1) {
|
|
|
|
addFile(files.at(0));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-07-03 08:49:46 +00:00
|
|
|
const qsizetype c = m_files.count();
|
2023-03-23 15:25:43 +00:00
|
|
|
|
|
|
|
for (const auto &file : files)
|
|
|
|
addFile(file, EmitPolicy::NeverEmit);
|
|
|
|
|
|
|
|
emit changed();
|
2023-07-03 08:49:46 +00:00
|
|
|
if (m_files.count() != c)
|
|
|
|
emit countChanged(m_files.count());
|
2023-03-23 15:25:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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)
|
|
|
|
{
|
2023-07-03 08:49:46 +00:00
|
|
|
if (index < 0 || index >= m_files.count())
|
2023-03-23 15:25:43 +00:00
|
|
|
return;
|
|
|
|
|
2023-07-03 08:49:46 +00:00
|
|
|
m_files.remove(index);
|
2023-03-23 15:25:43 +00:00
|
|
|
|
|
|
|
// No emit for duplicate removal, add emits changed later.
|
2023-07-03 11:44:27 +00:00
|
|
|
if (reason != RemoveReason::Duplicate)
|
|
|
|
emit changed();
|
2023-03-23 15:25:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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()) {
|
2023-07-03 08:49:46 +00:00
|
|
|
settings.beginWriteArray(s_fileNames, m_files.count());
|
|
|
|
for (int index = 0; index < m_files.count(); ++index) {
|
2023-03-23 15:25:43 +00:00
|
|
|
settings.setArrayIndex(index);
|
2023-07-03 08:49:46 +00:00
|
|
|
settings.setValue(s_file, m_files.at(index));
|
2023-03-23 15:25:43 +00:00
|
|
|
}
|
|
|
|
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);
|
2023-07-03 08:49:46 +00:00
|
|
|
m_files.clear(); // clear list without emitting
|
2023-03-23 15:25:43 +00:00
|
|
|
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();
|
2023-07-03 11:44:27 +00:00
|
|
|
if (!m_files.isEmpty())
|
2023-03-23 15:25:43 +00:00
|
|
|
emit changed();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|