ScreensCtrl.cpp 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  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 <ScreensCtrl.h>
  9. #include <ScreenFactory.h>
  10. #include <ScreenWidget.h>
  11. #include <UpdateProjectCtrl.h>
  12. #include <QTabWidget>
  13. #include <QVBoxLayout>
  14. namespace O3DE::ProjectManager
  15. {
  16. ScreensCtrl::ScreensCtrl(QWidget* parent, DownloadController* downloadController)
  17. : QWidget(parent)
  18. , m_downloadController(downloadController)
  19. {
  20. setObjectName("ScreensCtrl");
  21. QVBoxLayout* vLayout = new QVBoxLayout();
  22. vLayout->setContentsMargins(0, 0, 0, 0);
  23. setLayout(vLayout);
  24. m_screenStack = new QStackedWidget();
  25. vLayout->addWidget(m_screenStack);
  26. // add a tab widget at the bottom of the stack
  27. m_tabWidget = new QTabWidget();
  28. m_tabWidget->tabBar()->setFocusPolicy(Qt::TabFocus);
  29. m_screenStack->addWidget(m_tabWidget);
  30. connect(m_tabWidget, &QTabWidget::currentChanged, this, &ScreensCtrl::TabChanged);
  31. }
  32. void ScreensCtrl::BuildScreens(QVector<ProjectManagerScreen> screens)
  33. {
  34. for (ProjectManagerScreen screen : screens)
  35. {
  36. ResetScreen(screen);
  37. }
  38. }
  39. ScreenWidget* ScreensCtrl::FindScreen(ProjectManagerScreen screen)
  40. {
  41. const auto iterator = m_screenMap.find(screen);
  42. if (iterator != m_screenMap.end())
  43. {
  44. return iterator.value();
  45. }
  46. else
  47. {
  48. return nullptr;
  49. }
  50. }
  51. ScreenWidget* ScreensCtrl::GetCurrentScreen()
  52. {
  53. if (m_screenStack->currentWidget() == m_tabWidget)
  54. {
  55. return static_cast<ScreenWidget*>(m_tabWidget->currentWidget());
  56. }
  57. else
  58. {
  59. return static_cast<ScreenWidget*>(m_screenStack->currentWidget());
  60. }
  61. }
  62. bool ScreensCtrl::ChangeToScreen(ProjectManagerScreen screen)
  63. {
  64. if (m_screenStack->currentWidget())
  65. {
  66. ScreenWidget* currentScreenWidget = GetCurrentScreen();
  67. if (currentScreenWidget->IsReadyForNextScreen())
  68. {
  69. return ForceChangeToScreen(screen);
  70. }
  71. }
  72. return false;
  73. }
  74. bool ScreensCtrl::ForceChangeToScreen(ProjectManagerScreen screen, bool addVisit)
  75. {
  76. ScreenWidget* newScreen = nullptr;
  77. const auto iterator = m_screenMap.find(screen);
  78. if (iterator != m_screenMap.end())
  79. {
  80. newScreen = iterator.value();
  81. }
  82. else
  83. {
  84. // Check if screen is contained by another screen
  85. for (ScreenWidget* checkingScreen : m_screenMap)
  86. {
  87. if (checkingScreen->ContainsScreen(screen))
  88. {
  89. newScreen = checkingScreen;
  90. break;
  91. }
  92. }
  93. }
  94. if (newScreen)
  95. {
  96. ScreenWidget* currentScreen = GetCurrentScreen();
  97. if (currentScreen != newScreen)
  98. {
  99. if (addVisit)
  100. {
  101. ProjectManagerScreen oldScreen = currentScreen->GetScreenEnum();
  102. m_screenVisitOrder.push(oldScreen);
  103. }
  104. if (newScreen->IsTab())
  105. {
  106. m_tabWidget->setCurrentWidget(newScreen);
  107. m_screenStack->setCurrentWidget(m_tabWidget);
  108. }
  109. else
  110. {
  111. m_screenStack->setCurrentWidget(newScreen);
  112. }
  113. newScreen->NotifyCurrentScreen();
  114. if (iterator == m_screenMap.end())
  115. {
  116. newScreen->GoToScreen(screen);
  117. }
  118. return true;
  119. }
  120. else
  121. {
  122. // If we are already on this screen still notify we are on this screen to refresh it
  123. newScreen->NotifyCurrentScreen();
  124. }
  125. }
  126. return false;
  127. }
  128. bool ScreensCtrl::GoToPreviousScreen()
  129. {
  130. if (!m_screenVisitOrder.isEmpty())
  131. {
  132. // We do not check with screen if we can go back, we should always be able to go back
  133. ProjectManagerScreen previousScreen = m_screenVisitOrder.pop();
  134. return ForceChangeToScreen(previousScreen, false);
  135. }
  136. return false;
  137. }
  138. void ScreensCtrl::ResetScreen(ProjectManagerScreen screen)
  139. {
  140. bool shouldRestoreCurrentScreen = false;
  141. if (GetCurrentScreen() && GetCurrentScreen()->GetScreenEnum() == screen)
  142. {
  143. shouldRestoreCurrentScreen = true;
  144. }
  145. int tabIndex = GetScreenTabIndex(screen);
  146. // Delete old screen if it exists to start fresh
  147. DeleteScreen(screen);
  148. // Add new screen
  149. ScreenWidget* newScreen = BuildScreen(this, screen, m_downloadController);
  150. if (newScreen->IsTab())
  151. {
  152. if (tabIndex > -1)
  153. {
  154. m_tabWidget->insertTab(tabIndex, newScreen, newScreen->GetTabText());
  155. }
  156. else
  157. {
  158. m_tabWidget->addTab(newScreen, newScreen->GetTabText());
  159. }
  160. if (shouldRestoreCurrentScreen)
  161. {
  162. m_tabWidget->setCurrentWidget(newScreen);
  163. m_screenStack->setCurrentWidget(m_tabWidget);
  164. newScreen->NotifyCurrentScreen();
  165. }
  166. }
  167. else
  168. {
  169. m_screenStack->addWidget(newScreen);
  170. if (shouldRestoreCurrentScreen)
  171. {
  172. m_screenStack->setCurrentWidget(newScreen);
  173. newScreen->NotifyCurrentScreen();
  174. }
  175. }
  176. m_screenMap.insert(screen, newScreen);
  177. connect(newScreen, &ScreenWidget::ChangeScreenRequest, this, &ScreensCtrl::ChangeToScreen);
  178. connect(newScreen, &ScreenWidget::GoToPreviousScreenRequest, this, &ScreensCtrl::GoToPreviousScreen);
  179. connect(newScreen, &ScreenWidget::ResetScreenRequest, this, &ScreensCtrl::ResetScreen);
  180. connect(newScreen, &ScreenWidget::NotifyCurrentProject, this, &ScreensCtrl::NotifyCurrentProject);
  181. connect(newScreen, &ScreenWidget::NotifyBuildProject, this, &ScreensCtrl::NotifyBuildProject);
  182. connect(newScreen, &ScreenWidget::NotifyProjectRemoved, this, &ScreensCtrl::NotifyProjectRemoved);
  183. }
  184. void ScreensCtrl::ResetAllScreens()
  185. {
  186. for (auto iter = m_screenMap.begin(); iter != m_screenMap.end(); ++iter)
  187. {
  188. ResetScreen(iter.key());
  189. }
  190. }
  191. void ScreensCtrl::DeleteScreen(ProjectManagerScreen screen)
  192. {
  193. // Find the old screen if it exists and get rid of it
  194. const auto iter = m_screenMap.find(screen);
  195. if (iter != m_screenMap.end())
  196. {
  197. ScreenWidget* screenToDelete = iter.value();
  198. if (screenToDelete->IsTab())
  199. {
  200. int tabIndex = m_tabWidget->indexOf(screenToDelete);
  201. if (tabIndex > -1)
  202. {
  203. m_tabWidget->removeTab(tabIndex);
  204. }
  205. }
  206. else
  207. {
  208. // if the screen we delete is the current widget, a new one will
  209. // be selected automatically (randomly?)
  210. m_screenStack->removeWidget(screenToDelete);
  211. }
  212. // Erase does not cause a rehash so interators remain valid
  213. m_screenMap.erase(iter);
  214. }
  215. }
  216. void ScreensCtrl::DeleteAllScreens()
  217. {
  218. for (auto iter = m_screenMap.begin(); iter != m_screenMap.end(); ++iter)
  219. {
  220. DeleteScreen(iter.key());
  221. }
  222. }
  223. void ScreensCtrl::TabChanged([[maybe_unused]] int index)
  224. {
  225. ScreenWidget* screen = static_cast<ScreenWidget*>(m_tabWidget->currentWidget());
  226. if (screen)
  227. {
  228. screen->NotifyCurrentScreen();
  229. }
  230. }
  231. int ScreensCtrl::GetScreenTabIndex(ProjectManagerScreen screen)
  232. {
  233. const auto iter = m_screenMap.find(screen);
  234. if (iter != m_screenMap.end())
  235. {
  236. ScreenWidget* screenWidget = iter.value();
  237. if (screenWidget->IsTab())
  238. {
  239. return m_tabWidget->indexOf(screenWidget);
  240. }
  241. }
  242. return -1;
  243. }
  244. } // namespace O3DE::ProjectManager