2 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Copyright 2011-2017, Rene Gollent, rene@gollent.com.
4 * Distributed under the terms of the MIT License.
8 #include "ThreadListView.h"
15 #include <AutoLocker.h>
16 #include <ObjectList.h>
19 #include "GuiSettingsUtils.h"
20 #include "table/TableColumns.h"
25 MSG_SYNC_THREAD_LIST
= 'sytl'
29 // #pragma mark - ThreadsTableModel
32 class ThreadListView::ThreadsTableModel
: public TableModel
,
33 public TableToolTipProvider
{
35 ThreadsTableModel(Team
* team
)
48 bool Update(thread_id threadID
)
51 for (int32 i
= 0; Thread
* thread
= fThreads
.ItemAt(i
); i
++)
52 thread
->ReleaseReference();
58 AutoLocker
<Team
> locker(fTeam
);
60 ThreadList::ConstIterator it
= fTeam
->Threads().GetIterator();
61 Thread
* newThread
= it
.Next();
64 // remove no longer existing threads
65 while (Thread
* oldThread
= fThreads
.ItemAt(index
)) {
66 if (oldThread
== newThread
) {
67 if (threadID
>= 0 && oldThread
->ID() == threadID
)
68 NotifyRowsChanged(index
, 1);
70 newThread
= it
.Next();
72 // TODO: Not particularly efficient!
73 fThreads
.RemoveItemAt(index
);
74 oldThread
->ReleaseReference();
75 NotifyRowsRemoved(index
, 1);
80 int32 countBefore
= fThreads
.CountItems();
81 while (newThread
!= NULL
) {
82 if (!fThreads
.AddItem(newThread
))
85 newThread
->AcquireReference();
86 newThread
= it
.Next();
89 int32 count
= fThreads
.CountItems();
90 if (count
> countBefore
)
91 NotifyRowsAdded(countBefore
, count
- countBefore
);
96 virtual int32
CountColumns() const
101 virtual int32
CountRows() const
103 return fThreads
.CountItems();
106 virtual bool GetValueAt(int32 rowIndex
, int32 columnIndex
, BVariant
& value
)
108 Thread
* thread
= fThreads
.ItemAt(rowIndex
);
112 switch (columnIndex
) {
114 value
.SetTo(thread
->ID());
118 const char* string
= UiUtils::ThreadStateToString(
119 thread
->State(), thread
->StoppedReason());
120 value
.SetTo(string
, B_VARIANT_DONT_COPY_DATA
);
124 value
.SetTo(thread
->Name(), B_VARIANT_DONT_COPY_DATA
);
128 if (thread
->State() != THREAD_STATE_RUNNING
) {
129 value
.SetTo(thread
->StoppedReasonInfo(),
130 B_VARIANT_DONT_COPY_DATA
);
140 virtual bool GetToolTipForTableCell(int32 rowIndex
, int32 columnIndex
,
143 Thread
* thread
= fThreads
.ItemAt(rowIndex
);
148 text
<< "Thread: \"" << thread
->Name() << "\" (" << thread
->ID()
151 switch (thread
->State()) {
152 case THREAD_STATE_RUNNING
:
155 case THREAD_STATE_STOPPED
:
157 switch (thread
->StoppedReason()) {
158 case THREAD_STOPPED_DEBUGGER_CALL
:
159 text
<< "Called debugger(): "
160 << thread
->StoppedReasonInfo();
162 case THREAD_STOPPED_EXCEPTION
:
163 text
<< "Caused exception: "
164 << thread
->StoppedReasonInfo();
166 case THREAD_STOPPED_BREAKPOINT
:
167 case THREAD_STOPPED_WATCHPOINT
:
168 case THREAD_STOPPED_SINGLE_STEP
:
169 case THREAD_STOPPED_DEBUGGED
:
170 case THREAD_STOPPED_UNKNOWN
:
172 text
<< "Stopped for debugging";
177 case THREAD_STATE_UNKNOWN
:
179 text
<< "Current State Unknown";
183 BTextToolTip
* tip
= new(std::nothrow
) BTextToolTip(text
);
191 Thread
* ThreadAt(int32 index
) const
193 return fThreads
.ItemAt(index
);
198 BObjectList
<Thread
> fThreads
;
202 // #pragma mark - ThreadListView
205 ThreadListView::ThreadListView(Team
* team
, Listener
* listener
)
207 BGroupView(B_VERTICAL
),
211 fThreadsTableModel(NULL
),
218 ThreadListView::~ThreadListView()
220 fTeam
->RemoveListener(this);
221 fThreadsTable
->SetTableModel(NULL
);
222 delete fThreadsTableModel
;
226 /*static*/ ThreadListView
*
227 ThreadListView::Create(Team
* team
, Listener
* listener
)
229 ThreadListView
* self
= new ThreadListView(team
, listener
);
243 ThreadListView::UnsetListener()
250 ThreadListView::SetThread(Thread
* thread
)
252 if (thread
== fThread
)
256 fThread
->ReleaseReference();
260 if (fThread
!= NULL
) {
261 fThread
->AcquireReference();
263 for (int32 i
= 0; Thread
* other
= fThreadsTableModel
->ThreadAt(i
);
265 if (fThread
== other
) {
266 fThreadsTable
->SelectRow(i
, false);
272 fThreadsTable
->DeselectAllRows();
277 ThreadListView::MessageReceived(BMessage
* message
)
279 switch (message
->what
) {
280 case MSG_SYNC_THREAD_LIST
:
283 if (message
->FindInt32("thread", &threadID
) != B_OK
)
286 fThreadsTableModel
->Update(threadID
);
290 BGroupView::MessageReceived(message
);
297 ThreadListView::LoadSettings(const BMessage
& settings
)
299 BMessage tableSettings
;
300 if (settings
.FindMessage("threadsTable", &tableSettings
) == B_OK
) {
301 GuiSettingsUtils::UnarchiveTableSettings(tableSettings
,
308 ThreadListView::SaveSettings(BMessage
& settings
)
310 settings
.MakeEmpty();
312 BMessage tableSettings
;
313 status_t result
= GuiSettingsUtils::ArchiveTableSettings(tableSettings
,
316 result
= settings
.AddMessage("threadsTable", &tableSettings
);
325 ThreadListView::ThreadAdded(const Team::ThreadEvent
& event
)
327 Looper()->PostMessage(MSG_SYNC_THREAD_LIST
, this);
332 ThreadListView::ThreadRemoved(const Team::ThreadEvent
& event
)
334 Looper()->PostMessage(MSG_SYNC_THREAD_LIST
, this);
339 ThreadListView::ThreadStateChanged(const Team::ThreadEvent
& event
)
341 BMessage
message(MSG_SYNC_THREAD_LIST
);
342 message
.AddInt32("thread", event
.GetThread()->ID());
344 Looper()->PostMessage(&message
, this);
349 ThreadListView::TableSelectionChanged(Table
* table
)
351 if (fListener
== NULL
)
354 Thread
* thread
= NULL
;
355 TableSelectionModel
* selectionModel
= table
->SelectionModel();
356 thread
= fThreadsTableModel
->ThreadAt(selectionModel
->RowAt(0));
358 fListener
->ThreadSelectionChanged(thread
);
363 ThreadListView::_Init()
365 fThreadsTable
= new Table("threads list", 0, B_FANCY_BORDER
);
366 AddChild(fThreadsTable
->ToView());
369 fThreadsTable
->AddColumn(new Int32TableColumn(0, "ID", 60, 20, 1000,
370 B_TRUNCATE_MIDDLE
, B_ALIGN_RIGHT
));
371 fThreadsTable
->AddColumn(new StringTableColumn(1, "State", 80, 40, 1000,
372 B_TRUNCATE_END
, B_ALIGN_LEFT
));
373 fThreadsTable
->AddColumn(new StringTableColumn(2, "Name", 200, 40, 1000,
374 B_TRUNCATE_END
, B_ALIGN_LEFT
));
375 fThreadsTable
->AddColumn(new StringTableColumn(3, "Stop reason",
376 200, 40, 1000, B_TRUNCATE_END
, B_ALIGN_LEFT
));
378 fThreadsTable
->SetSelectionMode(B_SINGLE_SELECTION_LIST
);
379 fThreadsTable
->AddTableListener(this);
381 fThreadsTableModel
= new ThreadsTableModel(fTeam
);
382 fThreadsTable
->SetTableModel(fThreadsTableModel
);
383 fThreadsTable
->SetToolTipProvider(fThreadsTableModel
);
384 fTeam
->AddListener(this);
388 // #pragma mark - Listener
391 ThreadListView::Listener::~Listener()