BundleFileListModel.cpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <source/models/BundleFileListModel.h>
  9. #include <AzFramework/IO/LocalFileIO.h>
  10. #include <AzToolsFramework/AssetBundle/AssetBundleComponent.h>
  11. #include <source/utils/utils.h>
  12. #include <QFileInfo>
  13. namespace AssetBundler
  14. {
  15. BundleFileInfo::BundleFileInfo(const AZStd::string& absolutePath)
  16. : m_absolutePath(absolutePath)
  17. , m_compressedSize(0u)
  18. {
  19. AzFramework::StringFunc::Path::Normalize(m_absolutePath);
  20. AZStd::string fileNameStr;
  21. if (AzFramework::StringFunc::Path::GetFileName(m_absolutePath.c_str(), fileNameStr))
  22. {
  23. m_fileName = QString(fileNameStr.c_str());
  24. }
  25. else
  26. {
  27. AZ_Error("AssetBundler", false, "Failed to get file name from %s", m_absolutePath.c_str());
  28. }
  29. // Modification time will either give us the time the file was last overwritten
  30. // (or the time it was created if it has never been overwritten)
  31. QFileInfo fileInfo(m_absolutePath.c_str());
  32. m_fileCreationTime = fileInfo.fileTime(QFileDevice::FileModificationTime);
  33. }
  34. BundleFileListModel::BundleFileListModel()
  35. : AssetBundlerAbstractFileTableModel()
  36. {
  37. }
  38. bool BundleFileListModel::DeleteFile(const QModelIndex& index)
  39. {
  40. AZStd::string fileKey = GetFileKey(index);
  41. if (fileKey.empty())
  42. {
  43. // Error has already been thrown
  44. return false;
  45. }
  46. auto bundleFileInfoIt = m_bundleFileInfoMap.find(fileKey);
  47. if (bundleFileInfoIt == m_bundleFileInfoMap.end())
  48. {
  49. AZ_Error(AssetBundler::AppWindowName, false, "Unable to find Bundle Info with key ( %s )", fileKey.c_str());
  50. return false;
  51. }
  52. BundleFileInfoPtr bundleFileInfo = bundleFileInfoIt->second;
  53. // Remove file from disk
  54. const char* absolutePath = bundleFileInfo->m_absolutePath.c_str();
  55. if (AZ::IO::FileIOBase::GetInstance()->Exists(absolutePath))
  56. {
  57. if (AZ::IO::FileIOBase::GetInstance()->IsReadOnly(absolutePath))
  58. {
  59. AZ_Error(AssetBundler::AppWindowName, false, ReadOnlyFileErrorMessage, absolutePath);
  60. return false;
  61. }
  62. auto deleteResult = AZ::IO::FileIOBase::GetInstance()->Remove(absolutePath);
  63. if (!deleteResult)
  64. {
  65. AZ_Error(AssetBundler::AppWindowName, false,
  66. "Unable to delete (%s). Result code: %u", absolutePath, deleteResult.GetResultCode());
  67. return false;
  68. }
  69. }
  70. // Remove file from Model
  71. m_bundleFileInfoMap.erase(fileKey);
  72. RemoveFileKey(index);
  73. return true;
  74. }
  75. int BundleFileListModel::columnCount(const QModelIndex& parent) const
  76. {
  77. return parent.isValid() ? 0 : Column::Max;
  78. }
  79. QVariant BundleFileListModel::headerData(int section, Qt::Orientation orientation, int role) const
  80. {
  81. if (role == Qt::DisplayRole && orientation == Qt::Horizontal)
  82. {
  83. switch (section)
  84. {
  85. case Column::ColumnFileName:
  86. return QString(tr("Name"));
  87. case Column::ColumnFileCreationTime:
  88. return QString(tr("Creation Time"));
  89. default:
  90. break;
  91. }
  92. }
  93. return QVariant();
  94. }
  95. QVariant BundleFileListModel::data(const QModelIndex& index, int role) const
  96. {
  97. auto bundleInfoOutcome = GetBundleInfo(index);
  98. if (!bundleInfoOutcome.IsSuccess())
  99. {
  100. return QVariant();
  101. }
  102. int col = index.column();
  103. switch (role)
  104. {
  105. case Qt::DisplayRole:
  106. [[fallthrough]];
  107. case SortRole:
  108. {
  109. if (col == Column::ColumnFileName)
  110. {
  111. return bundleInfoOutcome.GetValue()->m_fileName;
  112. }
  113. else if (col == Column::ColumnFileCreationTime)
  114. {
  115. if (role == SortRole)
  116. {
  117. return bundleInfoOutcome.GetValue()->m_fileCreationTime;
  118. }
  119. else
  120. {
  121. return bundleInfoOutcome.GetValue()->m_fileCreationTime.toString(DateTimeFormat);
  122. }
  123. }
  124. }
  125. default:
  126. break;
  127. }
  128. return QVariant();
  129. }
  130. AZStd::string BundleFileListModel::GetFileAbsolutePath(const QModelIndex& index) const
  131. {
  132. AZStd::string key = GetFileKey(index);
  133. if (key.empty())
  134. {
  135. // Error has already been thrown
  136. return key;
  137. }
  138. return m_bundleFileInfoMap.at(key)->m_absolutePath;
  139. }
  140. int BundleFileListModel::GetFileNameColumnIndex() const
  141. {
  142. return Column::ColumnFileName;
  143. }
  144. int BundleFileListModel::GetTimeStampColumnIndex() const
  145. {
  146. return Column::ColumnFileCreationTime;
  147. }
  148. void BundleFileListModel::LoadFile(
  149. const AZStd::string& absoluteFilePath,
  150. const AZStd::string& /*projectName*/,
  151. bool /*isDefaultFile*/)
  152. {
  153. AZStd::string key = AssetBundler::GenerateKeyFromAbsolutePath(absoluteFilePath);
  154. BundleFileInfo* newInfo = new BundleFileInfo(absoluteFilePath);
  155. QFile bundleFile(absoluteFilePath.c_str());
  156. if (bundleFile.open(QIODevice::ReadOnly))
  157. {
  158. newInfo->m_compressedSize = bundleFile.size();
  159. bundleFile.close();
  160. }
  161. else
  162. {
  163. AZ_Error("AssetBundler", false, "Failed to open file at %s", absoluteFilePath.c_str());
  164. }
  165. auto manifest = AzToolsFramework::AssetBundleComponent::GetManifestFromBundle(absoluteFilePath);
  166. if (manifest != nullptr)
  167. {
  168. for (auto& bundleName : manifest->GetDependentBundleNames())
  169. {
  170. newInfo->m_relatedBundles.push_back(bundleName.c_str());
  171. }
  172. }
  173. else
  174. {
  175. AZ_Error("AssetBundler", false, "Failed to get manifest from bundle at %s", absoluteFilePath.c_str());
  176. }
  177. m_bundleFileInfoMap[key].reset(newInfo);
  178. // Add it to the list that gets displayed by AssetBundlerAbstractFileTableModel. Make sure that
  179. // AddFileKey is called after m_bundleFileInfoMap is reset since the filterAcceptsRow funtion
  180. // of the filter model will be called when a new row is inserted and it could cause a crash
  181. // without valid data being set
  182. AddFileKey(key);
  183. }
  184. AZ::Outcome<BundleFileInfoPtr, void> BundleFileListModel::GetBundleInfo(const QModelIndex& index) const
  185. {
  186. AZStd::string key = GetFileKey(index);
  187. if (key.empty())
  188. {
  189. // Error has already been thrown
  190. return AZ::Failure();
  191. }
  192. if (m_bundleFileInfoMap.find(key) != m_bundleFileInfoMap.end())
  193. {
  194. return AZ::Success(m_bundleFileInfoMap.at(key));
  195. }
  196. else
  197. {
  198. AZ_Error(AssetBundler::AppWindowName, false, "Cannot find Bundle File Info");
  199. return AZ::Failure();
  200. }
  201. }
  202. }