3
0

GraphTabBar.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474
  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 <QGraphicsView>
  9. #include <QLabel>
  10. #include <QMenu>
  11. #include <QMouseEvent>
  12. #include <QVariant>
  13. #include <QVBoxLayout>
  14. #include "GraphTabBar.h"
  15. #include <ScriptCanvas/Bus/RequestBus.h>
  16. #include <Editor/View/Widgets/CanvasWidget.h>
  17. #include <Editor/QtMetaTypes.h>
  18. #include <ScriptCanvas/Asset/AssetDescription.h>
  19. #include <Editor/Include/ScriptCanvas/Components/EditorGraph.h>
  20. namespace ScriptCanvasEditor
  21. {
  22. namespace Widget
  23. {
  24. ////////////////
  25. // GraphTabBar
  26. ////////////////
  27. GraphTabBar::GraphTabBar(QWidget* parent)
  28. : AzQtComponents::TabBar(parent)
  29. {
  30. setTabsClosable(true);
  31. setMovable(true);
  32. setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
  33. connect(this, &QTabBar::currentChanged, this, &GraphTabBar::currentChangedTab);
  34. setContextMenuPolicy(Qt::CustomContextMenu);
  35. connect(this, &QTabBar::customContextMenuRequested, this, &GraphTabBar::OnContextMenu);
  36. }
  37. void GraphTabBar::AddGraphTab(SourceHandle assetId, Tracker::ScriptCanvasFileState fileState)
  38. {
  39. InsertGraphTab(count(), assetId, fileState);
  40. }
  41. void GraphTabBar::ClearTabView(int tabIndex)
  42. {
  43. if (tabIndex < count())
  44. {
  45. if (QVariant tabDataVariant = tabData(tabIndex); tabDataVariant.isValid())
  46. {
  47. GraphTabMetadata replacement = tabDataVariant.value<GraphTabMetadata>();
  48. if (replacement.m_canvasWidget)
  49. {
  50. delete replacement.m_canvasWidget;
  51. replacement.m_canvasWidget = nullptr;
  52. tabDataVariant.setValue(replacement);
  53. setTabData(tabIndex, tabDataVariant);
  54. }
  55. }
  56. }
  57. }
  58. CanvasWidget* GraphTabBar::ModOrCreateTabView(int tabIndex)
  59. {
  60. if (tabIndex < count())
  61. {
  62. if (QVariant tabDataVariant = tabData(tabIndex); tabDataVariant.isValid())
  63. {
  64. if (!tabDataVariant.value<GraphTabMetadata>().m_canvasWidget)
  65. {
  66. CanvasWidget* canvasWidget = new CanvasWidget(tabDataVariant.value<GraphTabMetadata>().m_assetId, this);
  67. canvasWidget->SetDefaultBorderColor(ScriptCanvasEditor::SourceDescription::GetDisplayColor());
  68. GraphTabMetadata replacement = tabDataVariant.value<GraphTabMetadata>();
  69. replacement.m_canvasWidget = canvasWidget;
  70. tabDataVariant.setValue(replacement);
  71. setTabData(tabIndex, tabDataVariant);
  72. }
  73. return tabDataVariant.value<GraphTabMetadata>().m_canvasWidget;
  74. }
  75. }
  76. return nullptr;
  77. }
  78. CanvasWidget* GraphTabBar::ModTabView(int tabIndex)
  79. {
  80. if (tabIndex < count())
  81. {
  82. if (QVariant tabDataVariant = tabData(tabIndex); tabDataVariant.isValid())
  83. {
  84. return tabDataVariant.value<GraphTabMetadata>().m_canvasWidget;
  85. }
  86. }
  87. return nullptr;
  88. }
  89. AZStd::optional<GraphTabMetadata> GraphTabBar::GetTabData(int tabIndex) const
  90. {
  91. if (tabIndex < count())
  92. {
  93. if (QVariant tabDataVariant = tabData(tabIndex); tabDataVariant.isValid())
  94. {
  95. return tabDataVariant.value<GraphTabMetadata>();
  96. }
  97. }
  98. return AZStd::nullopt;
  99. }
  100. AZStd::optional<GraphTabMetadata> GraphTabBar::GetTabData(SourceHandle assetId) const
  101. {
  102. return GetTabData(FindTab(assetId));
  103. }
  104. void GraphTabBar::SetTabData(const GraphTabMetadata& metadata, int tabIndex)
  105. {
  106. if (tabIndex < count())
  107. {
  108. setTabData(tabIndex, QVariant::fromValue(metadata));
  109. }
  110. }
  111. void GraphTabBar::SetTabData(const GraphTabMetadata& metadata, SourceHandle assetId)
  112. {
  113. auto index = FindTab(assetId);
  114. auto replacement = GetTabData(assetId);
  115. if (index >= 0 && replacement)
  116. {
  117. replacement->m_assetId = assetId;
  118. SetTabData(metadata, index);
  119. }
  120. }
  121. int GraphTabBar::InsertGraphTab(int tabIndex, SourceHandle assetId, Tracker::ScriptCanvasFileState fileState)
  122. {
  123. if (!SelectTab(assetId))
  124. {
  125. QIcon tabIcon = QIcon(ScriptCanvasEditor::SourceDescription::GetIconPath());
  126. tabIndex = qobject_cast<AzQtComponents::TabWidget*>(parent())->insertTab(tabIndex, new QWidget(), tabIcon, "");
  127. GraphTabMetadata metaData;
  128. CanvasWidget* canvasWidget = new CanvasWidget(assetId, this);
  129. canvasWidget->SetDefaultBorderColor(SourceDescription::GetDisplayColor());
  130. metaData.m_canvasWidget = canvasWidget;
  131. metaData.m_assetId = assetId;
  132. metaData.m_fileState = fileState;
  133. AZStd::string tabName;
  134. AzFramework::StringFunc::Path::GetFileName(assetId.RelativePath().c_str(), tabName);
  135. SetTabText(tabIndex, tabName.c_str(), fileState);
  136. setTabData(tabIndex, QVariant::fromValue(metaData));
  137. return tabIndex;
  138. }
  139. return -1;
  140. }
  141. bool GraphTabBar::SelectTab(SourceHandle assetId)
  142. {
  143. int tabIndex = FindTab(assetId);
  144. if (-1 != tabIndex)
  145. {
  146. setCurrentIndex(tabIndex);
  147. return true;
  148. }
  149. return false;
  150. }
  151. int GraphTabBar::FindTab(SourceHandle assetId) const
  152. {
  153. for (int tabIndex = 0; tabIndex < count(); ++tabIndex)
  154. {
  155. QVariant tabDataVariant = tabData(tabIndex);
  156. if (tabDataVariant.isValid())
  157. {
  158. auto tabAssetId = tabDataVariant.value<GraphTabMetadata>();
  159. if (tabAssetId.m_assetId.AnyEquals(assetId))
  160. {
  161. return tabIndex;
  162. }
  163. }
  164. }
  165. return -1;
  166. }
  167. int GraphTabBar::FindTab(ScriptCanvasEditor::GraphPtrConst graph) const
  168. {
  169. for (int tabIndex = 0; tabIndex < count(); ++tabIndex)
  170. {
  171. QVariant tabDataVariant = tabData(tabIndex);
  172. if (tabDataVariant.isValid())
  173. {
  174. auto tabAssetId = tabDataVariant.value<GraphTabMetadata>();
  175. if (tabAssetId.m_assetId.Get() == graph)
  176. {
  177. return tabIndex;
  178. }
  179. }
  180. }
  181. return -1;
  182. }
  183. int GraphTabBar::FindSaveOverMatch(SourceHandle assetId) const
  184. {
  185. for (int tabIndex = 0; tabIndex < count(); ++tabIndex)
  186. {
  187. QVariant tabDataVariant = tabData(tabIndex);
  188. if (tabDataVariant.isValid())
  189. {
  190. auto tabAssetId = tabDataVariant.value<GraphTabMetadata>();
  191. if (tabAssetId.m_assetId.Get() != assetId.Get() && tabAssetId.m_assetId.PathEquals(assetId))
  192. {
  193. return tabIndex;
  194. }
  195. }
  196. }
  197. return -1;
  198. }
  199. SourceHandle GraphTabBar::FindTabByPath(AZStd::string_view path) const
  200. {
  201. SourceHandle candidate;
  202. candidate = SourceHandle::MarkAbsolutePath(candidate, path);
  203. for (int index = 0; index < count(); ++index)
  204. {
  205. QVariant tabdata = tabData(index);
  206. if (tabdata.isValid())
  207. {
  208. auto tabAssetId = tabdata.value<GraphTabMetadata>();
  209. if (tabAssetId.m_assetId.AnyEquals(candidate))
  210. {
  211. return tabAssetId.m_assetId;
  212. }
  213. }
  214. }
  215. return {};
  216. }
  217. SourceHandle GraphTabBar::FindAssetId(int tabIndex)
  218. {
  219. QVariant dataVariant = tabData(tabIndex);
  220. if (dataVariant.isValid())
  221. {
  222. auto tabAssetId = dataVariant.value<GraphTabMetadata>();
  223. return tabAssetId.m_assetId;
  224. }
  225. return SourceHandle();
  226. }
  227. ScriptCanvas::ScriptCanvasId GraphTabBar::FindScriptCanvasIdFromGraphCanvasId(const GraphCanvas::GraphId& graphCanvasGraphId) const
  228. {
  229. for (int index = 0; index < count(); ++index)
  230. {
  231. QVariant tabdata = tabData(index);
  232. if (tabdata.isValid())
  233. {
  234. auto tabAssetId = tabdata.value<GraphTabMetadata>();
  235. if (tabAssetId.m_assetId.IsGraphValid()
  236. && tabAssetId.m_assetId.Get()->GetGraphCanvasGraphId() == graphCanvasGraphId)
  237. {
  238. return tabAssetId.m_assetId.Get()->GetScriptCanvasId();
  239. }
  240. }
  241. }
  242. return ScriptCanvas::ScriptCanvasId{};
  243. }
  244. void GraphTabBar::CloseTab(int index)
  245. {
  246. if (index >= 0 && index < count())
  247. {
  248. qobject_cast<AzQtComponents::TabWidget*>(parent())->removeTab(index);
  249. }
  250. }
  251. void GraphTabBar::CloseAllTabs()
  252. {
  253. for (int i = count() - 1; i >= 0; --i)
  254. {
  255. Q_EMIT TabCloseNoButton(i);
  256. }
  257. }
  258. void GraphTabBar::OnContextMenu(const QPoint& point)
  259. {
  260. QPoint screenPoint = mapToGlobal(point);
  261. int tabIndex = tabAt(point);
  262. bool hasValidTab = (tabIndex >= 0);
  263. bool isModified = false;
  264. QVariant tabdata = tabData(tabIndex);
  265. if (tabdata.isValid())
  266. {
  267. auto tabAssetId = tabdata.value<GraphTabMetadata>();
  268. Tracker::ScriptCanvasFileState fileState = Tracker::ScriptCanvasFileState::INVALID;
  269. isModified = fileState == Tracker::ScriptCanvasFileState::NEW || fileState == Tracker::ScriptCanvasFileState::MODIFIED;
  270. }
  271. QMenu menu;
  272. QAction* saveAction = menu.addAction("Save");
  273. saveAction->setEnabled(hasValidTab && isModified);
  274. QAction* closeAction = menu.addAction("Close");
  275. closeAction->setEnabled(hasValidTab);
  276. QAction* closeAllAction = menu.addAction("Close All");
  277. QAction* closeAllButThis = menu.addAction("Close All But This");
  278. closeAllButThis->setEnabled(hasValidTab);
  279. menu.addSeparator();
  280. QAction* fullPathAction = menu.addAction("Copy Source Path To Clipboard");
  281. fullPathAction->setEnabled(hasValidTab);
  282. QAction* action = menu.exec(screenPoint);
  283. if (action)
  284. {
  285. if (action == saveAction)
  286. {
  287. if (tabIndex != currentIndex())
  288. {
  289. m_signalSaveOnChangeTo = tabIndex;
  290. setCurrentIndex(tabIndex);
  291. }
  292. else
  293. {
  294. Q_EMIT SaveTab(tabIndex);
  295. }
  296. }
  297. else if (action == closeAction)
  298. {
  299. tabCloseRequested(tabIndex);
  300. }
  301. else if (action == closeAllAction)
  302. {
  303. Q_EMIT CloseAllTabsSignal();
  304. }
  305. else if (action == closeAllButThis)
  306. {
  307. Q_EMIT CloseAllTabsButSignal(tabIndex);
  308. }
  309. else if (action == fullPathAction)
  310. {
  311. Q_EMIT CopyPathToClipboard(tabIndex);
  312. }
  313. }
  314. }
  315. void GraphTabBar::mouseReleaseEvent(QMouseEvent* event)
  316. {
  317. if (event->button() == Qt::MidButton)
  318. {
  319. int tabIndex = tabAt(event->localPos().toPoint());
  320. if (tabIndex >= 0)
  321. {
  322. tabCloseRequested(tabIndex);
  323. return;
  324. }
  325. }
  326. AzQtComponents::TabBar::mouseReleaseEvent(event);
  327. }
  328. void GraphTabBar::SetTabText(int tabIndex, const QString& path, Tracker::ScriptCanvasFileState fileState)
  329. {
  330. QString safePath = path;
  331. if (path.endsWith("^") || path.endsWith("*"))
  332. {
  333. safePath.chop(1);
  334. }
  335. if (tabIndex >= 0 && tabIndex < count())
  336. {
  337. const char* fileStateTag = "";
  338. switch (fileState)
  339. {
  340. case Tracker::ScriptCanvasFileState::NEW:
  341. fileStateTag = "^";
  342. break;
  343. case Tracker::ScriptCanvasFileState::SOURCE_REMOVED:
  344. case Tracker::ScriptCanvasFileState::MODIFIED:
  345. fileStateTag = "*";
  346. break;
  347. default:
  348. break;
  349. }
  350. setTabText(tabIndex, QString("%1%2").arg(safePath).arg(fileStateTag));
  351. }
  352. }
  353. void GraphTabBar::tabInserted(int index)
  354. {
  355. AzQtComponents::TabBar::tabInserted(index);
  356. Q_EMIT TabInserted(index);
  357. }
  358. void GraphTabBar::tabRemoved(int index)
  359. {
  360. AzQtComponents::TabBar::tabRemoved(index);
  361. Q_EMIT TabRemoved(index);
  362. }
  363. void GraphTabBar::UpdateFileState(const SourceHandle& assetId, Tracker::ScriptCanvasFileState fileState)
  364. {
  365. auto tabData = GetTabData(assetId);
  366. if (tabData && tabData->m_fileState != Tracker::ScriptCanvasFileState::NEW && tabData->m_fileState != fileState)
  367. {
  368. int index = FindTab(assetId);
  369. tabData->m_fileState = fileState;
  370. SetTabData(*tabData, assetId);
  371. SetTabText(index, tabText(index), fileState);
  372. if (index == currentIndex())
  373. {
  374. Q_EMIT OnActiveFileStateChanged();
  375. }
  376. }
  377. }
  378. void GraphTabBar::currentChangedTab(int index)
  379. {
  380. if (index < 0)
  381. {
  382. return;
  383. }
  384. QVariant tabdata = tabData(index);
  385. if (!tabdata.isValid())
  386. {
  387. return;
  388. }
  389. auto assetId = tabdata.value<GraphTabMetadata>().m_assetId;
  390. ScriptCanvasEditor::GeneralRequestBus::Broadcast(&ScriptCanvasEditor::GeneralRequests::OnChangeActiveGraphTab, assetId);
  391. if (m_signalSaveOnChangeTo >= 0 && m_signalSaveOnChangeTo == index)
  392. {
  393. m_signalSaveOnChangeTo = -1;
  394. Q_EMIT SaveTab(m_signalSaveOnChangeTo);
  395. }
  396. }
  397. #include <Editor/View/Widgets/moc_GraphTabBar.cpp>
  398. }
  399. }