Skip to content

Commit

Permalink
Merge pull request #601 from IENT/CreateDataSource
Browse files Browse the repository at this point in the history
Move dataSource to new folder
  • Loading branch information
ChristianFeldmann authored Dec 4, 2024
2 parents 5e768f8 + 7d476f8 commit c8a538b
Show file tree
Hide file tree
Showing 13 changed files with 201 additions and 82 deletions.
25 changes: 25 additions & 0 deletions YUViewLib/src/common/Functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@
#include <charconv>
#include <string_view>

#include <QDir>
#include <QFileInfo>
#include <QThread>

namespace functions
Expand Down Expand Up @@ -120,6 +122,29 @@ QStringList getThemeColors(QString themeName)
return QStringList();
}

// If you are loading a playlist and you have an absolute path and a relative path, this function
// will return the absolute path (if a file with that absolute path exists) or convert the relative
// path to an absolute one and return that (if that file exists). If neither exists the empty string
// is returned.
QString getAbsPathFromAbsAndRel(const QString &currentPath,
const QString &absolutePath,
const QString &relativePath)
{
QFileInfo checkAbsoluteFile(absolutePath);
if (checkAbsoluteFile.exists())
return absolutePath;

QFileInfo plFileInfo(currentPath);
auto combinePath = QDir(plFileInfo.path()).filePath(relativePath);
QFileInfo checkRelativeFile(combinePath);
if (checkRelativeFile.exists() && checkRelativeFile.isFile())
{
return QDir::cleanPath(combinePath);
}

return {};
}

