Implement class for handling filesystem paths

PR #15915.
This commit is contained in:
Vladimir Golovnev
2022-02-08 06:03:48 +03:00
committed by GitHub
parent facfa26eed
commit dd1bd8ad10
131 changed files with 2252 additions and 1868 deletions

View File

@@ -58,8 +58,8 @@ struct ProcessingJob
QVariantHash articleData;
};
const QString ConfFolderName(QStringLiteral("rss"));
const QString RulesFileName(QStringLiteral("download_rules.json"));
const QString CONF_FOLDER_NAME {QStringLiteral("rss")};
const QString RULES_FILE_NAME {QStringLiteral("download_rules.json")};
namespace
{
@@ -107,17 +107,16 @@ AutoDownloader::AutoDownloader()
Q_ASSERT(!m_instance); // only one instance is allowed
m_instance = this;
m_fileStorage = new AsyncFileStorage(
Utils::Fs::expandPathAbs(specialFolderLocation(SpecialFolder::Config) + QLatin1Char('/') + ConfFolderName));
m_fileStorage = new AsyncFileStorage(specialFolderLocation(SpecialFolder::Config) / Path(CONF_FOLDER_NAME));
if (!m_fileStorage)
throw RuntimeError(tr("Directory for RSS AutoDownloader data is unavailable."));
m_fileStorage->moveToThread(m_ioThread);
connect(m_ioThread, &QThread::finished, m_fileStorage, &AsyncFileStorage::deleteLater);
connect(m_fileStorage, &AsyncFileStorage::failed, [](const QString &fileName, const QString &errorString)
connect(m_fileStorage, &AsyncFileStorage::failed, [](const Path &fileName, const QString &errorString)
{
LogMsg(tr("Couldn't save RSS AutoDownloader data in %1. Error: %2")
.arg(fileName, errorString), Log::CRITICAL);
.arg(fileName.toString(), errorString), Log::CRITICAL);
});
m_ioThread->start();
@@ -414,7 +413,7 @@ void AutoDownloader::processJob(const QSharedPointer<ProcessingJob> &job)
void AutoDownloader::load()
{
QFile rulesFile(m_fileStorage->storageDir().absoluteFilePath(RulesFileName));
QFile rulesFile {(m_fileStorage->storageDir() / Path(RULES_FILE_NAME)).data()};
if (!rulesFile.exists())
loadRulesLegacy();
@@ -463,7 +462,7 @@ void AutoDownloader::store()
for (const auto &rule : asConst(m_rules))
jsonObj.insert(rule.name(), rule.toJsonObject());
m_fileStorage->store(RulesFileName, QJsonDocument(jsonObj).toJson());
m_fileStorage->store(Path(RULES_FILE_NAME), QJsonDocument(jsonObj).toJson());
}
void AutoDownloader::storeDeferred()

View File

@@ -41,6 +41,7 @@
#include <QStringList>
#include "base/global.h"
#include "base/path.h"
#include "base/preferences.h"
#include "base/utils/fs.h"
#include "base/utils/string.h"
@@ -132,7 +133,7 @@ namespace RSS
int ignoreDays = 0;
QDateTime lastMatch;
QString savePath;
Path savePath;
QString category;
std::optional<bool> addPaused;
std::optional<BitTorrent::TorrentContentLayout> contentLayout;
@@ -466,7 +467,7 @@ QJsonObject AutoDownloadRule::toJsonObject() const
, {Str_MustNotContain, mustNotContain()}
, {Str_EpisodeFilter, episodeFilter()}
, {Str_AffectedFeeds, QJsonArray::fromStringList(feedURLs())}
, {Str_SavePath, savePath()}
, {Str_SavePath, savePath().toString()}
, {Str_AssignedCategory, assignedCategory()}
, {Str_LastMatch, lastMatch().toString(Qt::RFC2822Date)}
, {Str_IgnoreDays, ignoreDays()}
@@ -485,7 +486,7 @@ AutoDownloadRule AutoDownloadRule::fromJsonObject(const QJsonObject &jsonObj, co
rule.setMustNotContain(jsonObj.value(Str_MustNotContain).toString());
rule.setEpisodeFilter(jsonObj.value(Str_EpisodeFilter).toString());
rule.setEnabled(jsonObj.value(Str_Enabled).toBool(true));
rule.setSavePath(jsonObj.value(Str_SavePath).toString());
rule.setSavePath(Path(jsonObj.value(Str_SavePath).toString()));
rule.setCategory(jsonObj.value(Str_AssignedCategory).toString());
rule.setAddPaused(toOptionalBool(jsonObj.value(Str_AddPaused)));
@@ -546,7 +547,7 @@ QVariantHash AutoDownloadRule::toLegacyDict() const
return {{"name", name()},
{"must_contain", mustContain()},
{"must_not_contain", mustNotContain()},
{"save_path", savePath()},
{"save_path", savePath().toString()},
{"affected_feeds", feedURLs()},
{"enabled", isEnabled()},
{"category_assigned", assignedCategory()},
@@ -567,7 +568,7 @@ AutoDownloadRule AutoDownloadRule::fromLegacyDict(const QVariantHash &dict)
rule.setEpisodeFilter(dict.value("episode_filter").toString());
rule.setFeedURLs(dict.value("affected_feeds").toStringList());
rule.setEnabled(dict.value("enabled", false).toBool());
rule.setSavePath(dict.value("save_path").toString());
rule.setSavePath(Path(dict.value("save_path").toString()));
rule.setCategory(dict.value("category_assigned").toString());
rule.setAddPaused(addPausedLegacyToOptionalBool(dict.value("add_paused").toInt()));
rule.setLastMatch(dict.value("last_match").toDateTime());
@@ -624,14 +625,14 @@ void AutoDownloadRule::setName(const QString &name)
m_dataPtr->name = name;
}
QString AutoDownloadRule::savePath() const
Path AutoDownloadRule::savePath() const
{
return m_dataPtr->savePath;
}
void AutoDownloadRule::setSavePath(const QString &savePath)
void AutoDownloadRule::setSavePath(const Path &savePath)
{
m_dataPtr->savePath = Utils::Fs::toUniformPath(savePath);
m_dataPtr->savePath = savePath;
}
std::optional<bool> AutoDownloadRule::addPaused() const

View File

@@ -35,6 +35,7 @@
#include <QVariant>
#include "base/bittorrent/torrentcontentlayout.h"
#include "base/pathfwd.h"
class QDateTime;
class QJsonObject;
@@ -77,8 +78,8 @@ namespace RSS
QStringList previouslyMatchedEpisodes() const;
void setPreviouslyMatchedEpisodes(const QStringList &previouslyMatchedEpisodes);
QString savePath() const;
void setSavePath(const QString &savePath);
Path savePath() const;
void setSavePath(const Path &savePath);
std::optional<bool> addPaused() const;
void setAddPaused(std::optional<bool> addPaused);
std::optional<BitTorrent::TorrentContentLayout> torrentContentLayout() const;

View File

@@ -68,17 +68,16 @@ Feed::Feed(const QUuid &uid, const QString &url, const QString &path, Session *s
, m_url(url)
{
const auto uidHex = QString::fromLatin1(m_uid.toRfc4122().toHex());
m_dataFileName = uidHex + QLatin1String(".json");
m_dataFileName = Path(uidHex + QLatin1String(".json"));
// Move to new file naming scheme (since v4.1.2)
const QString legacyFilename
{Utils::Fs::toValidFileSystemName(m_url, false, QLatin1String("_"))
+ QLatin1String(".json")};
const QDir storageDir {m_session->dataFileStorage()->storageDir()};
if (!QFile::exists(storageDir.absoluteFilePath(m_dataFileName)))
QFile::rename(storageDir.absoluteFilePath(legacyFilename), storageDir.absoluteFilePath(m_dataFileName));
const QString legacyFilename = Utils::Fs::toValidFileName(m_url, QLatin1String("_")) + QLatin1String(".json");
const Path storageDir = m_session->dataFileStorage()->storageDir();
const Path dataFilePath = storageDir / m_dataFileName;
if (!dataFilePath.exists())
Utils::Fs::renameFile((storageDir / Path(legacyFilename)), dataFilePath);
m_iconPath = Utils::Fs::toUniformPath(storageDir.absoluteFilePath(uidHex + QLatin1String(".ico")));
m_iconPath = storageDir / Path(uidHex + QLatin1String(".ico"));
m_parser = new Private::Parser(m_lastBuildDate);
m_parser->moveToThread(m_session->workingThread());
@@ -139,7 +138,7 @@ void Feed::refresh()
m_downloadHandler = Net::DownloadManager::instance()->download(m_url);
connect(m_downloadHandler, &Net::DownloadHandler::finished, this, &Feed::handleDownloadFinished);
if (!QFile::exists(m_iconPath))
if (!m_iconPath.exists())
downloadIcon();
m_isLoading = true;
@@ -262,7 +261,7 @@ void Feed::handleParsingFinished(const RSS::Private::ParsingResult &result)
void Feed::load()
{
QFile file(m_session->dataFileStorage()->storageDir().absoluteFilePath(m_dataFileName));
QFile file {(m_session->dataFileStorage()->storageDir() / m_dataFileName).data()};
if (!file.exists())
{
@@ -278,7 +277,7 @@ void Feed::load()
else
{
LogMsg(tr("Couldn't read RSS Session data from %1. Error: %2")
.arg(m_dataFileName, file.errorString())
.arg(m_dataFileName.toString(), file.errorString())
, Log::WARNING);
}
}
@@ -500,7 +499,7 @@ int Feed::updateArticles(const QList<QVariantHash> &loadedArticles)
return newArticlesCount;
}
QString Feed::iconPath() const
Path Feed::iconPath() const
{
return m_iconPath;
}
@@ -549,8 +548,8 @@ void Feed::handleArticleRead(Article *article)
void Feed::cleanup()
{
Utils::Fs::forceRemove(m_session->dataFileStorage()->storageDir().absoluteFilePath(m_dataFileName));
Utils::Fs::forceRemove(m_iconPath);
Utils::Fs::removeFile(m_session->dataFileStorage()->storageDir() / m_dataFileName);
Utils::Fs::removeFile(m_iconPath);
}
void Feed::timerEvent(QTimerEvent *event)

View File

@@ -35,6 +35,7 @@
#include <QList>
#include <QUuid>
#include "base/path.h"
#include "rss_item.h"
class AsyncFileStorage;
@@ -79,7 +80,7 @@ namespace RSS
bool hasError() const;
bool isLoading() const;
Article *articleByGUID(const QString &guid) const;
QString iconPath() const;
Path iconPath() const;
QJsonValue toJsonValue(bool withData = false) const override;
@@ -122,8 +123,8 @@ namespace RSS
QHash<QString, Article *> m_articles;
QList<Article *> m_articlesByDate;
int m_unreadCount = 0;
QString m_iconPath;
QString m_dataFileName;
Path m_iconPath;
Path m_dataFileName;
QBasicTimer m_savingTimer;
bool m_dirty = false;
Net::DownloadHandler *m_downloadHandler = nullptr;

View File

@@ -49,9 +49,9 @@
#include "rss_item.h"
const int MsecsPerMin = 60000;
const QString ConfFolderName(QStringLiteral("rss"));
const QString DataFolderName(QStringLiteral("rss/articles"));
const QString FeedsFileName(QStringLiteral("feeds.json"));
const QString CONF_FOLDER_NAME(QStringLiteral("rss"));
const QString DATA_FOLDER_NAME(QStringLiteral("rss/articles"));
const QString FEEDS_FILE_NAME(QStringLiteral("feeds.json"));
using namespace RSS;
@@ -66,24 +66,22 @@ Session::Session()
Q_ASSERT(!m_instance); // only one instance is allowed
m_instance = this;
m_confFileStorage = new AsyncFileStorage(
Utils::Fs::expandPathAbs(specialFolderLocation(SpecialFolder::Config) + QLatin1Char('/') + ConfFolderName));
m_confFileStorage = new AsyncFileStorage(specialFolderLocation(SpecialFolder::Config) / Path(CONF_FOLDER_NAME));
m_confFileStorage->moveToThread(m_workingThread);
connect(m_workingThread, &QThread::finished, m_confFileStorage, &AsyncFileStorage::deleteLater);
connect(m_confFileStorage, &AsyncFileStorage::failed, [](const QString &fileName, const QString &errorString)
connect(m_confFileStorage, &AsyncFileStorage::failed, [](const Path &fileName, const QString &errorString)
{
Logger::instance()->addMessage(QString("Couldn't save RSS Session configuration in %1. Error: %2")
.arg(fileName, errorString), Log::WARNING);
LogMsg(tr("Couldn't save RSS Session configuration in %1. Error: %2")
.arg(fileName.toString(), errorString), Log::WARNING);
});
m_dataFileStorage = new AsyncFileStorage(
Utils::Fs::expandPathAbs(specialFolderLocation(SpecialFolder::Data) + QLatin1Char('/') + DataFolderName));
m_dataFileStorage = new AsyncFileStorage(specialFolderLocation(SpecialFolder::Data) / Path(DATA_FOLDER_NAME));
m_dataFileStorage->moveToThread(m_workingThread);
connect(m_workingThread, &QThread::finished, m_dataFileStorage, &AsyncFileStorage::deleteLater);
connect(m_dataFileStorage, &AsyncFileStorage::failed, [](const QString &fileName, const QString &errorString)
connect(m_dataFileStorage, &AsyncFileStorage::failed, [](const Path &fileName, const QString &errorString)
{
Logger::instance()->addMessage(QString("Couldn't save RSS Session data in %1. Error: %2")
.arg(fileName, errorString), Log::WARNING);
LogMsg(tr("Couldn't save RSS Session data in %1. Error: %2")
.arg(fileName.toString(), errorString), Log::WARNING);
});
m_itemsByPath.insert("", new Folder); // root folder
@@ -233,7 +231,7 @@ Item *Session::itemByPath(const QString &path) const
void Session::load()
{
QFile itemsFile(m_confFileStorage->storageDir().absoluteFilePath(FeedsFileName));
QFile itemsFile {(m_confFileStorage->storageDir() / Path(FEEDS_FILE_NAME)).data()};
if (!itemsFile.exists())
{
loadLegacy();
@@ -372,7 +370,8 @@ void Session::loadLegacy()
void Session::store()
{
m_confFileStorage->store(FeedsFileName, QJsonDocument(rootFolder()->toJsonValue().toObject()).toJson());
m_confFileStorage->store(Path(FEEDS_FILE_NAME)
, QJsonDocument(rootFolder()->toJsonValue().toObject()).toJson());
}
nonstd::expected<Folder *, QString> Session::prepareItemDest(const QString &path)