CreateAGemScreen.cpp 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690
  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 <GemCatalog/GemCatalogHeaderWidget.h>
  9. #include <CreateAGemScreen.h>
  10. #include <ProjectUtils.h>
  11. #include <PythonBindingsInterface.h>
  12. #include <ScreenHeaderWidget.h>
  13. #include <QApplication>
  14. #include <QButtonGroup>
  15. #include <QComboBox>
  16. #include <QDialogButtonBox>
  17. #include <QDir>
  18. #include <QLabel>
  19. #include <QMessageBox>
  20. #include <QPushButton>
  21. #include <QRadioButton>
  22. #include <QScrollArea>
  23. #include <QStackedWidget>
  24. #include <QVBoxLayout>
  25. namespace O3DE::ProjectManager
  26. {
  27. CreateGem::CreateGem(QWidget* parent)
  28. : ScreenWidget(parent)
  29. {
  30. QVBoxLayout* screenLayout = new QVBoxLayout();
  31. screenLayout->setSpacing(0);
  32. screenLayout->setContentsMargins(0, 0, 0, 0);
  33. m_header = new ScreenHeader();
  34. m_header->setSubTitle(tr("Create a new gem"));
  35. connect(
  36. m_header->backButton(),
  37. &QPushButton::clicked,
  38. this,
  39. [&]()
  40. {
  41. //if previously editing a gem, cancel the operation and revert to old creation workflow
  42. //this way we prevent accidental stale data for an already existing gem.
  43. if(m_isEditGem)
  44. {
  45. ClearWorkflow();
  46. }
  47. emit GoToPreviousScreenRequest();
  48. });
  49. screenLayout->addWidget(m_header);
  50. QHBoxLayout* hLayout = new QHBoxLayout();
  51. hLayout->setSpacing(0);
  52. hLayout->setContentsMargins(0, 0, 0, 0);
  53. QFrame* tabButtonsFrame = CreateTabButtonsFrame();
  54. hLayout->addWidget(tabButtonsFrame);
  55. QFrame* tabPaneFrame = CreateTabPaneFrame();
  56. hLayout->addWidget(tabPaneFrame);
  57. QFrame* createGemFrame = new QFrame();
  58. createGemFrame->setLayout(hLayout);
  59. screenLayout->addWidget(createGemFrame);
  60. QFrame* footerFrame = new QFrame();
  61. footerFrame->setObjectName("createAGemFooter");
  62. m_backNextButtons = new QDialogButtonBox();
  63. m_backNextButtons->setObjectName("footer");
  64. QVBoxLayout* footerLayout = new QVBoxLayout();
  65. footerLayout->setContentsMargins(0, 0, 0, 0);
  66. footerFrame->setLayout(footerLayout);
  67. footerLayout->addWidget(m_backNextButtons);
  68. screenLayout->addWidget(footerFrame);
  69. m_backButton = m_backNextButtons->addButton(tr("Back"), QDialogButtonBox::RejectRole);
  70. m_backButton->setProperty("secondary", true);
  71. m_nextButton = m_backNextButtons->addButton(tr("Next"), QDialogButtonBox::ApplyRole);
  72. connect(m_backButton, &QPushButton::clicked, this, &CreateGem::HandleBackButton);
  73. connect(m_nextButton, &QPushButton::clicked, this, &CreateGem::HandleNextButton);
  74. setObjectName("createAGemBody");
  75. setLayout(screenLayout);
  76. }
  77. QFrame* CreateGem::CreateTabButtonsFrame()
  78. {
  79. QFrame* tabButtonsFrame = new QFrame();
  80. tabButtonsFrame->setObjectName("createAGemLHS");
  81. QVBoxLayout* vLayout = new QVBoxLayout();
  82. vLayout->setSpacing(0);
  83. vLayout->setContentsMargins(0, 0, 0, 0);
  84. m_gemTemplateSelectionTab = new QRadioButton(tr("1. Gem Setup"));
  85. m_gemDetailsTab = new QRadioButton(tr("2. Gem Details"));
  86. m_gemCreatorDetailsTab = new QRadioButton(tr("3. Creator Details"));
  87. m_gemTemplateSelectionTab->setChecked(true);
  88. m_gemDetailsTab->setEnabled(false);
  89. m_gemCreatorDetailsTab->setEnabled(false);
  90. connect(m_gemTemplateSelectionTab, &QPushButton::clicked, this, &CreateGem::HandleGemTemplateSelectionTab);
  91. connect(m_gemDetailsTab, &QPushButton::clicked, this, &CreateGem::HandleGemDetailsTab);
  92. connect(m_gemCreatorDetailsTab, &QPushButton::clicked, this, &CreateGem::HandleGemCreatorDetailsTab);
  93. vLayout->addSpacing(46);
  94. vLayout->addWidget(m_gemTemplateSelectionTab);
  95. vLayout->addSpacing(12);
  96. vLayout->addWidget(m_gemDetailsTab);
  97. vLayout->addSpacing(12);
  98. vLayout->addWidget(m_gemCreatorDetailsTab);
  99. vLayout->addStretch();
  100. tabButtonsFrame->setLayout(vLayout);
  101. return tabButtonsFrame;
  102. }
  103. void CreateGem::HandleGemTemplateSelectionTab()
  104. {
  105. m_stackWidget->setCurrentIndex(GemTemplateSelectionScreen);
  106. m_nextButton->setText(tr("Next"));
  107. m_backButton->setVisible(false);
  108. }
  109. void CreateGem::HandleGemDetailsTab()
  110. {
  111. m_stackWidget->setCurrentIndex(GemDetailsScreen);
  112. m_nextButton->setText(tr("Next"));
  113. m_backButton->setVisible(!m_isEditGem);
  114. }
  115. void CreateGem::HandleGemCreatorDetailsTab()
  116. {
  117. m_stackWidget->setCurrentIndex(GemCreatorDetailsScreen);
  118. if(m_isEditGem)
  119. {
  120. m_nextButton->setText(tr("Edit"));
  121. }
  122. else
  123. {
  124. m_nextButton->setText(tr("Create"));
  125. }
  126. m_backButton->setVisible(true);
  127. }
  128. QFrame* CreateGem::CreateTabPaneFrame()
  129. {
  130. QFrame* tabPaneFrame = new QFrame();
  131. QVBoxLayout* vLayout = new QVBoxLayout();
  132. vLayout->setSpacing(0);
  133. vLayout->setContentsMargins(0, 0, 0, 0);
  134. m_stackWidget = new QStackedWidget();
  135. m_stackWidget->setContentsMargins(0, 0, 0, 0);
  136. m_stackWidget->setObjectName("createAGemRHS");
  137. m_stackWidget->addWidget(CreateGemSetupScrollArea());
  138. m_stackWidget->addWidget(CreateGemDetailsScrollArea());
  139. m_stackWidget->addWidget(CreateGemCreatorScrollArea());
  140. vLayout->addWidget(m_stackWidget);
  141. tabPaneFrame->setLayout(vLayout);
  142. return tabPaneFrame;
  143. }
  144. void CreateGem::LoadButtonsFromGemTemplatePaths(QVBoxLayout* gemSetupLayout)
  145. {
  146. m_radioButtonGroup = new QButtonGroup();
  147. auto templatesResult = PythonBindingsInterface::Get()->GetGemTemplates();
  148. if (templatesResult.IsSuccess() && !templatesResult.GetValue().isEmpty())
  149. {
  150. m_gemTemplates = templatesResult.GetValue();
  151. for (int index = 0; index < m_gemTemplates.size(); ++index)
  152. {
  153. const ProjectTemplateInfo& gemTemplate = m_gemTemplates.at(index);
  154. QRadioButton* button = new QRadioButton(gemTemplate.m_displayName);
  155. button->setObjectName("createAGem");
  156. m_radioButtonGroup->addButton(button, index);
  157. QLabel* buttonSubtext = new QLabel(gemTemplate.m_summary);
  158. buttonSubtext->setObjectName("createAGemRadioButtonSubtext");
  159. gemSetupLayout->addWidget(button);
  160. gemSetupLayout->addWidget(buttonSubtext);
  161. }
  162. QAbstractButton* firstButton = m_radioButtonGroup->button(0);
  163. firstButton->setChecked(true);
  164. }
  165. }
  166. QScrollArea* CreateGem::CreateGemSetupScrollArea()
  167. {
  168. QScrollArea* gemSetupScrollArea = new QScrollArea();
  169. gemSetupScrollArea->setWidgetResizable(true);
  170. gemSetupScrollArea->setObjectName("createAGemRightPane");
  171. QFrame* gemSetupFrame = new QFrame();
  172. QWidget* gemSetupScrollWidget = new QWidget();
  173. gemSetupScrollArea->setWidget(gemSetupScrollWidget);
  174. QVBoxLayout* gemSetupLayout = new QVBoxLayout();
  175. gemSetupLayout->setAlignment(Qt::AlignTop);
  176. gemSetupLayout->addWidget(gemSetupFrame);
  177. gemSetupScrollWidget->setLayout(gemSetupLayout);
  178. QLabel* rightPaneHeader = new QLabel(tr("Please Choose a Gem Template"));
  179. rightPaneHeader->setObjectName("rightPaneHeader");
  180. QLabel* rightPaneSubheader = new QLabel(tr("Gems can contain assets new functionality and such as scripts, animations, meshes, textures, and more."));
  181. rightPaneSubheader->setObjectName("rightPaneSubheader");
  182. gemSetupLayout->addWidget(rightPaneHeader);
  183. gemSetupLayout->addWidget(rightPaneSubheader);
  184. LoadButtonsFromGemTemplatePaths(gemSetupLayout);
  185. m_formFolderRadioButton = new QRadioButton("Choose existing template");
  186. m_formFolderRadioButton->setObjectName("createAGem");
  187. m_radioButtonGroup->addButton(m_formFolderRadioButton);
  188. m_gemTemplateLocation = new FormFolderBrowseEditWidget(tr("Gem Template Location*"), "", "", tr("A path must be provided."));
  189. m_gemTemplateLocation->setObjectName("createAGemRadioButtonSubFormField");
  190. gemSetupLayout->addWidget(m_formFolderRadioButton);
  191. gemSetupLayout->addWidget(m_gemTemplateLocation);
  192. return gemSetupScrollArea;
  193. }
  194. QScrollArea* CreateGem::CreateGemDetailsScrollArea()
  195. {
  196. QScrollArea* gemDetailsScrollArea = new QScrollArea();
  197. gemDetailsScrollArea->setWidgetResizable(true);
  198. gemDetailsScrollArea->setObjectName("createAGemRightPane");
  199. QFrame* gemDetailsFrame = new QFrame();
  200. QWidget* gemDetailsScrollWidget = new QWidget();
  201. gemDetailsScrollArea->setWidget(gemDetailsScrollWidget);
  202. QVBoxLayout* gemDetailsLayout = new QVBoxLayout(this);
  203. gemDetailsLayout->setAlignment(Qt::AlignTop);
  204. gemDetailsLayout->addWidget(gemDetailsFrame);
  205. gemDetailsScrollWidget->setLayout(gemDetailsLayout);
  206. QLabel* secondRightPaneHeader = new QLabel(tr("Enter Gem Details"));
  207. secondRightPaneHeader->setObjectName("rightPaneDetailsHeader");
  208. gemDetailsLayout->addWidget(secondRightPaneHeader);
  209. m_gemName = new FormLineEditWidget(
  210. tr("Gem name*"),
  211. "",
  212. tr("The unique name for your gem consisting of only alphanumeric characters, '-' and '_'."),
  213. tr("A gem system name is required."));
  214. m_gemName->lineEdit()->setValidator(new QRegularExpressionValidator(QRegularExpression("[a-zA-Z]+[a-zA-Z0-9\\-\\_]*"), this));
  215. gemDetailsLayout->addWidget(m_gemName);
  216. m_gemDisplayName = new FormLineEditWidget(
  217. tr("Gem Display name*"), "", tr("The name displayed in the Gem Catalog"), tr("A gem display name is required."));
  218. m_gemDisplayName->lineEdit()->setValidator(new QRegularExpressionValidator(QRegularExpression("( |\\w)+"), this));
  219. gemDetailsLayout->addWidget(m_gemDisplayName);
  220. m_gemSummary = new FormLineEditWidget(tr("Gem Summary"), "", tr("A short description of your Gem"), "");
  221. gemDetailsLayout->addWidget(m_gemSummary);
  222. m_requirements = new FormLineEditWidget(tr("Requirements"), "", tr("Notice of any requirements your Gem. i.e. This requires X other gem"), "");
  223. gemDetailsLayout->addWidget(m_requirements);
  224. m_license = new FormLineEditWidget(
  225. tr("License*"), "", tr("License uses goes here: i.e. Apache-2.0 or MIT"), tr("License details are required."));
  226. gemDetailsLayout->addWidget(m_license);
  227. m_licenseURL = new FormLineEditWidget(tr("License URL"), "", tr("Link to the license web site i.e. https://opensource.org/licenses/Apache-2.0"), "");
  228. gemDetailsLayout->addWidget(m_licenseURL);
  229. m_userDefinedGemTags = new FormLineEditTagsWidget(
  230. tr("User-defined Gem Tags <i>&nbsp;&nbsp;&nbsp;(Press enter to create Gem Tag)</i>"), "", tr("Tags without spaces: i.e. SampleGame"), "");
  231. m_userDefinedGemTags->lineEdit()->setValidator(new QRegularExpressionValidator(QRegularExpression("(^$|((\\w+)(\\w*)*))"), this));
  232. gemDetailsLayout->addWidget(m_userDefinedGemTags);
  233. m_gemLocation = new FormFolderBrowseEditWidget(tr("Gem Location"), "", tr("The path that the gem will be created at."), tr("The chosen directory must either not exist or be empty."));
  234. gemDetailsLayout->addWidget(m_gemLocation);
  235. m_gemIconPath = new FormLineEditWidget(tr("Gem Icon Path"), "default.png", tr("Select Gem icon path"), "");
  236. gemDetailsLayout->addWidget(m_gemIconPath);
  237. m_documentationURL = new FormLineEditWidget(
  238. tr("Documentation URL"), "", tr("Link to any documentation of your Gem i.e. https://o3de.org/docs/user-guide/gems/..."), "");
  239. gemDetailsLayout->addWidget(m_documentationURL);
  240. return gemDetailsScrollArea;
  241. }
  242. QScrollArea* CreateGem::CreateGemCreatorScrollArea()
  243. {
  244. QScrollArea* gemCreatorScrollArea = new QScrollArea();
  245. gemCreatorScrollArea->setWidgetResizable(true);
  246. gemCreatorScrollArea->setObjectName("createAGemRightPane");
  247. QFrame* gemCreatorFrame = new QFrame();
  248. QWidget* gemCreatorScrollWidget = new QWidget();
  249. gemCreatorScrollArea->setWidget(gemCreatorScrollWidget);
  250. QVBoxLayout* gemCreatorLayout = new QVBoxLayout();
  251. gemCreatorLayout->setAlignment(Qt::AlignTop);
  252. gemCreatorLayout->addWidget(gemCreatorFrame);
  253. gemCreatorScrollWidget->setLayout(gemCreatorLayout);
  254. QLabel* thirdRightPaneHeader = new QLabel(tr("Enter your Details"));
  255. thirdRightPaneHeader->setObjectName("rightPaneDetailsHeader");
  256. gemCreatorLayout->addWidget(thirdRightPaneHeader);
  257. m_origin =
  258. new FormLineEditWidget(tr("Creator Name*"), "", tr("The name of the gem creator or originator goes here. i.e. O3DE"), tr("You must provide a creator name."));
  259. gemCreatorLayout->addWidget(m_origin);
  260. m_originURL = new FormLineEditWidget(tr("Origin URL"), "", tr("The primary website for your Gem. i.e. http://o3de.org"), "");
  261. gemCreatorLayout->addWidget(m_originURL);
  262. m_repositoryURL = new FormLineEditWidget(tr("Repository URL"), "", tr("Optional URL of the repository for this gem."), "");
  263. gemCreatorLayout->addWidget(m_repositoryURL);
  264. return gemCreatorScrollArea;
  265. }
  266. bool CreateGem::ValidateGemTemplateLocation()
  267. {
  268. bool gemTemplateLocationFilled = true;
  269. if (m_formFolderRadioButton->isChecked() && m_gemTemplateLocation->lineEdit()->text().isEmpty())
  270. {
  271. gemTemplateLocationFilled = false;
  272. }
  273. m_gemTemplateLocation->setErrorLabelVisible(!gemTemplateLocationFilled);
  274. return gemTemplateLocationFilled;
  275. }
  276. bool CreateGem::ValidateGemDisplayName()
  277. {
  278. bool gemScreenNameIsValid = true;
  279. if (m_gemDisplayName->lineEdit()->text().isEmpty() || !m_gemDisplayName->lineEdit()->hasAcceptableInput())
  280. {
  281. gemScreenNameIsValid = false;
  282. }
  283. m_gemDisplayName->setErrorLabelVisible(!gemScreenNameIsValid);
  284. return gemScreenNameIsValid;
  285. }
  286. bool CreateGem::ValidateGemName()
  287. {
  288. bool gemSystemNameIsValid = true;
  289. if (m_gemName->lineEdit()->text().isEmpty() || !m_gemName->lineEdit()->hasAcceptableInput())
  290. {
  291. gemSystemNameIsValid = false;
  292. }
  293. m_gemName->setErrorLabelVisible(!gemSystemNameIsValid);
  294. return gemSystemNameIsValid;
  295. }
  296. bool CreateGem::ValidateGemPath()
  297. {
  298. // This first isEmpty check is to check that the input field is not empty. If it is QDir will use the current
  299. // directory as the gem location, so that if that folder is also empty it will pass the chosenGemLocation.isEmpty()
  300. // check and place the created gem there, which is likely unintended behavior for a GUI app such as Project Manager.
  301. if (m_gemLocation->lineEdit()->text().isEmpty())
  302. {
  303. return false;
  304. }
  305. QDir chosenGemLocation = QDir(m_gemLocation->lineEdit()->text());
  306. bool locationValid = false;
  307. if(m_isEditGem)
  308. {
  309. //If in edit gem workflow, users cannot change this value, so this check should suffice
  310. locationValid = chosenGemLocation.exists();
  311. }
  312. else
  313. {
  314. locationValid = !chosenGemLocation.exists() || chosenGemLocation.isEmpty();
  315. }
  316. m_gemLocation->setErrorLabelVisible(!locationValid);
  317. return locationValid;
  318. }
  319. bool CreateGem::ValidateFormNotEmpty(FormLineEditWidget* form)
  320. {
  321. bool formIsValid = !form->lineEdit()->text().isEmpty();
  322. form->setErrorLabelVisible(!formIsValid);
  323. return formIsValid;
  324. }
  325. bool CreateGem::ValidateRepositoryURL()
  326. {
  327. bool repositoryURLIsValid = true;
  328. if (!m_repositoryURL->lineEdit()->text().isEmpty())
  329. {
  330. QUrl checkURL = QUrl(m_repositoryURL->lineEdit()->text(), QUrl::StrictMode);
  331. repositoryURLIsValid = checkURL.isValid();
  332. m_repositoryURL->setErrorLabelText(tr("Repository URL is not valid."));
  333. }
  334. m_repositoryURL->setErrorLabelVisible(!repositoryURLIsValid);
  335. return repositoryURLIsValid;
  336. }
  337. void CreateGem::HandleBackButton()
  338. {
  339. int indexBackLimit = 0;
  340. if(m_isEditGem)
  341. {
  342. //this will prevent us from reaching the templates page in the edit gem workflow
  343. indexBackLimit = 1;
  344. }
  345. if (m_stackWidget->currentIndex() > indexBackLimit)
  346. {
  347. const int newIndex = m_stackWidget->currentIndex() - 1;
  348. m_stackWidget->setCurrentIndex(newIndex);
  349. if (newIndex == GemDetailsScreen)
  350. {
  351. m_gemDetailsTab->setChecked(true);
  352. }
  353. else if (newIndex == GemTemplateSelectionScreen)
  354. {
  355. m_gemTemplateSelectionTab->setChecked(true);
  356. }
  357. }
  358. if (m_stackWidget->currentIndex() == indexBackLimit)
  359. {
  360. m_backButton->setVisible(false);
  361. }
  362. m_nextButton->setText(tr("Next"));
  363. }
  364. void CreateGem::HandleNextButton()
  365. {
  366. if (m_stackWidget->currentIndex() == GemTemplateSelectionScreen && ValidateGemTemplateLocation())
  367. {
  368. m_backButton->setVisible(true);
  369. m_stackWidget->setCurrentIndex(GemDetailsScreen);
  370. m_gemDetailsTab->setEnabled(true);
  371. m_gemDetailsTab->setChecked(true);
  372. }
  373. else if (m_stackWidget->currentIndex() == GemDetailsScreen)
  374. {
  375. bool gemNameValid = ValidateGemName();
  376. bool gemDisplayNameValid = ValidateGemDisplayName();
  377. bool licenseValid = ValidateFormNotEmpty(m_license);
  378. bool gemPathValid = ValidateGemPath();
  379. if (gemNameValid && gemDisplayNameValid && licenseValid && gemPathValid)
  380. {
  381. m_createGemInfo.m_displayName = m_gemDisplayName->lineEdit()->text();
  382. m_createGemInfo.m_name = m_gemName->lineEdit()->text();
  383. m_createGemInfo.m_summary = m_gemSummary->lineEdit()->text();
  384. m_createGemInfo.m_requirement = m_requirements->lineEdit()->text();
  385. m_createGemInfo.m_licenseText = m_license->lineEdit()->text();
  386. m_createGemInfo.m_licenseLink = m_licenseURL->lineEdit()->text();
  387. m_createGemInfo.m_documentationLink = m_documentationURL->lineEdit()->text();
  388. m_createGemInfo.m_path = m_gemLocation->lineEdit()->text();
  389. m_createGemInfo.m_features = m_userDefinedGemTags->getTags();
  390. m_stackWidget->setCurrentIndex(GemCreatorDetailsScreen);
  391. if(m_isEditGem)
  392. {
  393. m_nextButton->setText(tr("Edit"));
  394. m_backButton->setVisible(true);
  395. }
  396. else
  397. {
  398. m_nextButton->setText(tr("Create"));
  399. }
  400. m_gemCreatorDetailsTab->setEnabled(true);
  401. m_gemCreatorDetailsTab->setChecked(true);
  402. }
  403. }
  404. else if (m_stackWidget->currentIndex() == GemCreatorDetailsScreen)
  405. {
  406. bool originIsValid = ValidateFormNotEmpty(m_origin);
  407. bool repoURLIsValid = ValidateRepositoryURL();
  408. if (originIsValid && repoURLIsValid)
  409. {
  410. m_createGemInfo.m_origin = m_origin->lineEdit()->text();
  411. m_createGemInfo.m_originURL = m_originURL->lineEdit()->text();
  412. m_createGemInfo.m_repoUri = m_repositoryURL->lineEdit()->text();
  413. QString templateLocation;
  414. if (m_formFolderRadioButton->isChecked())
  415. {
  416. templateLocation = m_gemTemplateLocation->lineEdit()->text();
  417. }
  418. else
  419. {
  420. int templateID = m_radioButtonGroup->checkedId();
  421. templateLocation = m_gemTemplates[templateID].m_path;
  422. }
  423. if (m_isEditGem)
  424. {
  425. //during editing, we remove the gem name tag to prevent the user accidentally altering it
  426. //so add it back here before submission
  427. if(!m_createGemInfo.m_features.contains(m_createGemInfo.m_name))
  428. {
  429. m_createGemInfo.m_features << m_createGemInfo.m_name;
  430. }
  431. auto result = PythonBindingsInterface::Get()->EditGem(m_oldGemInfo, m_createGemInfo);
  432. if(result.IsSuccess())
  433. {
  434. ClearWorkflow();
  435. emit GemEdited(result.GetValue<GemInfo>());
  436. emit GoToPreviousScreenRequest();
  437. }
  438. else
  439. {
  440. QMessageBox::critical(
  441. this,
  442. tr("Failed to edit gem"),
  443. tr("The gem failed to be edited"));
  444. }
  445. }
  446. else
  447. {
  448. auto result = PythonBindingsInterface::Get()->CreateGem(templateLocation, m_createGemInfo);
  449. if (result.IsSuccess())
  450. {
  451. ClearWorkflow();
  452. emit GemCreated(result.GetValue<GemInfo>());
  453. emit GoToPreviousScreenRequest();
  454. }
  455. else
  456. {
  457. QMessageBox::critical(
  458. this,
  459. tr("Failed to create gem"),
  460. tr("The gem failed to be created"));
  461. }
  462. }
  463. }
  464. }
  465. }
  466. //this ignores the templates page
  467. void CreateGem::ClearWorkflow()
  468. {
  469. //details page
  470. m_gemDisplayName->lineEdit()->clear();
  471. m_gemDisplayName->setErrorLabelVisible(false);
  472. m_gemName->lineEdit()->clear();
  473. m_gemName->setErrorLabelVisible(false);
  474. m_gemSummary->lineEdit()->clear();
  475. m_requirements->lineEdit()->clear();
  476. m_license->lineEdit()->clear();
  477. m_license->setErrorLabelVisible(false);
  478. m_licenseURL->lineEdit()->clear();
  479. m_documentationURL->lineEdit()->clear();
  480. m_gemLocation->lineEdit()->clear();
  481. m_gemLocation->setErrorLabelVisible(false);
  482. m_gemIconPath->lineEdit()->clear();
  483. m_userDefinedGemTags->clear();
  484. //creator details page
  485. m_origin->lineEdit()->clear();
  486. m_origin->setErrorLabelVisible(false);
  487. m_originURL->lineEdit()->clear();
  488. m_repositoryURL->lineEdit()->clear();
  489. //we remove any assumptions about editing a gem, if it was an edit workflow, set it back
  490. if(m_isEditGem)
  491. {
  492. m_isEditGem = false;
  493. ChangeToCreateWorkflow();
  494. }
  495. }
  496. void CreateGem::ChangeToCreateWorkflow()
  497. {
  498. m_header->setSubTitle(tr("Create a new gem"));
  499. //we ensure that we are using all pages
  500. m_gemTemplateSelectionTab->setVisible(true);
  501. m_gemTemplateSelectionTab->setChecked(true);
  502. m_gemDetailsTab->setEnabled(false);
  503. m_gemDetailsTab->setChecked(false);
  504. m_gemCreatorDetailsTab->setEnabled(false);
  505. m_gemCreatorDetailsTab->setChecked(false);
  506. m_gemDetailsTab->setText(tr("2. Gem Details"));
  507. m_gemCreatorDetailsTab->setText(tr("3. Creator Details"));
  508. m_stackWidget->setCurrentIndex(GemTemplateSelectionScreen);
  509. m_gemLocation->setEnabled(true);
  510. //there exists an edge case where backing out from an old edit gem workflow fails to update next button title
  511. m_nextButton->setText(tr("Next"));
  512. }
  513. void CreateGem::ResetWorkflow(const GemInfo& oldGemInfo, bool isEditWorkflow)
  514. {
  515. //details page
  516. m_gemDisplayName->lineEdit()->setText(oldGemInfo.m_displayName);
  517. m_gemDisplayName->setErrorLabelVisible(false);
  518. m_gemName->lineEdit()->setText(oldGemInfo.m_name);
  519. m_gemName->setErrorLabelVisible(false);
  520. m_gemSummary->lineEdit()->setText(oldGemInfo.m_summary);
  521. m_requirements->lineEdit()->setText(oldGemInfo.m_requirement);
  522. m_license->lineEdit()->setText(oldGemInfo.m_licenseText);
  523. m_license->setErrorLabelVisible(false);
  524. m_licenseURL->lineEdit()->setText(oldGemInfo.m_licenseLink);
  525. m_documentationURL->lineEdit()->setText(oldGemInfo.m_documentationLink);
  526. m_gemLocation->lineEdit()->setText(oldGemInfo.m_path);
  527. m_gemLocation->setErrorLabelVisible(false);
  528. m_gemIconPath->lineEdit()->setText(oldGemInfo.m_iconPath);
  529. //before settings the tags field, find a tag that includes the gem name, and remove it
  530. QStringList tagsToEdit = oldGemInfo.m_features;
  531. tagsToEdit.removeAll(oldGemInfo.m_name);
  532. m_userDefinedGemTags->setTags(tagsToEdit);
  533. //creator details page
  534. m_origin->lineEdit()->setText(oldGemInfo.m_origin);
  535. m_origin->setErrorLabelVisible(false);
  536. m_originURL->lineEdit()->setText(oldGemInfo.m_originURL);
  537. m_repositoryURL->lineEdit()->setText(oldGemInfo.m_repoUri);
  538. //mark if we are editing a gem, and if so, change the UI accordingly
  539. m_isEditGem = isEditWorkflow;
  540. if(isEditWorkflow)
  541. {
  542. ChangeToEditWorkflow();
  543. m_oldGemInfo = oldGemInfo;
  544. }
  545. }
  546. void CreateGem::ChangeToEditWorkflow()
  547. {
  548. m_header->setSubTitle(tr("Edit gem"));
  549. //we will only have two pages: details page and creator details page
  550. m_gemTemplateSelectionTab->setChecked(false);
  551. m_gemTemplateSelectionTab->setVisible(false);
  552. m_gemDetailsTab->setEnabled(true);
  553. m_gemDetailsTab->setChecked(true);
  554. m_gemCreatorDetailsTab->setEnabled(true);
  555. m_gemDetailsTab->setText(tr("1. Gem Details"));
  556. m_gemCreatorDetailsTab->setText(tr("2. Creator Details"));
  557. m_stackWidget->setCurrentIndex(GemDetailsScreen);
  558. m_gemLocation->setEnabled(false);
  559. //there exists an edge case where backing out from an old create gem workflow fails to update next button title
  560. m_nextButton->setText(tr("Next"));
  561. }
  562. } // namespace O3DE::ProjectManager