QString formatDataSize(double size, bool isBits)
{
unsigned divCounter = 0;
Expand Down
7 changes: 5 additions & 2 deletions YUViewLib/src/common/Functions.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,18 @@ QString getThemeFileName(QString themeName);
// The values to replace them by are returned in this order.
QStringList getThemeColors(QString themeName);

QString getAbsPathFromAbsAndRel(const QString &currentPath,
const QString &absolutePath,
const QString &relativePath);

// Format the data size as a huma readable string. If isBits is set, assumes bits, oterwise bytes.
// From Qt 5.10 there is a built in function (QLocale::formattedDataSize). But we want to be 5.9
// compatible.
QString formatDataSize(double size, bool isBits = false);

QStringList toQStringList(const std::vector<std::string> &stringVec);

template <size_t N>
QStringList toQStringList(const std::array<std::string_view, N> &stringArray)
template <size_t N> QStringList toQStringList(const std::array<std::string_view, N> &stringArray)
{
QStringList list;
for (const auto &s : stringArray)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,37 @@

#include "DataSourceLocalFile.h"

namespace filesource
#ifdef Q_OS_WIN
#include <windows.h>
#endif

namespace datasource
{

namespace
{

std::optional<std::filesystem::file_time_type>
getLastWriteTime(const std::filesystem::path &filePath) noexcept
{
try
{
return {std::filesystem::last_write_time(filePath)};
}
catch (const std::exception &e)
{
return {};
}
}

} // namespace

DataSourceLocalFile::DataSourceLocalFile(const std::filesystem::path &filePath)
{
this->file.open(filePath.string(), std::ios_base::in | std::ios_base::binary);
this->filePath = filePath;
this->file.open(this->filePath.string(), std::ios_base::in | std::ios_base::binary);
if (this->isOk())
this->path = filePath;
this->lastWriteTime = getLastWriteTime(this->filePath);
}

std::vector<InfoItem> DataSourceLocalFile::getInfoList() const
Expand All @@ -49,8 +72,8 @@ std::vector<InfoItem> DataSourceLocalFile::getInfoList() const

std::vector<InfoItem> infoList;
infoList.push_back(
InfoItem({"File Path", this->path.string(), "The absolute path of the local file"}));
if (const auto size = this->fileSize())
InfoItem({"File Path", this->filePath.string(), "The absolute path of the local file"}));
if (const auto size = this->getFileSize())
infoList.push_back(InfoItem({"File Size", std::to_string(*size)}));

return infoList;
Expand All @@ -68,11 +91,52 @@ bool DataSourceLocalFile::isOk() const
return true;
}

std::int64_t DataSourceLocalFile::position() const
std::int64_t DataSourceLocalFile::getPosition() const
{
return this->filePosition;
}

void DataSourceLocalFile::clearFileCache()
{
if (!this->isOk())
return;

#ifdef Q_OS_WIN
// Currently, we only support this on windows. But this is only used in performance testing.
// We will close the QFile, open it using the FILE_FLAG_NO_BUFFERING flags, close it and reopen
// the QFile. Suggested:
// http://stackoverflow.com/questions/478340/clear-file-cache-to-repeat-performance-testing
const std::lock_guard<std::mutex> readLock(this->readingMutex);
this->file.close();

LPCWSTR file = this->filePath.wstring().c_str();
HANDLE hFile =
CreateFile(file, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, NULL);
CloseHandle(hFile);

this->file.open(this->filePath.string(), std::ios_base::in | std::ios_base::binary);
#endif
}

bool DataSourceLocalFile::wasSourceModified() const
{
if (!this->isOk())
return false;

if (const auto newTime = getLastWriteTime(this->filePath))
return *newTime > *this->lastWriteTime;

return false;
}

void DataSourceLocalFile::reloadAndResetDataSource()
{
this->file.close();
this->file.open(this->filePath.string(), std::ios_base::in | std::ios_base::binary);
if (this->isOk())
this->lastWriteTime = getLastWriteTime(this->filePath);
}

bool DataSourceLocalFile::seek(const std::int64_t pos)
{
if (!this->isOk())
Expand All @@ -90,11 +154,13 @@ std::int64_t DataSourceLocalFile::read(ByteVector &buffer, const std::int64_t nr
if (!this->isOk())
return 0;

const auto usize = static_cast<size_t>(nrBytes);
const std::lock_guard<std::mutex> readLock(this->readingMutex);

const auto size = static_cast<size_t>(nrBytes);
if (static_cast<std::int64_t>(buffer.size()) < nrBytes)
buffer.resize(usize);
buffer.resize(size);

this->file.read(reinterpret_cast<char *>(buffer.data()), usize);
this->file.read(reinterpret_cast<char *>(buffer.data()), size);

const auto bytesRead = this->file.gcount();
buffer.resize(bytesRead);
Expand All @@ -103,18 +169,18 @@ std::int64_t DataSourceLocalFile::read(ByteVector &buffer, const std::int64_t nr
return static_cast<std::int64_t>(bytesRead);
}

std::optional<std::int64_t> DataSourceLocalFile::fileSize() const
std::optional<std::int64_t> DataSourceLocalFile::getFileSize() const
{
if (this->path.empty())
if (!this->isOk())
return {};

const auto size = std::filesystem::file_size(this->path);
const auto size = std::filesystem::file_size(this->filePath);
return static_cast<std::int64_t>(size);
}

[[nodiscard]] std::filesystem::path DataSourceLocalFile::filePath() const
[[nodiscard]] std::filesystem::path DataSourceLocalFile::getFilePath() const
{
return this->path;
return this->filePath;
}

} // namespace filesource
} // namespace datasource
Original file line number Diff line number Diff line change
Expand Up @@ -36,32 +36,41 @@

#include <filesystem>
#include <fstream>
#include <mutex>

namespace filesource
namespace datasource
{

class DataSourceLocalFile : public IDataSource
{
public:
DataSourceLocalFile() = delete;
DataSourceLocalFile(const std::filesystem::path &filePath);

[[nodiscard]] std::vector<InfoItem> getInfoList() const override;
[[nodiscard]] bool atEnd() const override;
[[nodiscard]] bool isOk() const override;
[[nodiscard]] std::int64_t position() const override;
[[nodiscard]] std::int64_t getPosition() const override;

void clearFileCache() override;
[[nodiscard]] bool wasSourceModified() const override;
void reloadAndResetDataSource() override;

[[nodiscard]] bool seek(const std::int64_t pos) override;
[[nodiscard]] std::int64_t read(ByteVector &buffer, const std::int64_t nrBytes) override;

[[nodiscard]] std::optional<std::int64_t> fileSize() const;
[[nodiscard]] std::filesystem::path filePath() const;
[[nodiscard]] std::optional<std::int64_t> getFileSize() const;
[[nodiscard]] std::filesystem::path getFilePath() const;

protected:
std::filesystem::path path{};
bool isFileOpened{};
std::filesystem::path filePath{};
std::optional<std::filesystem::file_time_type> lastWriteTime{};
bool isFileOpened{};

std::ifstream file{};
std::int64_t filePosition{};

std::mutex readingMutex;
};

} // namespace filesource
} // namespace datasource
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
#include <common/InfoItemAndData.h>
#include <common/Typedef.h>

