UpdateProjectSettingsScreen.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  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 <UpdateProjectSettingsScreen.h>
  9. #include <PythonBindingsInterface.h>
  10. #include <ProjectManagerDefs.h>
  11. #include <FormImageBrowseEditWidget.h>
  12. #include <FormLineEditWidget.h>
  13. #include <FormComboBoxWidget.h>
  14. #include <QVBoxLayout>
  15. #include <QLineEdit>
  16. #include <QDir>
  17. #include <QLabel>
  18. #include <QFileInfo>
  19. #include <QPushButton>
  20. #include <QComboBox>
  21. namespace O3DE::ProjectManager
  22. {
  23. UpdateProjectSettingsScreen::UpdateProjectSettingsScreen(QWidget* parent)
  24. : ProjectSettingsScreen(parent)
  25. , m_userChangedPreview(false)
  26. {
  27. // Engine combo box
  28. m_projectEngine = new FormComboBoxWidget(tr("Engine"), {}, this);
  29. connect(m_projectEngine->comboBox(), QOverload<int>::of(&QComboBox::currentIndexChanged),
  30. this, &UpdateProjectSettingsScreen::OnProjectEngineUpdated);
  31. m_verticalLayout->addWidget(m_projectEngine);
  32. // Project preview browse edit
  33. m_projectPreview = new FormImageBrowseEditWidget(tr("Project Preview"), "", this);
  34. m_projectPreview->lineEdit()->setReadOnly(true);
  35. connect(m_projectPreview->lineEdit(), &QLineEdit::textChanged, this, &ProjectSettingsScreen::Validate);
  36. connect(m_projectPreview->lineEdit(), &QLineEdit::textChanged, this, &UpdateProjectSettingsScreen::PreviewPathChanged);
  37. connect(m_projectPath->lineEdit(), &QLineEdit::textChanged, this, &UpdateProjectSettingsScreen::UpdateProjectPreviewPath);
  38. m_verticalLayout->addWidget(m_projectPreview);
  39. QVBoxLayout* previewExtrasLayout = new QVBoxLayout();
  40. previewExtrasLayout->setAlignment(Qt::AlignTop);
  41. previewExtrasLayout->setContentsMargins(30, 45, 30, 0);
  42. QLabel* projectPreviewLabel = new QLabel(tr("Project Preview"));
  43. previewExtrasLayout->addWidget(projectPreviewLabel);
  44. // Project preview image
  45. m_projectPreviewImage = new QLabel(this);
  46. m_projectPreviewImage->setFixedSize(ProjectPreviewImageWidth, ProjectPreviewImageHeight);
  47. m_projectPreviewImage->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
  48. previewExtrasLayout->addWidget(m_projectPreviewImage);
  49. QLabel* projectPreviewInfoLabel = new QLabel(tr("Select an image (PNG). Minimum %1 x %2 pixels.")
  50. .arg(QString::number(ProjectPreviewImageWidth), QString::number(ProjectPreviewImageHeight)));
  51. projectPreviewInfoLabel->setObjectName("projectSmallInfoLabel");
  52. projectPreviewInfoLabel->setWordWrap(true);
  53. previewExtrasLayout->addWidget(projectPreviewInfoLabel);
  54. m_horizontalLayout->addLayout(previewExtrasLayout);
  55. m_verticalLayout->addSpacing(10);
  56. // Collapse button
  57. QHBoxLayout* advancedCollapseLayout = new QHBoxLayout();
  58. advancedCollapseLayout->setContentsMargins(50, 0, 0, 0);
  59. m_advancedSettingsCollapseButton = new QPushButton();
  60. m_advancedSettingsCollapseButton->setCheckable(true);
  61. m_advancedSettingsCollapseButton->setChecked(true);
  62. m_advancedSettingsCollapseButton->setFlat(true);
  63. m_advancedSettingsCollapseButton->setFocusPolicy(Qt::NoFocus);
  64. m_advancedSettingsCollapseButton->setFixedWidth(s_collapseButtonSize);
  65. connect(m_advancedSettingsCollapseButton, &QPushButton::clicked, this, &UpdateProjectSettingsScreen::UpdateAdvancedSettingsCollapseState);
  66. advancedCollapseLayout->addWidget(m_advancedSettingsCollapseButton);
  67. // Category title
  68. QLabel* advancedLabel = new QLabel(tr("Advanced Settings"));
  69. advancedLabel->setObjectName("projectSettingsSectionTitle");
  70. advancedCollapseLayout->addWidget(advancedLabel);
  71. m_verticalLayout->addLayout(advancedCollapseLayout);
  72. m_verticalLayout->addSpacing(5);
  73. // Everything in the advanced settings widget will be collapsed/uncollapsed
  74. {
  75. m_advancedSettingWidget = new QWidget();
  76. m_verticalLayout->addWidget(m_advancedSettingWidget);
  77. QVBoxLayout* advancedSettingsLayout = new QVBoxLayout();
  78. advancedSettingsLayout->setMargin(0);
  79. advancedSettingsLayout->setAlignment(Qt::AlignTop);
  80. m_advancedSettingWidget->setLayout(advancedSettingsLayout);
  81. m_projectId = new FormLineEditWidget(tr("Project ID"), "", this);
  82. connect(m_projectId->lineEdit(), &QLineEdit::textChanged, this, &UpdateProjectSettingsScreen::OnProjectIdUpdated);
  83. advancedSettingsLayout->addWidget(m_projectId);
  84. }
  85. UpdateAdvancedSettingsCollapseState();
  86. }
  87. ProjectManagerScreen UpdateProjectSettingsScreen::GetScreenEnum()
  88. {
  89. return ProjectManagerScreen::UpdateProjectSettings;
  90. }
  91. ProjectInfo UpdateProjectSettingsScreen::GetProjectInfo()
  92. {
  93. m_projectInfo.m_displayName = m_projectName->lineEdit()->text();
  94. m_projectInfo.m_version = m_projectVersion->lineEdit()->text();
  95. m_projectInfo.m_path = m_projectPath->lineEdit()->text();
  96. m_projectInfo.m_id = m_projectId->lineEdit()->text();
  97. if (m_userChangedPreview)
  98. {
  99. m_projectInfo.m_iconPath = ProjectPreviewImagePath;
  100. m_projectInfo.m_newPreviewImagePath = m_projectPreview->lineEdit()->text();
  101. }
  102. return m_projectInfo;
  103. }
  104. void UpdateProjectSettingsScreen::SetProjectInfo(const ProjectInfo& projectInfo)
  105. {
  106. m_projectInfo = projectInfo;
  107. m_projectName->lineEdit()->setText(projectInfo.GetProjectDisplayName());
  108. m_projectVersion->lineEdit()->setText(projectInfo.m_version);
  109. m_projectPath->lineEdit()->setText(projectInfo.m_path);
  110. m_projectId->lineEdit()->setText(projectInfo.m_id);
  111. UpdateProjectPreviewPath();
  112. QComboBox* combobox = m_projectEngine->comboBox();
  113. combobox->clear();
  114. // we use engine path which is unique instead of engine name which may not be
  115. EngineInfo assignedEngine;
  116. if(auto result = PythonBindingsInterface::Get()->GetProjectEngine(projectInfo.m_path); result)
  117. {
  118. assignedEngine = result.TakeValue();
  119. }
  120. // handle case where user may not want to set the engine name (engine-centric)
  121. int index = 0;
  122. int selectedIndex = -1;
  123. if (projectInfo.m_engineName.isEmpty() && !assignedEngine.m_path.isEmpty())
  124. {
  125. combobox->addItem(
  126. QString("(no engine specified) %1 %2 (%3)").
  127. arg(assignedEngine.m_name,assignedEngine.m_version, assignedEngine.m_path),
  128. QStringList{ assignedEngine.m_path, "" });
  129. selectedIndex = index;
  130. index++;
  131. }
  132. // handle case when project uses an engine that isn't registered
  133. else if (!projectInfo.m_engineName.isEmpty() && assignedEngine.m_path.isEmpty())
  134. {
  135. combobox->addItem(QString("%1 (not registered)").arg(projectInfo.m_engineName), QStringList{ "", projectInfo.m_engineName });
  136. selectedIndex = index;
  137. index++;
  138. }
  139. if (auto result = PythonBindingsInterface::Get()->GetAllEngineInfos(); result)
  140. {
  141. for (auto engineInfo : result.GetValue<QVector<EngineInfo>>())
  142. {
  143. if (!engineInfo.m_name.isEmpty())
  144. {
  145. const bool useDisplayVersion = !engineInfo.m_displayVersion.isEmpty() &&
  146. engineInfo.m_displayVersion != "00.00" &&
  147. engineInfo.m_displayVersion != "0.1.0.0";
  148. const auto engineVersion = useDisplayVersion ? engineInfo.m_displayVersion : engineInfo.m_version;
  149. combobox->addItem(
  150. QString("%1 %2 (%3)").arg(engineInfo.m_name, engineVersion, engineInfo.m_path),
  151. QStringList{ engineInfo.m_path, engineInfo.m_name });
  152. if (selectedIndex == -1 && !assignedEngine.m_path.isEmpty() && QDir(assignedEngine.m_path) == QDir(engineInfo.m_path))
  153. {
  154. selectedIndex = index;
  155. }
  156. index++;
  157. }
  158. }
  159. }
  160. if (selectedIndex != -1)
  161. {
  162. combobox->setCurrentIndex(selectedIndex);
  163. }
  164. combobox->setVisible(combobox->count() > 0);
  165. }
  166. void UpdateProjectSettingsScreen::UpdateProjectPreviewPath()
  167. {
  168. if (!m_userChangedPreview)
  169. {
  170. m_projectPreview->lineEdit()->setText(QDir(m_projectPath->lineEdit()->text()).filePath(m_projectInfo.m_iconPath));
  171. // Setting the text sets m_userChangedPreview to true
  172. // Set it back to false because it should only be true when changed by user
  173. m_userChangedPreview = false;
  174. }
  175. }
  176. AZ::Outcome<void, QString> UpdateProjectSettingsScreen::Validate() const
  177. {
  178. if (!(ValidateProjectPreview() && ValidateProjectId()))
  179. {
  180. // Returning empty string to use the default error message
  181. return AZ::Failure<QString>("");
  182. }
  183. return ProjectSettingsScreen::Validate();
  184. }
  185. void UpdateProjectSettingsScreen::ResetProjectPreviewPath()
  186. {
  187. m_userChangedPreview = false;
  188. UpdateProjectPreviewPath();
  189. }
  190. void UpdateProjectSettingsScreen::PreviewPathChanged()
  191. {
  192. m_userChangedPreview = true;
  193. // Update with latest image
  194. m_projectPreviewImage->setPixmap(
  195. QPixmap(m_projectPreview->lineEdit()->text()).scaled(m_projectPreviewImage->size(), Qt::KeepAspectRatioByExpanding));
  196. }
  197. void UpdateProjectSettingsScreen::OnProjectIdUpdated()
  198. {
  199. ValidateProjectId();
  200. }
  201. void UpdateProjectSettingsScreen::OnProjectEngineUpdated(int index)
  202. {
  203. auto value = m_projectEngine->comboBox()->itemData(index).value<QStringList>();
  204. if (value.count() == 2)
  205. {
  206. m_projectInfo.m_enginePath = value[0];
  207. m_projectInfo.m_engineName = value[1];
  208. }
  209. }
  210. bool UpdateProjectSettingsScreen::ValidateProjectPath() const
  211. {
  212. bool projectPathIsValid = true;
  213. QDir path(m_projectPath->lineEdit()->text());
  214. if (!path.isAbsolute())
  215. {
  216. projectPathIsValid = false;
  217. m_projectPath->setErrorLabelText(tr("Please provide an absolute path for the project location."));
  218. }
  219. m_projectPath->setErrorLabelVisible(!projectPathIsValid);
  220. return projectPathIsValid;
  221. }
  222. bool UpdateProjectSettingsScreen::ValidateProjectPreview() const
  223. {
  224. bool projectPreviewIsValid = true;
  225. if (m_projectPreview->lineEdit()->text().isEmpty())
  226. {
  227. projectPreviewIsValid = false;
  228. m_projectPreview->setErrorLabelText(tr("Please select a file."));
  229. }
  230. else
  231. {
  232. if (m_userChangedPreview)
  233. {
  234. QFileInfo previewFile(m_projectPreview->lineEdit()->text());
  235. if (!previewFile.exists() || !previewFile.isFile())
  236. {
  237. projectPreviewIsValid = false;
  238. m_projectPreview->setErrorLabelText(tr("Please select a valid png file."));
  239. }
  240. else
  241. {
  242. QString fileType = previewFile.completeSuffix().toLower();
  243. if (fileType != "png")
  244. {
  245. projectPreviewIsValid = false;
  246. m_projectPreview->setErrorLabelText(tr("Please select a png image."));
  247. }
  248. }
  249. }
  250. }
  251. m_projectPreview->setErrorLabelVisible(!projectPreviewIsValid);
  252. return projectPreviewIsValid;
  253. }
  254. bool UpdateProjectSettingsScreen::ValidateProjectId() const
  255. {
  256. bool projectIdIsValid = true;
  257. if (m_projectId->lineEdit()->text().isEmpty())
  258. {
  259. projectIdIsValid = false;
  260. m_projectId->setErrorLabelText(tr("Project ID cannot be empty."));
  261. }
  262. m_projectId->setErrorLabelVisible(!projectIdIsValid);
  263. return projectIdIsValid;
  264. }
  265. void UpdateProjectSettingsScreen::UpdateAdvancedSettingsCollapseState()
  266. {
  267. if (m_advancedSettingsCollapseButton->isChecked())
  268. {
  269. m_advancedSettingsCollapseButton->setIcon(QIcon(":/ArrowDownLine.svg"));
  270. m_advancedSettingWidget->hide();
  271. }
  272. else
  273. {
  274. m_advancedSettingsCollapseButton->setIcon(QIcon(":/ArrowUpLine.svg"));
  275. m_advancedSettingWidget->show();
  276. }
  277. }
  278. } // namespace O3DE::ProjectManager