Files
oak-editor/app/common/filefunctions.cpp
T
itsmattkc d7c5ac4b44 implement entire project in nodes
Project items are now represented directly in nodes opening up more versatility and possibilities. This is the first iteration of this and will be buggy. Need to test thoroughly.
2021-02-15 21:31:57 +11:00

244 lines
6.1 KiB
C++

/***
Olive - Non-Linear Video Editor
Copyright (C) 2020 Olive Team
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
#include "filefunctions.h"
#include <QCoreApplication>
#include <QCryptographicHash>
#include <QDateTime>
#include <QDir>
#include <QFileInfo>
#include <QStandardPaths>
#include "config/config.h"
namespace olive {
QString FileFunctions::GetUniqueFileIdentifier(const QString &filename)
{
QFileInfo info(filename);
if (!info.exists()) {
return QString();
}
QCryptographicHash hash(QCryptographicHash::Sha1);
hash.addData(info.absoluteFilePath().toUtf8());
hash.addData(QString::number(info.lastModified().toMSecsSinceEpoch()).toUtf8());
QByteArray result = hash.result();
return QString(result.toHex());
}
QString FileFunctions::GetConfigurationLocation()
{
if (IsPortable()) {
return GetApplicationPath();
} else {
QString s = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
QDir(s).mkpath(".");
return s;
}
}
bool FileFunctions::IsPortable()
{
return QFileInfo::exists(QDir(GetApplicationPath()).filePath("portable"));
}
QString FileFunctions::GetApplicationPath()
{
return QCoreApplication::applicationDirPath();
}
QString FileFunctions::GetTempFilePath()
{
QString temp_path = QDir(QDir(QStandardPaths::writableLocation(QStandardPaths::TempLocation))
.filePath(QCoreApplication::organizationName()))
.filePath(QCoreApplication::applicationName());
// Ensure it exists
QDir(temp_path).mkpath(".");
return temp_path;
}
bool FileFunctions::CanCopyDirectoryWithoutOverwriting(const QString& source, const QString& dest)
{
QFileInfoList info_list = QDir(source).entryInfoList();
foreach (const QFileInfo& info, info_list) {
// QDir::NoDotAndDotDot continues to not work, so we have to check manually
if (info.fileName() == QStringLiteral(".") || info.fileName() == QStringLiteral("..")) {
continue;
}
QString dest_equivalent = QDir(dest).filePath(info.fileName());
if (info.isDir()) {
if (!CanCopyDirectoryWithoutOverwriting(info.absoluteFilePath(), dest_equivalent)) {
return false;
}
} else if (QFileInfo::exists(dest_equivalent)) {
return false;
}
}
return true;
}
void FileFunctions::CopyDirectory(const QString &source, const QString &dest, bool overwrite)
{
QDir d(source);
if (!d.exists()) {
qCritical() << "Failed to copy directory, source" << source << "didn't exist";
return;
}
QDir dest_dir(dest);
if (!dest_dir.mkpath(QStringLiteral("."))) {
qCritical() << "Failed to create destination directory" << dest;
return;
}
QFileInfoList l = d.entryInfoList();
foreach (const QFileInfo& info, l) {
// QDir::NoDotAndDotDot continues to not work, so we have to check manually
if (info.fileName() == QStringLiteral(".") || info.fileName() == QStringLiteral("..")) {
continue;
}
QString dest_file_path = dest_dir.filePath(info.fileName());
if (info.isDir()) {
// Copy dir
CopyDirectory(info.absoluteFilePath(), dest_file_path, overwrite);
} else {
// Copy file
if (overwrite && QFile::exists(dest_file_path)) {
QFile::remove(dest_file_path);
}
QFile::copy(info.absoluteFilePath(), dest_file_path);
}
}
}
bool FileFunctions::DirectoryIsValid(const QString &dir, bool try_to_create)
{
// Empty string is invalid
if (dir.isEmpty()) {
return false;
}
QDir d(dir);
// If directory already exists, this is valid
if (d.exists()) {
return true;
}
// If we can create and creation is successful, this is valid
if (try_to_create && d.mkpath(".")) {
return true;
}
// Otherwise, invalid
return false;
}
QString FileFunctions::EnsureFilenameExtension(QString fn, const QString &extension)
{
// No-op if either input is empty
if (!fn.isEmpty() && !extension.isEmpty()) {
QString extension_with_dot;
extension_with_dot.append('.');
extension_with_dot.append(extension);
if (!fn.endsWith(extension_with_dot, Qt::CaseInsensitive)) {
fn.append(extension_with_dot);
}
}
return fn;
}
QString FileFunctions::ReadFileAsString(const QString &filename)
{
QFile f(filename);
QString file_data;
if (f.open(QFile::ReadOnly | QFile::Text)) {
QTextStream text_stream(&f);
file_data = text_stream.readAll();
f.close();
}
return file_data;
}
QString FileFunctions::GetSafeTemporaryFilename(const QString &original)
{
int counter = 0;
QFileInfo original_info(original);
QString basename = original_info.baseName();
QString complete_suffix = original_info.completeSuffix();
// If we have a complete suffix, make sure there's a period in it
if (!complete_suffix.isEmpty()) {
complete_suffix.prepend('.');
}
QString temp_abs_path;
do {
temp_abs_path = original_info.dir().filePath(
QStringLiteral("%1.tmp%2%3").arg(basename,
QString::number(counter),
complete_suffix));
counter++;
} while (QFileInfo::exists(temp_abs_path));
return temp_abs_path;
}
bool FileFunctions::RenameFileAllowOverwrite(const QString &from, const QString &to)
{
if (QFileInfo::exists(to) && !QFile::remove(to)) {
qCritical() << "Couldn't remove existing file" << to << "for overwrite";
return false;
}
// By this point, we can assume `to` either never existed or has now been deleted
if (!QFile::rename(from, to)) {
qCritical() << "Failed to rename file" << from << "to" << to;
return false;
}
return true;
}
}