You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
o3de/Code/Tools/AssetBundler/source/models/RulesFileTableModel.cpp

311 lines
9.6 KiB
C++

/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <source/models/RulesFileTableModel.h>
#include <AzCore/std/smart_ptr/shared_ptr.h>
#include <AzCore/std/smart_ptr/make_shared.h>
#include <AzFramework/IO/LocalFileIO.h>
#include <AzFramework/StringFunc/StringFunc.h>
#include <QFileInfo>
#include <QFont>
namespace AssetBundler
{
RulesFileInfo::RulesFileInfo(const AZStd::string& absolutePath, const QString& fileName, bool loadFromFile)
: m_absolutePath(absolutePath)
, m_fileName(fileName)
{
AzFramework::StringFunc::Path::Normalize(m_absolutePath);
m_comparisonSteps = AZStd::make_shared<AzToolsFramework::AssetFileInfoListComparison>();
if (loadFromFile)
{
auto outcome = AzToolsFramework::AssetFileInfoListComparison::Load(m_absolutePath);
if (!outcome.IsSuccess())
{
AZ_Error("AssetBundler", false, outcome.GetError().c_str());
return;
}
m_comparisonSteps = AZStd::make_unique<AzToolsFramework::AssetFileInfoListComparison>(outcome.TakeValue());
QFileInfo fileInfo(m_absolutePath.c_str());
m_fileModificationTime = fileInfo.fileTime(QFileDevice::FileModificationTime);
}
else
{
m_fileModificationTime = QDateTime::currentDateTime();
}
}
bool RulesFileInfo::SaveRulesFile()
{
if (!m_comparisonSteps->Save(m_absolutePath))
{
return false;
}
m_hasUnsavedChanges = false;
m_fileModificationTime = QDateTime::currentDateTime();
return true;
}
RulesFileTableModel::RulesFileTableModel()
: AssetBundlerAbstractFileTableModel()
{
}
AZStd::vector<AZStd::string> RulesFileTableModel::CreateNewFiles(
const AZStd::string& absoluteFilePath,
const AzFramework::PlatformFlags& /*platforms*/,
const QString& /*project*/)
{
if (absoluteFilePath.empty())
{
AZ_Error(AssetBundler::AppWindowName, false, "Input file path is empty");
return {};
}
// Create a platform-specific file path
if (AZ::IO::FileIOBase::GetInstance()->Exists(absoluteFilePath.c_str()))
{
AZ_Error(AssetBundler::AppWindowName, false, "Cannot Create New File: (%s) already exists", absoluteFilePath.c_str());
return {};
}
// Get the file name without the extension for display purposes
AZStd::string fileName = absoluteFilePath;
AzToolsFramework::RemovePlatformIdentifier(fileName);
AzFramework::StringFunc::Path::GetFileName(fileName.c_str(), fileName);
// Create a Rules File and save it to disk
AZStd::string key = AssetBundler::GenerateKeyFromAbsolutePath(absoluteFilePath);
RulesFileInfoPtr newRulesFile = AZStd::make_shared<RulesFileInfo>(absoluteFilePath, QString(fileName.c_str()), false);
if (!newRulesFile->SaveRulesFile())
{
return {};
}
// Add the new file to the model
m_rulesFileInfoMap[key] = newRulesFile;
AddFileKey(key);
return { absoluteFilePath };
}
bool RulesFileTableModel::DeleteFile(const QModelIndex& index)
{
AZStd::string key = GetFileKey(index);
if (key.empty())
{
// Error has already been thrown
return false;
}
RulesFileInfoPtr rulesFileInfo = m_rulesFileInfoMap[key];
// Remove file from disk
if (AZ::IO::FileIOBase::GetInstance()->IsReadOnly(rulesFileInfo->m_absolutePath.c_str()))
{
AZ_Error(AssetBundler::AppWindowName, false, ReadOnlyFileErrorMessage, rulesFileInfo->m_absolutePath.c_str());
return false;
}
auto deleteResult = AZ::IO::FileIOBase::GetInstance()->Remove(rulesFileInfo->m_absolutePath.c_str());
if (!deleteResult)
{
AZ_Error(AssetBundler::AppWindowName, false,
"Unable to delete (%s). Result code: %u", rulesFileInfo->m_absolutePath.c_str(),
deleteResult.GetResultCode());
return false;
}
// Remove file from model
m_rulesFileInfoMap.erase(key);
RemoveFileKey(index);
return true;
}
void RulesFileTableModel::LoadFile(
const AZStd::string& absoluteFilePath,
const AZStd::string& /*projectName*/,
bool /*isDefaultFile*/)
{
// Get the file name without the extension for display purposes
AZStd::string fileName(absoluteFilePath);
AzFramework::StringFunc::Path::GetFileName(fileName.c_str(), fileName);
// Read the Rules file into memory and store it
AZStd::string key = AssetBundler::GenerateKeyFromAbsolutePath(absoluteFilePath);
auto fileInfoIt = m_rulesFileInfoMap.find(key);
if (fileInfoIt != m_rulesFileInfoMap.end() && fileInfoIt->second->m_hasUnsavedChanges)
{
AZ_Warning(AssetBundler::AppWindowName, false,
"Rules File %s has unsaved changes and couldn't be reloaded", absoluteFilePath.c_str());
return;
}
m_rulesFileInfoMap[key] = AZStd::make_shared<RulesFileInfo>(absoluteFilePath, QString(fileName.c_str()), true);
AddFileKey(key);
}
bool RulesFileTableModel::WriteToDisk(const AZStd::string& key)
{
auto rulesFileIt = m_rulesFileInfoMap.find(key);
return rulesFileIt != m_rulesFileInfoMap.end() && rulesFileIt->second->SaveRulesFile();
}
AZStd::string RulesFileTableModel::GetFileAbsolutePath(const QModelIndex& index) const
{
RulesFileInfoPtr rulesFileInfo = GetRulesFileInfoPtr(index);
if (!rulesFileInfo)
{
return AZStd::string();
}
return rulesFileInfo->m_absolutePath;
}
int RulesFileTableModel::GetFileNameColumnIndex() const
{
return Column::ColumnFileName;
}
int RulesFileTableModel::GetTimeStampColumnIndex() const
{
return Column::ColumnFileModificationTime;
}
AZStd::shared_ptr<AzToolsFramework::AssetFileInfoListComparison> RulesFileTableModel::GetComparisonSteps(const QModelIndex& index) const
{
RulesFileInfoPtr rulesFileInfo = GetRulesFileInfoPtr(index);
if (!rulesFileInfo)
{
return nullptr;
}
return rulesFileInfo->m_comparisonSteps;
}
bool RulesFileTableModel::MarkFileChanged(const QModelIndex& index)
{
AZStd::string key = GetFileKey(index);
if (key.empty())
{
// Error has already been thrown
return false;
}
m_rulesFileInfoMap[key]->m_hasUnsavedChanges = true;
// Update display so the user knows there are unsaved changes
m_keysWithUnsavedChanges.emplace(key);
QModelIndex changedIndex = QAbstractTableModel::index(index.row(), Column::ColumnFileName);
emit dataChanged(changedIndex, changedIndex, { Qt::DisplayRole, Qt::FontRole });
return true;
}
int RulesFileTableModel::columnCount(const QModelIndex& parent) const
{
return parent.isValid() ? 0 : Column::Max;
}
QVariant RulesFileTableModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (role == Qt::DisplayRole && orientation == Qt::Horizontal)
{
switch (section)
{
case Column::ColumnFileName:
return QString(tr("Name"));
case Column::ColumnFileModificationTime:
return QString(tr("Modification Time"));
default:
break;
}
}
return QVariant();
}
QVariant RulesFileTableModel::data(const QModelIndex& index, int role) const
{
AZStd::string key = GetFileKey(index);
if (key.empty())
{
return QVariant();
}
RulesFileInfoPtr rulesFileInfo = m_rulesFileInfoMap.at(key);
int col = index.column();
bool hasUnsavedChanges = rulesFileInfo->m_hasUnsavedChanges;
switch (role)
{
case Qt::DisplayRole:
[[fallthrough]];
case SortRole:
{
if (col == Column::ColumnFileName)
{
QString displayName = rulesFileInfo->m_fileName;
if (hasUnsavedChanges)
{
displayName.append("*");
}
return displayName;
}
else if (col == Column::ColumnFileModificationTime)
{
if (role == SortRole)
{
return rulesFileInfo->m_fileModificationTime;
}
else
{
return rulesFileInfo->m_fileModificationTime.toString(DateTimeFormat);
}
}
break;
}
case Qt::FontRole:
{
if (col == Column::ColumnFileName && hasUnsavedChanges)
{
QFont boldFont;
boldFont.setBold(true);
return boldFont;
}
break;
}
default:
break;
}
return QVariant();
}
RulesFileInfoPtr RulesFileTableModel::GetRulesFileInfoPtr(const QModelIndex& index) const
{
AZStd::string key = GetFileKey(index);
if (key.empty())
{
return nullptr;
}
return m_rulesFileInfoMap.at(key);
}
} // namespace AssetBundler