* Made Model a Referenceable, so we can juggle it in different windows without

ownership headaches.
* Added some more Model::Team/Thread getters.
* Added ThreadWindow, a window presenting information on a thread. There's only
  a page with general information yet. The window can be opened by
  double-clicking on a thread in the threads table.
* The pages are now inner classes of their respective windows.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@30403 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2009-04-25 16:59:44 +00:00
parent a6dbddff43
commit df540b5095
15 changed files with 506 additions and 28 deletions
@@ -0,0 +1,46 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#include "AbstractGeneralPage.h"
#include <GridLayoutBuilder.h>
#include <GroupLayoutBuilder.h>
AbstractGeneralPage::AbstractGeneralPage()
:
BGroupView(B_VERTICAL),
fDataView(NULL)
{
SetName("General");
GroupLayout()->SetInsets(10, 10, 10, 10);
BGroupLayoutBuilder(this)
.Add(fDataView = new BGridView(10, 5))
.AddGlue()
;
}
AbstractGeneralPage::~AbstractGeneralPage()
{
}
/*! Throws std::bad_alloc.
*/
TextDataView*
AbstractGeneralPage::AddDataView(const char* label, const char* text)
{
BGridLayout* layout = fDataView->GridLayout();
int32 row = layout->CountRows();
layout->AddView(new LabelView(label), 0, row);
TextDataView* dataView = new TextDataView(text);
layout->AddView(dataView, 1, row);
return dataView;
}
@@ -0,0 +1,60 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef ABSTRACT_GENERAL_PAGE_H
#define ABSTRACT_GENERAL_PAGE_H
#include <GroupView.h>
#include <StringView.h>
class BGridView;
class LabelView : public BStringView {
public:
LabelView(const char* text)
:
BStringView(NULL, text)
{
SetExplicitAlignment(BAlignment(B_ALIGN_RIGHT,
B_ALIGN_VERTICAL_CENTER));
}
};
class TextDataView : public BStringView {
public:
TextDataView()
:
BStringView(NULL, "")
{
SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET));
}
TextDataView(const char* text)
:
BStringView(NULL, text)
{
SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET));
}
};
class AbstractGeneralPage : public BGroupView {
public:
AbstractGeneralPage();
virtual ~AbstractGeneralPage();
protected:
TextDataView* AddDataView(const char* label,
const char* text = NULL);
protected:
BGridView* fDataView;
};
#endif // ABSTRACT_GENERAL_PAGE_H
+2 -1
View File
@@ -14,9 +14,10 @@
#include <AutoDeleter.h> #include <AutoDeleter.h>
#include "DataSource.h" #include "DataSource.h"
#include "MainWindow.h"
#include "MessageCodes.h" #include "MessageCodes.h"
#include "main_window/MainWindow.h"
static const char* const kSignature = "application/x-vnd.Haiku-DebugAnalyzer"; static const char* const kSignature = "application/x-vnd.Haiku-DebugAnalyzer";
+13 -4
View File
@@ -7,16 +7,25 @@ SEARCH_SOURCE += [ FDirName $(SUBDIR) main_window ] ;
Application DebugAnalyzer Application DebugAnalyzer
: :
AbstractGeneralPage.cpp
DataSource.cpp DataSource.cpp
DebugAnalyzer.cpp DebugAnalyzer.cpp
MainWindow.cpp
Model.cpp Model.cpp
ModelLoader.cpp ModelLoader.cpp
SubWindow.cpp
SubWindowManager.cpp
Table.cpp Table.cpp
TableColumns.cpp TableColumns.cpp
ThreadsPage.cpp
Variant.cpp Variant.cpp
: libcolumnlistview.a libdebug.so be :
: DebugAnalyzer.rdef <nogrist>DebugAnalyzer_MainWindow.o
<nogrist>DebugAnalyzer_ThreadWindow.o
libcolumnlistview.a libdebug.so be
:
DebugAnalyzer.rdef
; ;
HaikuSubInclude main_window ;
HaikuSubInclude thread_window ;
+20 -1
View File
@@ -8,11 +8,13 @@
#include <ObjectList.h> #include <ObjectList.h>
#include <OS.h> #include <OS.h>
#include <Referenceable.h>
#include <system_profiler_defs.h> #include <system_profiler_defs.h>
#include <util/SinglyLinkedList.h> #include <util/SinglyLinkedList.h>
class Model { class Model : public Referenceable {
public: public:
struct creation_time_id; struct creation_time_id;
struct type_and_object; struct type_and_object;
@@ -183,6 +185,7 @@ public:
~Team(); ~Team();
inline team_id ID() const; inline team_id ID() const;
inline const char* Name() const;
inline bigtime_t CreationTime() const; inline bigtime_t CreationTime() const;
inline bigtime_t DeletionTime() const; inline bigtime_t DeletionTime() const;
@@ -215,6 +218,7 @@ public:
inline thread_id ID() const; inline thread_id ID() const;
inline const char* Name() const; inline const char* Name() const;
inline Team* GetTeam() const;
inline bigtime_t CreationTime() const; inline bigtime_t CreationTime() const;
inline bigtime_t DeletionTime() const; inline bigtime_t DeletionTime() const;
@@ -459,6 +463,14 @@ Model::Team::ID() const
} }
const char*
Model::Team::Name() const
{
return fCreationEvent->name;
// TODO: We should probably return the last exec name!
}
bigtime_t bigtime_t
Model::Team::CreationTime() const Model::Team::CreationTime() const
{ {
@@ -511,6 +523,13 @@ Model::Thread::Name() const
} }
Model::Team*
Model::Thread::GetTeam() const
{
return fTeam;
}
bigtime_t bigtime_t
Model::Thread::CreationTime() const Model::Thread::CreationTime() const
{ {
@@ -0,0 +1,12 @@
SubDir HAIKU_TOP src apps debuganalyzer main_window ;
UsePrivateHeaders debug interface kernel shared ;
UsePrivateSystemHeaders ;
SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) ] ;
MergeObject DebugAnalyzer_MainWindow.o
:
MainWindow.cpp
ThreadsPage.cpp
;
@@ -7,17 +7,22 @@
#include <stdio.h> #include <stdio.h>
#include <new>
#include <Application.h> #include <Application.h>
#include <GroupLayoutBuilder.h> #include <GroupLayoutBuilder.h>
#include <TabView.h> #include <TabView.h>
#include <AutoDeleter.h>
#include <AutoLocker.h> #include <AutoLocker.h>
#include "DataSource.h" #include "DataSource.h"
#include "MessageCodes.h" #include "MessageCodes.h"
#include "Model.h"
#include "ModelLoader.h" #include "ModelLoader.h"
#include "ThreadsPage.h" #include "SubWindowManager.h"
#include "main_window/ThreadsPage.h"
#include "thread_window/ThreadWindow.h"
MainWindow::MainWindow(DataSource* dataSource) MainWindow::MainWindow(DataSource* dataSource)
@@ -25,10 +30,13 @@ MainWindow::MainWindow(DataSource* dataSource)
BWindow(BRect(50, 50, 599, 499), "DebugAnalyzer", B_DOCUMENT_WINDOW, BWindow(BRect(50, 50, 599, 499), "DebugAnalyzer", B_DOCUMENT_WINDOW,
B_ASYNCHRONOUS_CONTROLS), B_ASYNCHRONOUS_CONTROLS),
fMainTabView(NULL), fMainTabView(NULL),
fThreadsPage(new ThreadsPage), fThreadsPage(NULL),
fModel(NULL), fModel(NULL),
fModelLoader(NULL) fModelLoader(NULL),
fSubWindowManager(NULL)
{ {
fSubWindowManager = new SubWindowManager(this);
BGroupLayout* rootLayout = new BGroupLayout(B_VERTICAL); BGroupLayout* rootLayout = new BGroupLayout(B_VERTICAL);
SetLayout(rootLayout); SetLayout(rootLayout);
@@ -38,7 +46,7 @@ MainWindow::MainWindow(DataSource* dataSource)
.Add(fMainTabView); .Add(fMainTabView);
fMainTabView->AddTab(new BView("Teams", 0)); fMainTabView->AddTab(new BView("Teams", 0));
fMainTabView->AddTab(fThreadsPage); fMainTabView->AddTab(fThreadsPage = new ThreadsPage(this));
// create a model loader, if we have a data source // create a model loader, if we have a data source
if (dataSource != NULL) if (dataSource != NULL)
@@ -49,7 +57,11 @@ MainWindow::MainWindow(DataSource* dataSource)
MainWindow::~MainWindow() MainWindow::~MainWindow()
{ {
delete fModelLoader; delete fModelLoader;
delete fModel;
if (fModel != NULL)
fModel->RemoveReference();
fSubWindowManager->RemoveReference();
} }
@@ -63,8 +75,8 @@ printf("MSG_MODEL_LOADED_SUCCESSFULLY\n");
Model* model = fModelLoader->DetachModel(); Model* model = fModelLoader->DetachModel();
delete fModelLoader; delete fModelLoader;
fModelLoader = NULL; fModelLoader = NULL;
_SetModel(model); _SetModel(model);
model->RemoveReference();
break; break;
} }
@@ -88,6 +100,7 @@ printf("MSG_MODEL_LOADED_FAILED/MSG_MODEL_LOADED_ABORTED\n");
void void
MainWindow::Quit() MainWindow::Quit()
{ {
fSubWindowManager->Broadcast(B_QUIT_REQUESTED);
be_app->PostMessage(MSG_WINDOW_QUIT); be_app->PostMessage(MSG_WINDOW_QUIT);
BWindow::Quit(); BWindow::Quit();
@@ -113,11 +126,58 @@ MainWindow::Show()
} }
void
MainWindow::OpenThreadWindow(Model::Thread* thread)
{
// create a sub window key
ObjectSubWindowKey* key = new(std::nothrow) ObjectSubWindowKey(thread);
if (key == NULL) {
// TODO: Report error!
return;
}
ObjectDeleter<ObjectSubWindowKey> keyDeleter(key);
AutoLocker<SubWindowManager> locker(fSubWindowManager);
// check whether the window already exists
ThreadWindow* window = dynamic_cast<ThreadWindow*>(
fSubWindowManager->LookupSubWindow(*key));
if (window != NULL) {
// window exists -- just bring it to front
locker.Unlock();
window->Lock();
window->Activate();
return;
}
// window doesn't exist yet -- create it
try {
window = new ThreadWindow(fSubWindowManager, fModel, thread);
} catch (std::bad_alloc) {
// TODO: Report error!
}
if (!window->AddToSubWindowManager(key)) {
// TODO: Report error!
delete window;
}
keyDeleter.Detach();
window->Show();
}
void void
MainWindow::_SetModel(Model* model) MainWindow::_SetModel(Model* model)
{ {
delete fModel; if (fModel != NULL)
fModel->RemoveReference();
fModel = model; fModel = model;
if (fModel != NULL)
fModel->AddReference();
fThreadsPage->SetModel(fModel); fThreadsPage->SetModel(fModel);
} }
@@ -7,12 +7,13 @@
#include <Window.h> #include <Window.h>
#include "Model.h"
class BTabView; class BTabView;
class DataSource; class DataSource;
class ModelLoader; class ModelLoader;
class Model; class SubWindowManager;
class ThreadsPage;
class MainWindow : public BWindow { class MainWindow : public BWindow {
@@ -26,6 +27,11 @@ public:
virtual void Show(); virtual void Show();
void OpenThreadWindow(Model::Thread* thread);
private:
class ThreadsPage;
private: private:
void _SetModel(Model* model); void _SetModel(Model* model);
@@ -34,8 +40,8 @@ private:
ThreadsPage* fThreadsPage; ThreadsPage* fThreadsPage;
Model* fModel; Model* fModel;
ModelLoader* fModelLoader; ModelLoader* fModelLoader;
SubWindowManager* fSubWindowManager;
}; };
#endif // MAIN_WINDOW_H #endif // MAIN_WINDOW_H
@@ -3,20 +3,19 @@
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
#include "ThreadsPage.h" #include "main_window/ThreadsPage.h"
#include <stdio.h> #include <stdio.h>
#include <new> #include <new>
#include "Model.h"
#include "TableColumns.h" #include "TableColumns.h"
// #pragma mark - ThreadsTableModel // #pragma mark - ThreadsTableModel
class ThreadsPage::ThreadsTableModel : public TableModel { class MainWindow::ThreadsPage::ThreadsTableModel : public TableModel {
public: public:
ThreadsTableModel(Model* model) ThreadsTableModel(Model* model)
: :
@@ -87,9 +86,10 @@ private:
// #pragma mark - ThreadsPage // #pragma mark - ThreadsPage
ThreadsPage::ThreadsPage() MainWindow::ThreadsPage::ThreadsPage(MainWindow* parent)
: :
BGroupView(B_VERTICAL), BGroupView(B_VERTICAL),
fParent(parent),
fThreadsTable(NULL), fThreadsTable(NULL),
fThreadsTableModel(NULL), fThreadsTableModel(NULL),
fModel(NULL) fModel(NULL)
@@ -100,7 +100,7 @@ ThreadsPage::ThreadsPage()
fThreadsTable = new Table("threads list", 0); fThreadsTable = new Table("threads list", 0);
AddChild(fThreadsTable->ToView()); AddChild(fThreadsTable->ToView());
fThreadsTable->AddColumn(new Int32TableColumn(0, "Thread", 40, 20, 1000, fThreadsTable->AddColumn(new Int32TableColumn(0, "ID", 40, 20, 1000,
B_TRUNCATE_MIDDLE, B_ALIGN_RIGHT)); B_TRUNCATE_MIDDLE, B_ALIGN_RIGHT));
fThreadsTable->AddColumn(new StringTableColumn(1, "Name", 80, 40, 1000, fThreadsTable->AddColumn(new StringTableColumn(1, "Name", 80, 40, 1000,
B_TRUNCATE_END, B_ALIGN_LEFT)); B_TRUNCATE_END, B_ALIGN_LEFT));
@@ -122,10 +122,12 @@ ThreadsPage::ThreadsPage()
1000, B_TRUNCATE_END, B_ALIGN_RIGHT)); 1000, B_TRUNCATE_END, B_ALIGN_RIGHT));
fThreadsTable->AddColumn(new Int64TableColumn(10, "Preemptions", 80, 20, fThreadsTable->AddColumn(new Int64TableColumn(10, "Preemptions", 80, 20,
1000, B_TRUNCATE_END, B_ALIGN_RIGHT)); 1000, B_TRUNCATE_END, B_ALIGN_RIGHT));
fThreadsTable->AddTableListener(this);
} }
ThreadsPage::~ThreadsPage() MainWindow::ThreadsPage::~ThreadsPage()
{ {
fThreadsTable->SetTableModel(NULL); fThreadsTable->SetTableModel(NULL);
delete fThreadsTableModel; delete fThreadsTableModel;
@@ -133,7 +135,7 @@ ThreadsPage::~ThreadsPage()
void void
ThreadsPage::SetModel(Model* model) MainWindow::ThreadsPage::SetModel(Model* model)
{ {
if (model == fModel) if (model == fModel)
return; return;
@@ -151,3 +153,12 @@ ThreadsPage::SetModel(Model* model)
fThreadsTable->SetTableModel(fThreadsTableModel); fThreadsTable->SetTableModel(fThreadsTableModel);
} }
} }
void
MainWindow::ThreadsPage::TableRowInvoked(Table* table, int32 rowIndex)
{
Model::Thread* thread = fModel->ThreadAt(rowIndex);
if (thread != NULL)
fParent->OpenThreadWindow(thread);
}
@@ -7,14 +7,14 @@
#include <GroupView.h> #include <GroupView.h>
#include "Table.h"
class Model; #include "main_window/MainWindow.h"
class Table;
class ThreadsPage : public BGroupView { class MainWindow::ThreadsPage : public BGroupView, private TableListener {
public: public:
ThreadsPage(); ThreadsPage(MainWindow* parent);
virtual ~ThreadsPage(); virtual ~ThreadsPage();
void SetModel(Model* model); void SetModel(Model* model);
@@ -23,6 +23,11 @@ private:
class ThreadsTableModel; class ThreadsTableModel;
private: private:
// TableListener
virtual void TableRowInvoked(Table* table, int32 rowIndex);
private:
MainWindow* fParent;
Table* fThreadsTable; Table* fThreadsTable;
ThreadsTableModel* fThreadsTableModel; ThreadsTableModel* fThreadsTableModel;
Model* fModel; Model* fModel;
@@ -0,0 +1,90 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#include "thread_window/GeneralPage.h"
#include <stdio.h>
ThreadWindow::GeneralPage::GeneralPage()
:
AbstractGeneralPage(),
fModel(NULL),
fThread(NULL),
fThreadNameView(NULL),
fThreadIDView(NULL),
fTeamView(NULL),
fRunTimeView(NULL),
fWaitTimeView(NULL),
fLatencyView(NULL),
fPreemptionView(NULL)
{
fThreadNameView = AddDataView("Name:");
fThreadIDView = AddDataView("ID:");
fTeamView = AddDataView("Team:");
fRunTimeView = AddDataView("Run Time:");
fWaitTimeView = AddDataView("Wait Time:");
fLatencyView = AddDataView("Latencies:");
fPreemptionView = AddDataView("Preemptions:");
}
ThreadWindow::GeneralPage::~GeneralPage()
{
}
void
ThreadWindow::GeneralPage::SetModel(Model* model, Model::Thread* thread)
{
if (model == fModel && thread == fThread)
return;
fModel = model;
fThread = thread;
if (fThread != NULL) {
// name
fThreadNameView->SetText(fThread->Name());
// ID
char buffer[128];
snprintf(buffer, sizeof(buffer), "%ld", fThread->ID());
fThreadIDView->SetText(buffer);
// team
fTeamView->SetText(thread->GetTeam()->Name());
// run time
snprintf(buffer, sizeof(buffer), "%lld μs (%lld)",
fThread->TotalRunTime(), fThread->Runs());
fRunTimeView->SetText(buffer);
// wait time
fWaitTimeView->SetText("");
// TODO:...
// snprintf(buffer, sizeof(buffer), "%lld μs (%lld)",
// fThread->TotalRunTime(), fThread->Runs());
// fWaitTimeView->SetText(buffer);
// latencies
snprintf(buffer, sizeof(buffer), "%lld μs (%lld)",
fThread->TotalLatency(), fThread->Latencies());
fLatencyView->SetText(buffer);
// preemptions
snprintf(buffer, sizeof(buffer), "%lld μs (%lld)",
fThread->TotalRerunTime(), fThread->Preemptions());
fPreemptionView->SetText(buffer);
} else {
fThreadNameView->SetText("");
fThreadIDView->SetText("");
fTeamView->SetText("");
fRunTimeView->SetText("");
fWaitTimeView->SetText("");
fLatencyView->SetText("");
fPreemptionView->SetText("");
}
}
@@ -0,0 +1,36 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef THREAD_GENERAL_PAGE_H
#define THREAD_GENERAL_PAGE_H
#include "AbstractGeneralPage.h"
#include "thread_window/ThreadWindow.h"
class TextDataView;
class ThreadWindow::GeneralPage : public AbstractGeneralPage {
public:
GeneralPage();
virtual ~GeneralPage();
void SetModel(Model* model, Model::Thread* thread);
private:
Model* fModel;
Model::Thread* fThread;
TextDataView* fThreadNameView;
TextDataView* fThreadIDView;
TextDataView* fTeamView;
TextDataView* fRunTimeView;
TextDataView* fWaitTimeView;
TextDataView* fLatencyView;
TextDataView* fPreemptionView;
};
#endif // THREAD_GENERAL_PAGE_H
@@ -0,0 +1,12 @@
SubDir HAIKU_TOP src apps debuganalyzer thread_window ;
UsePrivateHeaders debug interface kernel shared ;
UsePrivateSystemHeaders ;
SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) ] ;
MergeObject DebugAnalyzer_ThreadWindow.o
:
ThreadWindow.cpp
GeneralPage.cpp
;
@@ -0,0 +1,67 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#include "ThreadWindow.h"
#include <stdio.h>
#include <Application.h>
#include <GroupLayoutBuilder.h>
#include <String.h>
#include <TabView.h>
#include <AutoLocker.h>
//#include "MessageCodes.h"
#include "thread_window/GeneralPage.h"
static BString
get_window_name(Model::Thread* thread)
{
char buffer[1024];
snprintf(buffer, sizeof(buffer), "Thread: %s (%ld)", thread->Name(),
thread->ID());
return BString(buffer);
}
ThreadWindow::ThreadWindow(SubWindowManager* manager, Model* model,
Model::Thread* thread)
:
SubWindow(manager, BRect(50, 50, 599, 499),
get_window_name(thread).String(), B_DOCUMENT_WINDOW,
B_ASYNCHRONOUS_CONTROLS),
fMainTabView(NULL),
fGeneralPage(NULL),
fWaitObjectsPage(NULL),
fModel(model),
fThread(thread)
{
BGroupLayout* rootLayout = new BGroupLayout(B_VERTICAL);
SetLayout(rootLayout);
fMainTabView = new BTabView("main tab view");
BGroupLayoutBuilder(rootLayout)
.Add(fMainTabView);
fMainTabView->AddTab(fGeneralPage = new GeneralPage);
// fMainTabView->AddTab(fWaitObjectsPage = new WaitObjectsPage);
fMainTabView->AddTab(new BView("Dummy", 0));
//fMainTabView->Select(0);
fGeneralPage->SetModel(fModel, fThread);
// fWaitObjectsPage->SetModel(fModel, fThread);
fModel->AddReference();
}
ThreadWindow::~ThreadWindow()
{
fModel->RemoveReference();
}
@@ -0,0 +1,44 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef THREAD_WINDOW_H
#define THREAD_WINDOW_H
#include "Model.h"
#include "SubWindow.h"
class BTabView;
class ThreadWindow : public SubWindow {
public:
ThreadWindow(SubWindowManager* manager,
Model* model, Model::Thread* thread);
virtual ~ThreadWindow();
// virtual void MessageReceived(BMessage* message);
// virtual void Quit();
// virtual void Show();
private:
class GeneralPage;
class WaitObjectsPage;
private:
void _SetModel(Model* model);
private:
BTabView* fMainTabView;
GeneralPage* fGeneralPage;
WaitObjectsPage* fWaitObjectsPage;
Model* fModel;
Model::Thread* fThread;
};
#endif // THREAD_WINDOW_H