BreakpointPanel.cpp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  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 "BreakpointPanel.hxx"
  9. #include <Source/LUA/moc_BreakpointPanel.cpp>
  10. #include <AzCore/Debug/Trace.h>
  11. #include <QAction>
  12. DHBreakpointsWidget::DHBreakpointsWidget(QWidget* parent)
  13. : QTableWidget(parent)
  14. , m_PauseUpdates(false)
  15. {
  16. connect(this, SIGNAL(doubleClicked(const QModelIndex &)), this, SLOT(OnDoubleClicked(const QModelIndex &)));
  17. LUABreakpointTrackerMessages::Handler::BusConnect();
  18. CreateContextMenu();
  19. }
  20. DHBreakpointsWidget::~DHBreakpointsWidget()
  21. {
  22. LUABreakpointTrackerMessages::Handler::BusDisconnect();
  23. clearContents();
  24. setRowCount(0);
  25. }
  26. void DHBreakpointsWidget::PullFromContext()
  27. {
  28. const LUAEditor::BreakpointMap* myData = NULL;
  29. LUAEditor::LUABreakpointRequestMessages::Bus::BroadcastResult(
  30. myData, &LUAEditor::LUABreakpointRequestMessages::Bus::Events::RequestBreakpoints);
  31. AZ_Assert(myData, "Nobody responded to the request breakpoints message.");
  32. BreakpointsUpdate(*myData);
  33. }
  34. void DHBreakpointsWidget::CreateContextMenu()
  35. {
  36. actionDeleteAll = new QAction(tr("Delete All"), this);
  37. connect(actionDeleteAll, SIGNAL(triggered()), this, SLOT(DeleteAll()));
  38. actionDeleteSelected = new QAction(tr("Delete Selected"), this);
  39. connect(actionDeleteSelected, SIGNAL(triggered()), this, SLOT(DeleteSelected()));
  40. addAction(actionDeleteAll);
  41. addAction(actionDeleteSelected);
  42. setContextMenuPolicy(Qt::ActionsContextMenu);
  43. }
  44. void DHBreakpointsWidget::DeleteAll()
  45. {
  46. while (rowCount())
  47. {
  48. RemoveRow(0);
  49. }
  50. }
  51. void DHBreakpointsWidget::DeleteSelected()
  52. {
  53. m_PauseUpdates = true;
  54. QList<QTableWidgetItem*> list = selectedItems();
  55. for (int i = list.size() - 1; i >= 0; i -= 2) // magic number 2 is the column count, will be 3 if the empty first column ever gets contents
  56. {
  57. RemoveRow(list.at(i)->row());
  58. }
  59. m_PauseUpdates = false;
  60. PullFromContext();
  61. }
  62. //////////////////////////////////////////////////////////////////////////
  63. //Debugger Messages, from the LUAEditor::LUABreakpointTrackerMessages::Bus
  64. void DHBreakpointsWidget::BreakpointsUpdate(const LUAEditor::BreakpointMap& uniqueBreakpoints)
  65. {
  66. if (!m_PauseUpdates)
  67. {
  68. // not using DeleteAll() here, this is an outside message so we only need to do internal housekeeping
  69. while (rowCount())
  70. {
  71. removeRow(0);
  72. }
  73. for (LUAEditor::BreakpointMap::const_iterator it = uniqueBreakpoints.begin(); it != uniqueBreakpoints.end(); ++it)
  74. {
  75. const LUAEditor::Breakpoint& bp = it->second;
  76. // sanity check to hopefully bypass corrupted entries
  77. // in a pure world this should never trigger
  78. //if ( (bp.m_documentLine >= 0) && (bp.m_blob.length() >= 5) ) // magic number 5
  79. {
  80. CreateBreakpoint(bp.m_assetName, bp.m_documentLine);
  81. }
  82. //else
  83. //{
  84. // AZ_TracePrintf("BP", "Corrupted Breakpoint %s at line %d Was Stripped From Incoming Data\n", bp.m_blob, bp.m_documentLine);
  85. //}
  86. }
  87. }
  88. }
  89. void DHBreakpointsWidget::BreakpointHit(const LUAEditor::Breakpoint& bp)
  90. {
  91. // clear any previous hit
  92. selectionModel()->clearSelection();
  93. // scroll to and highlight this one
  94. QList<QTableWidgetItem*> list = findItems(bp.m_assetName.c_str(), Qt::MatchExactly);
  95. QString q;
  96. q.setNum(bp.m_documentLine + 1); // +1 offset to match editor numbering
  97. for (int i = list.size() - 1; i >= 0; --i)
  98. {
  99. // magic number column #0 is the line number, 1 is the script file name
  100. QTableWidgetItem* line = item(list.at(i)->row(), 0);
  101. if (line->text() == q)
  102. {
  103. QModelIndex indexInModel = indexFromItem(line);
  104. selectionModel()->select(indexInModel, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows);
  105. setCurrentIndex(indexInModel);
  106. break;
  107. }
  108. }
  109. }
  110. void DHBreakpointsWidget::BreakpointResume()
  111. {
  112. // no op
  113. }
  114. void DHBreakpointsWidget::CreateBreakpoint(const AZStd::string& debugName, int lineNumber)
  115. {
  116. //AZ_TracePrintf("BP", "CreateBreakpoint %s at line %d\n", debugName.c_str(), lineNumber);
  117. int newRow = rowCount();
  118. insertRow(newRow);
  119. // magic number column #0 is the line number, 1 is the script file name
  120. QTableWidgetItem* newItem = new QTableWidgetItem(debugName.c_str());
  121. newItem->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
  122. setItem(newRow, 1, newItem);
  123. newItem = new QTableWidgetItem(QString().setNum(lineNumber));
  124. newItem->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
  125. setItem(newRow, 0, newItem);
  126. }
  127. void DHBreakpointsWidget::RemoveBreakpoint(const AZStd::string& debugName, int lineNumber)
  128. {
  129. //AZ_TracePrintf("BP", "RemoveBreakpoint %s at line %d\n", debugName.c_str(), lineNumber);
  130. QList<QTableWidgetItem*> list = findItems(debugName.c_str(), Qt::MatchExactly);
  131. QString q;
  132. q.setNum(lineNumber + 1); // +1 offset to match editor numbering
  133. for (int i = list.size() - 1; i >= 0; --i)
  134. {
  135. // magic number column #0 is the line number, 1 is the script file name
  136. QTableWidgetItem* line = item(list.at(i)->row(), 0);
  137. if (line->text() == q)
  138. {
  139. RemoveRow(list.at(i)->row());
  140. break;
  141. }
  142. }
  143. }
  144. // QT table view messages
  145. void DHBreakpointsWidget::OnDoubleClicked(const QModelIndex& modelIdx)
  146. {
  147. //AZ_TracePrintf("BP", "OnDoubleClicked() %d, %d\n", modelIdx.row(), modelIdx.column());
  148. // magic number column #0 is the line number, 1 is the script file name
  149. QTableWidgetItem* line = item(modelIdx.row(), 0);
  150. QTableWidgetItem* file = item(modelIdx.row(), 1);
  151. LUAEditor::LUABreakpointRequestMessages::Bus::Broadcast(
  152. &LUAEditor::LUABreakpointRequestMessages::Bus::Events::RequestEditorFocus,
  153. AZStd::string(file->data(Qt::DisplayRole).toString().toUtf8().data()),
  154. line->data(Qt::DisplayRole).toInt());
  155. }
  156. void DHBreakpointsWidget::RemoveRow(int which)
  157. {
  158. // magic number column #0 is the line number, 1 is the script file name
  159. QTableWidgetItem* line = item(which, 0);
  160. QTableWidgetItem* file = item(which, 1);
  161. QByteArray fileName = file->data(Qt::DisplayRole).toString().toUtf8().data();
  162. int lineNumber = line->data(Qt::DisplayRole).toInt();
  163. LUAEditor::LUABreakpointRequestMessages::Bus::Broadcast(
  164. &LUAEditor::LUABreakpointRequestMessages::Bus::Events::RequestDeleteBreakpoint, AZStd::string(fileName.constData()), lineNumber);
  165. }