|
@@ -7,16 +7,70 @@
|
|
|
#include "ThreadStackWidget.h"
|
|
|
#include <LibCore/Timer.h>
|
|
|
#include <LibGUI/BoxLayout.h>
|
|
|
+#include <LibGUI/Model.h>
|
|
|
#include <LibSymbolication/Symbolication.h>
|
|
|
#include <LibThreading/BackgroundAction.h>
|
|
|
|
|
|
+class ThreadStackModel final : public GUI::Model {
|
|
|
+
|
|
|
+ enum Column {
|
|
|
+ Address,
|
|
|
+ Object,
|
|
|
+ Symbol
|
|
|
+ };
|
|
|
+
|
|
|
+public:
|
|
|
+ int column_count(GUI::ModelIndex const&) const override { return 3; };
|
|
|
+ int row_count(GUI::ModelIndex const&) const override { return m_symbols.size(); };
|
|
|
+ bool is_column_sortable(int) const override { return false; }
|
|
|
+
|
|
|
+ String column_name(int column) const override
|
|
|
+ {
|
|
|
+ switch (column) {
|
|
|
+ case Column::Address:
|
|
|
+ return "Address";
|
|
|
+ case Column::Object:
|
|
|
+ return "Object";
|
|
|
+ case Column::Symbol:
|
|
|
+ return "Symbol";
|
|
|
+ default:
|
|
|
+ VERIFY_NOT_REACHED();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ GUI::Variant data(GUI::ModelIndex const& model_index, GUI::ModelRole) const override
|
|
|
+ {
|
|
|
+ auto& symbol = m_symbols[model_index.row()];
|
|
|
+ switch (model_index.column()) {
|
|
|
+ case Column::Address:
|
|
|
+ return String::formatted("{:p}", symbol.address);
|
|
|
+ case Column::Object:
|
|
|
+ return symbol.object;
|
|
|
+ case Column::Symbol:
|
|
|
+ return symbol.name;
|
|
|
+ default:
|
|
|
+ VERIFY_NOT_REACHED();
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ void set_symbols(Vector<Symbolication::Symbol> const& symbols)
|
|
|
+ {
|
|
|
+ if (m_symbols == symbols)
|
|
|
+ return;
|
|
|
+ m_symbols = symbols;
|
|
|
+ invalidate();
|
|
|
+ }
|
|
|
+
|
|
|
+private:
|
|
|
+ Vector<Symbolication::Symbol> m_symbols;
|
|
|
+};
|
|
|
+
|
|
|
ThreadStackWidget::ThreadStackWidget()
|
|
|
{
|
|
|
set_layout<GUI::VerticalBoxLayout>();
|
|
|
layout()->set_margins(4);
|
|
|
- m_stack_editor = add<GUI::TextEditor>();
|
|
|
- m_stack_editor->set_mode(GUI::TextEditor::ReadOnly);
|
|
|
- m_stack_editor->set_text("Symbolicating...");
|
|
|
+ m_stack_table = add<GUI::TableView>();
|
|
|
+ m_stack_table->set_model(adopt_ref(*new ThreadStackModel()));
|
|
|
}
|
|
|
|
|
|
ThreadStackWidget::~ThreadStackWidget()
|
|
@@ -74,17 +128,5 @@ void ThreadStackWidget::refresh()
|
|
|
void ThreadStackWidget::custom_event(Core::CustomEvent& event)
|
|
|
{
|
|
|
auto& completion_event = verify_cast<CompletionEvent>(event);
|
|
|
-
|
|
|
- StringBuilder builder;
|
|
|
-
|
|
|
- for (auto& symbol : completion_event.symbols()) {
|
|
|
- builder.appendff("{:p} {:30s}", symbol.address, symbol.object);
|
|
|
- if (!symbol.name.is_empty())
|
|
|
- builder.appendff(" {}", symbol.name);
|
|
|
- builder.append('\n');
|
|
|
- }
|
|
|
-
|
|
|
- if (m_stack_editor->text() != builder.string_view()) {
|
|
|
- m_stack_editor->set_text(builder.string_view());
|
|
|
- }
|
|
|
+ verify_cast<ThreadStackModel>(m_stack_table->model())->set_symbols(completion_event.symbols());
|
|
|
}
|