3
0

SeedListTableModel.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  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/SeedListTableModel.h>
  9. #include <source/utils/utils.h>
  10. #include <AzCore/Outcome/Outcome.h>
  11. #include <AzCore/std/smart_ptr/make_shared.h>
  12. #include <AzFramework/IO/LocalFileIO.h>
  13. #include <AzFramework/StringFunc/StringFunc.h>
  14. #include <AzToolsFramework/AssetCatalog/PlatformAddressedAssetCatalog.h>
  15. #include <QFont>
  16. namespace AssetBundler
  17. {
  18. //////////////////////////////////////////////////////////////////////////////////////////////////
  19. // AdditionalSeedInfo
  20. //////////////////////////////////////////////////////////////////////////////////////////////////
  21. AdditionalSeedInfo::AdditionalSeedInfo(const QString& relativePath, const QString& platformList)
  22. : m_relativePath(relativePath)
  23. , m_platformList(platformList)
  24. {
  25. }
  26. //////////////////////////////////////////////////////////////////////////////////////////////////
  27. // SeedListTableModel
  28. //////////////////////////////////////////////////////////////////////////////////////////////////
  29. SeedListTableModel::SeedListTableModel(
  30. QObject* parent,
  31. const AZStd::string& absolutePath,
  32. const AZStd::vector<AZStd::string>& defaultSeeds,
  33. const AzFramework::PlatformFlags& platforms)
  34. : QAbstractTableModel(parent)
  35. , m_errorImage(QStringLiteral(":/stylesheet/img/logging/error.svg"))
  36. {
  37. m_seedListManager.reset(new AzToolsFramework::AssetSeedManager());
  38. if (absolutePath.empty() && defaultSeeds.empty())
  39. {
  40. return;
  41. }
  42. if (!defaultSeeds.empty())
  43. {
  44. for (const AZStd::string& seed : defaultSeeds)
  45. {
  46. m_seedListManager->AddSeedAssetForValidPlatforms(seed, platforms);
  47. }
  48. m_isFileOnDisk = false;
  49. }
  50. else
  51. {
  52. m_seedListManager->Load(absolutePath);
  53. }
  54. AZ::Data::AssetInfo assetInfo;
  55. QString platformList;
  56. for (const auto& seed : m_seedListManager->GetAssetSeedList())
  57. {
  58. assetInfo = AzToolsFramework::AssetSeedManager::GetAssetInfoById(
  59. seed.m_assetId,
  60. AzFramework::PlatformHelper::GetPlatformIndicesInterpreted(seed.m_platformFlags)[0],
  61. absolutePath,
  62. seed.m_assetRelativePath);
  63. platformList = QString(m_seedListManager->GetReadablePlatformList(seed).c_str());
  64. m_additionalSeedInfoMap[seed.m_assetId].reset(new AdditionalSeedInfo(assetInfo.m_relativePath.c_str(), platformList));
  65. // Missing assets still show up in the seed list view. Display An error message where the blank filename would otherwise be.
  66. if (!assetInfo.m_assetId.IsValid())
  67. {
  68. const AZStd::string assetIdStr(seed.m_assetId.ToString<AZStd::string>());
  69. m_additionalSeedInfoMap[seed.m_assetId]->m_errorMessage = tr("Missing asset: path hint '%1', asset ID '%2'").arg(seed.m_assetRelativePath.c_str()).arg(assetIdStr.c_str());
  70. }
  71. }
  72. }
  73. AZ::Outcome<AzFramework::PlatformFlags, void> SeedListTableModel::GetSeedPlatforms(const QModelIndex& index) const
  74. {
  75. auto seedOutcome = GetSeedInfo(index);
  76. if (!seedOutcome.IsSuccess())
  77. {
  78. // Error has already been thrown
  79. return AZ::Failure();
  80. }
  81. return AZ::Success(seedOutcome.GetValue().get().m_platformFlags);
  82. }
  83. bool SeedListTableModel::Save(const AZStd::string& absolutePath)
  84. {
  85. if (!HasUnsavedChanges())
  86. {
  87. // There are no changes, so there is nothing to save
  88. return true;
  89. }
  90. SetHasUnsavedChanges(!m_seedListManager->Save(absolutePath));
  91. return !HasUnsavedChanges();
  92. }
  93. bool SeedListTableModel::SetSeedPlatforms(const QModelIndex& index, const AzFramework::PlatformFlags& platforms)
  94. {
  95. auto seedOutcome = GetSeedInfo(index);
  96. if (!seedOutcome.IsSuccess())
  97. {
  98. // Error has already been thrown
  99. return false;
  100. }
  101. if (platforms == AzFramework::PlatformFlags::Platform_NONE)
  102. {
  103. AZ_Error(AssetBundler::AppWindowName, false, "Cannot Edit Platforms: No platforms were selected");
  104. return false;
  105. }
  106. auto setPlatformOutcome = m_seedListManager->SetSeedPlatformFlags(index.row(), platforms);
  107. if (!setPlatformOutcome.IsSuccess())
  108. {
  109. AZ_Error(AssetBundler::AppWindowName, false, setPlatformOutcome.GetError().c_str());
  110. return false;
  111. }
  112. // Update the cached display info
  113. auto additionalSeedInfo = m_additionalSeedInfoMap.find(seedOutcome.GetValue().get().m_assetId);
  114. if (additionalSeedInfo == m_additionalSeedInfoMap.end())
  115. {
  116. AZ_Error(AssetBundler::AppWindowName, false, "Unable to find additional Seed info");
  117. return false;
  118. }
  119. additionalSeedInfo->second->m_platformList =
  120. QString(AzFramework::PlatformHelper::GetCommaSeparatedPlatformList(platforms).c_str());
  121. SetHasUnsavedChanges(true);
  122. // Update the display
  123. QModelIndex firstChangedIndex = QAbstractTableModel::index(index.row(), Column::ColumnRelativePath);
  124. QModelIndex lastChangedIndex = QAbstractTableModel::index(index.row(), Column::Max - 1);
  125. emit dataChanged(firstChangedIndex, lastChangedIndex, { Qt::DisplayRole });
  126. return true;
  127. }
  128. bool SeedListTableModel::AddSeed(const AZStd::string& seedRelativePath, const AzFramework::PlatformFlags& platforms)
  129. {
  130. AZStd::pair<AZ::Data::AssetId, AzFramework::PlatformFlags> addSeedsResult =
  131. m_seedListManager->AddSeedAssetForValidPlatforms(seedRelativePath, platforms);
  132. if (!addSeedsResult.first.IsValid() || addSeedsResult.second == AzFramework::PlatformFlags::Platform_NONE)
  133. {
  134. // Error has already been thrown
  135. return false;
  136. }
  137. QString platformList = QString(AzFramework::PlatformHelper::GetCommaSeparatedPlatformList(addSeedsResult.second).c_str());
  138. int lastRowIndex = AZStd::max(rowCount() - 1, 0);
  139. beginInsertRows(QModelIndex(), lastRowIndex, lastRowIndex);
  140. m_additionalSeedInfoMap[addSeedsResult.first].reset(new AdditionalSeedInfo(QString(seedRelativePath.c_str()), platformList));
  141. endInsertRows();
  142. SetHasUnsavedChanges(true);
  143. return true;
  144. }
  145. bool SeedListTableModel::RemoveSeed(const QModelIndex& seedIndex)
  146. {
  147. auto seedOutcome = GetSeedInfo(seedIndex);
  148. if (!seedOutcome.IsSuccess())
  149. {
  150. // Error has already been thrown
  151. return false;
  152. }
  153. int row = seedIndex.row();
  154. beginRemoveRows(QModelIndex(), row, row);
  155. m_seedListManager->RemoveSeedAsset(seedOutcome.GetValue().get().m_assetId, seedOutcome.GetValue().get().m_platformFlags);
  156. m_additionalSeedInfoMap.erase(seedOutcome.GetValue().get().m_assetId);
  157. endRemoveRows();
  158. SetHasUnsavedChanges(true);
  159. return true;
  160. }
  161. int SeedListTableModel::rowCount(const QModelIndex& parent) const
  162. {
  163. return parent.isValid() ? 0 : static_cast<int>(m_additionalSeedInfoMap.size());
  164. }
  165. int SeedListTableModel::columnCount(const QModelIndex& parent) const
  166. {
  167. return parent.isValid() ? 0 : Column::Max;
  168. }
  169. QVariant SeedListTableModel::headerData(int section, Qt::Orientation orientation, int role) const
  170. {
  171. if (role == Qt::DisplayRole && orientation == Qt::Horizontal)
  172. {
  173. switch (section)
  174. {
  175. case Column::ColumnRelativePath:
  176. return QString("Seed");
  177. case Column::ColumnPlatformList:
  178. return QString("Platforms");
  179. default:
  180. break;
  181. }
  182. }
  183. return QVariant();
  184. }
  185. QVariant SeedListTableModel::data(const QModelIndex& index, int role) const
  186. {
  187. auto additionalSeedInfoOutcome = GetAdditionalSeedInfo(index);
  188. if (!additionalSeedInfoOutcome.IsSuccess())
  189. {
  190. return QVariant();
  191. }
  192. switch (role)
  193. {
  194. case Qt::DecorationRole:
  195. if (index.column() == Column::ColumnRelativePath)
  196. {
  197. if (!additionalSeedInfoOutcome.GetValue()->m_errorMessage.isEmpty())
  198. {
  199. return m_errorImage;
  200. }
  201. }
  202. break;
  203. case Qt::DisplayRole:
  204. {
  205. if (index.column() == Column::ColumnRelativePath)
  206. {
  207. // If this seed has an error, display that instead of the path.
  208. if (!additionalSeedInfoOutcome.GetValue()->m_errorMessage.isEmpty())
  209. {
  210. return additionalSeedInfoOutcome.GetValue()->m_errorMessage;
  211. }
  212. return additionalSeedInfoOutcome.GetValue()->m_relativePath;
  213. }
  214. else if (index.column() == Column::ColumnPlatformList)
  215. {
  216. return additionalSeedInfoOutcome.GetValue()->m_platformList;
  217. }
  218. }
  219. default:
  220. break;
  221. }
  222. return QVariant();
  223. }
  224. AZ::Outcome<AZStd::reference_wrapper<const AzFramework::SeedInfo>, void> SeedListTableModel::GetSeedInfo(const QModelIndex& index) const
  225. {
  226. int row = index.row();
  227. int col = index.column();
  228. if (row >= rowCount() || row < 0 || col >= columnCount() || col < 0)
  229. {
  230. AZ_Error(AssetBundler::AppWindowName, false, "Selected index (%i, %i) is out of range", row, col);
  231. return AZ::Failure();
  232. }
  233. return m_seedListManager->GetAssetSeedList().at(row);
  234. }
  235. AZ::Outcome<AdditionalSeedInfoPtr, void> SeedListTableModel::GetAdditionalSeedInfo(const QModelIndex& index) const
  236. {
  237. auto seedInfoOutcome = GetSeedInfo(index);
  238. if (!seedInfoOutcome.IsSuccess())
  239. {
  240. // Error has already been thrown
  241. return AZ::Failure();
  242. }
  243. auto additionalSeedInfoIt = m_additionalSeedInfoMap.find(seedInfoOutcome.GetValue().get().m_assetId);
  244. if (additionalSeedInfoIt == m_additionalSeedInfoMap.end())
  245. {
  246. return AZ::Failure();
  247. }
  248. return AZ::Success(additionalSeedInfoIt->second);
  249. }
  250. } // namespace AssetBundler