namespace filesource
namespace datasource
{

/* The data source interface defines a something that can provide data.
Expand All @@ -48,12 +48,16 @@ class IDataSource
[[nodiscard]] virtual std::vector<InfoItem> getInfoList() const = 0;
[[nodiscard]] virtual bool atEnd() const = 0;
[[nodiscard]] virtual bool isOk() const = 0;
[[nodiscard]] virtual std::int64_t position() const = 0;
[[nodiscard]] virtual std::int64_t getPosition() const = 0;

virtual void clearFileCache() = 0;
[[nodiscard]] virtual bool wasSourceModified() const = 0;
virtual void reloadAndResetDataSource() = 0;

explicit operator bool() const { return this->isOk(); }

[[nodiscard]] virtual bool seek(const std::int64_t pos) = 0;
[[nodiscard]] virtual std::int64_t read(ByteVector &buffer, const std::int64_t nrBytes) = 0;
};

} // namespace filesource
} // namespace datasource
23 changes: 0 additions & 23 deletions YUViewLib/src/filesource/FileSource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,29 +159,6 @@ std::string FileSource::getAbsoluteFilePath() const
return this->isFileOpened ? this->fullFilePath.string() : "";
}

// If you are loading a playlist and you have an absolute path and a relative path, this function
// will return the absolute path (if a file with that absolute path exists) or convert the relative
// path to an absolute one and return that (if that file exists). If neither exists the empty string
// is returned.
QString FileSource::getAbsPathFromAbsAndRel(const QString &currentPath,
const QString &absolutePath,
const QString &relativePath)
{
QFileInfo checkAbsoluteFile(absolutePath);
if (checkAbsoluteFile.exists())
return absolutePath;

QFileInfo plFileInfo(currentPath);
auto combinePath = QDir(plFileInfo.path()).filePath(relativePath);
QFileInfo checkRelativeFile(combinePath);
if (checkRelativeFile.exists() && checkRelativeFile.isFile())
{
return QDir::cleanPath(combinePath);
}

return {};
}

bool FileSource::getAndResetFileChangedFlag()
{
bool b = this->fileChanged;
Expand Down
4 changes: 0 additions & 4 deletions YUViewLib/src/filesource/FileSource.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,10 +97,6 @@ class FileSource : public QObject
void readBytes(byteArrayAligned &data, int64_t startPos, int64_t nrBytes);
#endif

static QString getAbsPathFromAbsAndRel(const QString &currentPath,
const QString &absolutePath,
const QString &relativePath);

void updateFileWatchSetting();
void clearFileCache();

Expand Down
4 changes: 2 additions & 2 deletions YUViewLib/src/playlistitem/playlistItemCompressedVideo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ playlistItemCompressedVideo::playlistItemCompressedVideo(const QString &compress
{
// Open file
DEBUG_COMPRESSED("playlistItemCompressedVideo::playlistItemCompressedVideo Open annexB file");
const auto filePath = std::filesystem::path(compressedFilePath.toStdString());
const auto filePath = std::filesystem::path(compressedFilePath.toStdString());
this->inputFileAnnexBLoading = std::make_unique<FileSourceAnnexBFile>(filePath);
if (this->cachingEnabled)
this->inputFileAnnexBCaching = std::make_unique<FileSourceAnnexBFile>(filePath);
Expand Down Expand Up @@ -430,7 +430,7 @@ playlistItemCompressedVideo::newPlaylistItemCompressedVideo(const YUViewDomEleme
int displaySignal = root.findChildValue("displayComponent").toInt();

// check if file with absolute path exists, otherwise check relative path
auto filePath = FileSource::getAbsPathFromAbsAndRel(playlistFilePath, absolutePath, relativePath);
const auto filePath = getAbsPathFromAbsAndRel(playlistFilePath, absolutePath, relativePath);
if (filePath.isEmpty())
return nullptr;

Expand Down
4 changes: 3 additions & 1 deletion YUViewLib/src/playlistitem/playlistItemImageFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include <QUrl>

#include <common/Formatting.h>
#include <common/Functions.h>
#include <common/FunctionsGui.h>
#include <filesource/FileSource.h>

Expand Down Expand Up @@ -109,7 +110,8 @@ playlistItemImageFile::newplaylistItemImageFile(const YUViewDomElement &root,
auto relativePath = root.findChildValue("relativePath");

// check if file with absolute path exists, otherwise check relative path
auto filePath = FileSource::getAbsPathFromAbsAndRel(playlistFilePath, absolutePath, relativePath);
const auto filePath =
functions::getAbsPathFromAbsAndRel(playlistFilePath, absolutePath, relativePath);
if (filePath.isEmpty())
return nullptr;

Expand Down
5 changes: 3 additions & 2 deletions YUViewLib/src/playlistitem/playlistItemImageFileSequence.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include <QUrl>

#include <common/Formatting.h>
#include <common/Functions.h>
#include <common/FunctionsGui.h>
#include <filesource/FileSource.h>

Expand Down Expand Up @@ -231,8 +232,8 @@ playlistItemImageFileSequence::newplaylistItemImageFileSequence(const YUViewDomE
break;

// check if file with absolute path exists, otherwise check relative path
QString filePath =
FileSource::getAbsPathFromAbsAndRel(playlistFilePath, absolutePath, relativePath);
const auto filePath =
functions::getAbsPathFromAbsAndRel(playlistFilePath, absolutePath, relativePath);

// Check if the file exists
QFileInfo fileInfo(filePath);
Expand Down
3 changes: 2 additions & 1 deletion YUViewLib/src/playlistitem/playlistItemRawFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -520,7 +520,8 @@ playlistItemRawFile *playlistItemRawFile::newplaylistItemRawFile(const YUViewDom
auto type = root.findChildValue("type");

// check if file with absolute path exists, otherwise check relative path
auto filePath = FileSource::getAbsPathFromAbsAndRel(playlistFilePath, absolutePath, relativePath);
const auto filePath =
functions::getAbsPathFromAbsAndRel(playlistFilePath, absolutePath, relativePath);
if (filePath.isEmpty())
return nullptr;

Expand Down
Loading

0 comments on commit c8a538b

Please sign in to comment.