Debugger: More work on signal configuration.

- Introduce SignalDispositionEditWindow for add/editing disposition
  exceptions.

SignalsConfigView:
- Factor out helper class SignalDispositionMenu. Use accordingly in
  SignalsConfigView and SignalDispositionEditWindow.
- Watch table selection changes to update button statuses appropriately.
- On add/edit request, show disposition edit window.
- Listen for disposition changes from team and react accordingly.

UiUtils:
- Add helper function to map signal defines to strings.

Together with the previous set of commits, this implements #9720.
This commit is contained in:
Rene Gollent
2015-07-02 22:38:08 -04:00
parent b66f61af9b
commit b3f2ebf008
10 changed files with 524 additions and 20 deletions
+2
View File
@@ -299,11 +299,13 @@ Application Debugger :
ActionMenuItem.cpp ActionMenuItem.cpp
GuiSettingsUtils.cpp GuiSettingsUtils.cpp
SettingsMenu.cpp SettingsMenu.cpp
SignalDispositionMenu.cpp
TargetAddressTableColumn.cpp TargetAddressTableColumn.cpp
# user_interface/gui/utility_windows # user_interface/gui/utility_windows
BreakpointEditWindow.cpp BreakpointEditWindow.cpp
ExpressionPromptWindow.cpp ExpressionPromptWindow.cpp
SignalDispositionEditWindow.cpp
StartTeamWindow.cpp StartTeamWindow.cpp
WatchPromptWindow.cpp WatchPromptWindow.cpp
+2
View File
@@ -69,6 +69,8 @@ enum {
MSG_TEAM_SETTINGS_WINDOW_CLOSED = 'tswc', MSG_TEAM_SETTINGS_WINDOW_CLOSED = 'tswc',
MSG_SHOW_BREAKPOINT_EDIT_WINDOW = 'sbew', MSG_SHOW_BREAKPOINT_EDIT_WINDOW = 'sbew',
MSG_BREAKPOINT_EDIT_WINDOW_CLOSED = 'bewc', MSG_BREAKPOINT_EDIT_WINDOW_CLOSED = 'bewc',
MSG_SHOW_SIGNAL_DISPOSITION_EDIT_WINDOW = 'sdew',
MSG_SIGNAL_DISPOSITION_EDIT_WINDOW_CLOSED = 'sdec',
MSG_SHOW_START_TEAM_WINDOW = 'sstw', MSG_SHOW_START_TEAM_WINDOW = 'sstw',
MSG_START_TEAM_WINDOW_CLOSED = 'stwc', MSG_START_TEAM_WINDOW_CLOSED = 'stwc',
MSG_START_NEW_TEAM = 'sttt', MSG_START_NEW_TEAM = 'sttt',
@@ -15,6 +15,8 @@
#include "table/TableColumns.h" #include "table/TableColumns.h"
#include "MessageCodes.h" #include "MessageCodes.h"
#include "SignalDispositionEditWindow.h"
#include "SignalDispositionMenu.h"
#include "SignalDispositionTypes.h" #include "SignalDispositionTypes.h"
#include "UiUtils.h" #include "UiUtils.h"
#include "UserInterface.h" #include "UserInterface.h"
@@ -73,11 +75,18 @@ public:
switch (columnIndex) { switch (columnIndex) {
case 0: case 0:
value = info->signal; {
BString tempValue;
value.SetTo(UiUtils::SignalNameToString(info->signal,
tempValue));
return true; return true;
}
case 1: case 1:
value = info->disposition; {
value.SetTo(UiUtils::SignalDispositionToString(
info->disposition), B_VARIANT_DONT_COPY_DATA);
return true; return true;
}
default: default:
break; break;
} }
@@ -85,6 +94,15 @@ public:
return false; return false;
} }
bool SignalDispositionInfoAt(int32 rowIndex, SignalDispositionInfo*& _info)
{
_info = fDispositions.ItemAt(rowIndex);
if (_info == NULL)
return false;
return true;
}
void Update(int32 signal, int32 disposition) void Update(int32 signal, int32 disposition)
{ {
for (int32 i = 0; i < fDispositions.CountItems(); i++) { for (int32 i = 0; i < fDispositions.CountItems(); i++) {
@@ -168,7 +186,8 @@ SignalsConfigView::SignalsConfigView(::Team* team,
fAddDispositionButton(NULL), fAddDispositionButton(NULL),
fEditDispositionButton(NULL), fEditDispositionButton(NULL),
fRemoveDispositionButton(NULL), fRemoveDispositionButton(NULL),
fDispositionModel(NULL) fDispositionModel(NULL),
fEditWindow(NULL)
{ {
SetName("Signals"); SetName("Signals");
fTeam->AddListener(this); fTeam->AddListener(this);
@@ -178,6 +197,7 @@ SignalsConfigView::SignalsConfigView(::Team* team,
SignalsConfigView::~SignalsConfigView() SignalsConfigView::~SignalsConfigView()
{ {
fTeam->RemoveListener(this); fTeam->RemoveListener(this);
BMessenger(fEditWindow).SendMessage(B_QUIT_REQUESTED);
} }
@@ -219,6 +239,10 @@ void
SignalsConfigView::MessageReceived(BMessage* message) SignalsConfigView::MessageReceived(BMessage* message)
{ {
switch (message->what) { switch (message->what) {
case MSG_SIGNAL_DISPOSITION_EDIT_WINDOW_CLOSED:
{
fEditWindow = NULL;
}
case MSG_SET_DEFAULT_SIGNAL_DISPOSITION: case MSG_SET_DEFAULT_SIGNAL_DISPOSITION:
{ {
int32 disposition; int32 disposition;
@@ -229,15 +253,64 @@ SignalsConfigView::MessageReceived(BMessage* message)
break; break;
} }
case MSG_ADD_DISPOSITION_EXCEPTION: case MSG_ADD_DISPOSITION_EXCEPTION:
{
break;
}
case MSG_EDIT_DISPOSITION_EXCEPTION: case MSG_EDIT_DISPOSITION_EXCEPTION:
{ {
if (fEditWindow != NULL) {
AutoLocker<BWindow> lock(fEditWindow);
if (lock.IsLocked())
fEditWindow->Activate(true);
} else {
int32 signal = 0;
if (message->what == MSG_EDIT_DISPOSITION_EXCEPTION) {
TableSelectionModel* model
= fDispositionExceptions->SelectionModel();
SignalDispositionInfo* info;
if (fDispositionModel->SignalDispositionInfoAt(
model->RowAt(0), info)) {
signal = info->signal;
}
}
try {
fEditWindow = SignalDispositionEditWindow::Create(fTeam,
signal, fListener, this);
if (fEditWindow != NULL)
fEditWindow->Show();
} catch (...) {
// TODO: notify user
}
}
break; break;
} }
case MSG_REMOVE_DISPOSITION_EXCEPTION: case MSG_REMOVE_DISPOSITION_EXCEPTION:
{ {
TableSelectionModel* model
= fDispositionExceptions->SelectionModel();
for (int32 i = 0; i < model->CountRows(); i++) {
SignalDispositionInfo* info;
if (fDispositionModel->SignalDispositionInfoAt(model->RowAt(i),
info)) {
fListener->RemoveCustomSignalDispositionRequested(
info->signal);
}
}
break;
}
case MSG_SET_CUSTOM_SIGNAL_DISPOSITION:
{
int32 signal;
int32 disposition;
if (message->FindInt32("signal", &signal) == B_OK
&& message->FindInt32("disposition", &disposition) == B_OK) {
fDispositionModel->Update(signal, disposition);
}
break;
}
case MSG_REMOVE_CUSTOM_SIGNAL_DISPOSITION:
{
int32 signal;
if (message->FindInt32("signal", &signal) == B_OK)
fDispositionModel->Remove(signal);
break; break;
} }
default: default:
@@ -247,24 +320,45 @@ SignalsConfigView::MessageReceived(BMessage* message)
} }
void
SignalsConfigView::CustomSignalDispositionChanged(
const Team::CustomSignalDispositionEvent& event)
{
BMessage message(MSG_SET_CUSTOM_SIGNAL_DISPOSITION);
message.AddInt32("signal", event.Signal());
message.AddInt32("disposition", event.Disposition());
BMessenger(this).SendMessage(&message);
}
void
SignalsConfigView::CustomSignalDispositionRemoved(
const Team::CustomSignalDispositionEvent& event)
{
BMessage message(MSG_REMOVE_CUSTOM_SIGNAL_DISPOSITION);
message.AddInt32("signal", event.Signal());
BMessenger(this).SendMessage(&message);
}
void void
SignalsConfigView::TableSelectionChanged(Table* table) SignalsConfigView::TableSelectionChanged(Table* table)
{ {
TableSelectionModel* model = fDispositionExceptions->SelectionModel();
int32 rowCount = model->CountRows();
fEditDispositionButton->SetEnabled(rowCount == 1);
fRemoveDispositionButton->SetEnabled(rowCount > 0);
} }
void void
SignalsConfigView::_Init() SignalsConfigView::_Init()
{ {
BMenu* dispositionMenu = new BMenu("signalDispositionsMenu"); SignalDispositionMenu* dispositionMenu = new SignalDispositionMenu(
"signalDispositionsMenu",
for (int i = 0; i < SIGNAL_DISPOSITION_MAX; i++) { new BMessage(MSG_SET_DEFAULT_SIGNAL_DISPOSITION));
BMessage* message = new BMessage(
MSG_SET_DEFAULT_SIGNAL_DISPOSITION);
message->AddInt32("disposition", i);
dispositionMenu->AddItem(new BMenuItem(
UiUtils::SignalDispositionToString(i), message));
}
BGroupView* customDispositionsGroup = new BGroupView(); BGroupView* customDispositionsGroup = new BGroupView();
BLayoutBuilder::Group<>(customDispositionsGroup, B_VERTICAL, 0.0) BLayoutBuilder::Group<>(customDispositionsGroup, B_VERTICAL, 0.0)
@@ -17,6 +17,7 @@
class BButton; class BButton;
class BMenuField; class BMenuField;
class SignalDispositionEditWindow;
class UserInterfaceListener; class UserInterfaceListener;
@@ -35,15 +36,21 @@ public:
virtual void AttachedToWindow(); virtual void AttachedToWindow();
virtual void MessageReceived(BMessage* message); virtual void MessageReceived(BMessage* message);
// Team::Listener
// TableListener
virtual void TableSelectionChanged(Table* table);
private: private:
class SignalDispositionModel; class SignalDispositionModel;
private: private:
// Team::Listener
virtual void CustomSignalDispositionChanged(
const Team::CustomSignalDispositionEvent&
event);
virtual void CustomSignalDispositionRemoved(
const Team::CustomSignalDispositionEvent&
event);
// TableListener
virtual void TableSelectionChanged(Table* table);
void _Init(); void _Init();
void _UpdateSignalConfigState(); void _UpdateSignalConfigState();
@@ -58,6 +65,7 @@ private:
BButton* fEditDispositionButton; BButton* fEditDispositionButton;
BButton* fRemoveDispositionButton; BButton* fRemoveDispositionButton;
SignalDispositionModel* fDispositionModel; SignalDispositionModel* fDispositionModel;
SignalDispositionEditWindow* fEditWindow;
}; };
@@ -0,0 +1,36 @@
/*
* Copyright 2015, Rene Gollent, [email protected].
* Distributed under the terms of the MIT License.
*/
#include "SignalDispositionMenu.h"
#include <new>
#include <MenuItem.h>
#include "SignalDispositionTypes.h"
#include "UiUtils.h"
SignalDispositionMenu::SignalDispositionMenu(const char* label,
BMessage* baseMessage)
:
BMenu(label)
{
for (int i = 0; i < SIGNAL_DISPOSITION_MAX; i++) {
BMessage* message = NULL;
if (baseMessage != NULL) {
message = new BMessage(*baseMessage);
message->AddInt32("disposition", i);
}
AddItem(new BMenuItem(UiUtils::SignalDispositionToString(i), message));
}
}
SignalDispositionMenu::~SignalDispositionMenu()
{
}
@@ -0,0 +1,20 @@
/*
* Copyright 2015, Rene Gollent, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef SIGNAL_DISPOSITION_MENU_H
#define SIGNAL_DISPOSITION_MENU_H
#include <Menu.h>
class SignalDispositionMenu : public BMenu {
public:
SignalDispositionMenu(const char* label,
BMessage* baseMessage = NULL);
virtual ~SignalDispositionMenu();
};
#endif // SIGNAL_DISPOSITION_MENU_H
@@ -0,0 +1,223 @@
/*
* Copyright 2015, Rene Gollent, [email protected].
* Distributed under the terms of the MIT License.
*/
#include "SignalDispositionEditWindow.h"
#include <signal.h>
#include <Button.h>
#include <LayoutBuilder.h>
#include <MenuField.h>
#include <AutoDeleter.h>
#include <AutoLocker.h>
#include "MessageCodes.h"
#include "SignalDispositionMenu.h"
#include "SignalDispositionTypes.h"
#include "UiUtils.h"
#include "UserInterface.h"
#include "Team.h"
enum {
MSG_SELECTED_SIGNAL_CHANGED = 'ssic',
MSG_SELECTED_DISPOSITION_CHANGED = 'sdic',
MSG_SAVE_SIGNAL_DISPOSITION = 'ssid'
};
SignalDispositionEditWindow::SignalDispositionEditWindow(::Team* team,
int32 signal, UserInterfaceListener* listener, BHandler* target)
:
BWindow(BRect(), "Edit breakpoint", B_FLOATING_WINDOW,
B_AUTO_UPDATE_SIZE_LIMITS | B_CLOSE_ON_ESCAPE),
fTeam(team),
fListener(listener),
fEditMode(signal > 0),
fCurrentSignal(signal),
fSaveButton(NULL),
fCancelButton(NULL),
fSignalSelectionField(NULL),
fDispositionSelectionField(NULL),
fTarget(target)
{
}
SignalDispositionEditWindow::~SignalDispositionEditWindow()
{
BMessenger(fTarget).SendMessage(MSG_SIGNAL_DISPOSITION_EDIT_WINDOW_CLOSED);
}
SignalDispositionEditWindow*
SignalDispositionEditWindow::Create(::Team* team, int32 signal,
UserInterfaceListener* listener, BHandler* target)
{
SignalDispositionEditWindow* self = new SignalDispositionEditWindow(
team, signal, listener, target);
try {
self->_Init();
} catch (...) {
delete self;
throw;
}
return self;
}
void
SignalDispositionEditWindow::MessageReceived(BMessage* message)
{
switch (message->what) {
case MSG_SELECTED_SIGNAL_CHANGED:
{
int32 signal;
if (message->FindInt32("signal", &signal) == B_OK)
fCurrentSignal = signal;
break;
}
case MSG_SELECTED_DISPOSITION_CHANGED:
{
int32 disposition;
if (message->FindInt32("disposition", &disposition) == B_OK)
fCurrentDisposition = disposition;
break;
}
case MSG_SAVE_SIGNAL_DISPOSITION:
{
fListener->SetCustomSignalDispositionRequested(fCurrentSignal,
fCurrentDisposition);
// fall through
}
case B_CANCEL:
Quit();
break;
default:
BWindow::MessageReceived(message);
break;
}
}
void
SignalDispositionEditWindow::Show()
{
CenterOnScreen();
BWindow::Show();
}
void
SignalDispositionEditWindow::_Init()
{
SignalDispositionMenu* menu = new SignalDispositionMenu("dispositionMenu",
new BMessage(MSG_SELECTED_DISPOSITION_CHANGED));
BLayoutBuilder::Group<>(this, B_VERTICAL)
.SetInsets(B_USE_DEFAULT_SPACING)
.AddGroup(B_HORIZONTAL)
.Add((fSignalSelectionField = new BMenuField("Signal:",
_BuildSignalSelectionMenu())))
.Add((fDispositionSelectionField = new BMenuField("Disposition:",
menu)))
.End()
.AddGroup(B_HORIZONTAL)
.AddGlue()
.Add((fSaveButton = new BButton("Save",
new BMessage(MSG_SAVE_SIGNAL_DISPOSITION))))
.Add((fCancelButton = new BButton("Cancel",
new BMessage(B_CANCEL))))
.End()
.End();
fSignalSelectionField->Menu()->SetLabelFromMarked(true);
fSignalSelectionField->Menu()->SetTargetForItems(this);
menu->SetLabelFromMarked(true);
menu->SetTargetForItems(this);
AutoLocker< ::Team> teamLocker(fTeam);
_UpdateState();
// if we're editing an existing row, don't allow changing the signal
// selection
if (fEditMode)
fSignalSelectionField->SetEnabled(false);
}
BMenu*
SignalDispositionEditWindow::_BuildSignalSelectionMenu()
{
BMenu* menu = new BMenu("signals");
BMenuItem* item;
#undef ADD_SIGNAL_MENU_ITEM
#define ADD_SIGNAL_MENU_ITEM(x) \
menu->AddItem((item = new BMenuItem(#x, new BMessage( \
MSG_SELECTED_SIGNAL_CHANGED)))); \
item->Message()->AddInt32("signal", x);
ADD_SIGNAL_MENU_ITEM(SIGHUP)
ADD_SIGNAL_MENU_ITEM(SIGINT)
ADD_SIGNAL_MENU_ITEM(SIGQUIT)
ADD_SIGNAL_MENU_ITEM(SIGILL)
ADD_SIGNAL_MENU_ITEM(SIGCHLD)
ADD_SIGNAL_MENU_ITEM(SIGABRT)
ADD_SIGNAL_MENU_ITEM(SIGPIPE)
ADD_SIGNAL_MENU_ITEM(SIGFPE)
ADD_SIGNAL_MENU_ITEM(SIGKILL)
ADD_SIGNAL_MENU_ITEM(SIGSTOP)
ADD_SIGNAL_MENU_ITEM(SIGSEGV)
ADD_SIGNAL_MENU_ITEM(SIGCONT)
ADD_SIGNAL_MENU_ITEM(SIGTSTP)
ADD_SIGNAL_MENU_ITEM(SIGALRM)
ADD_SIGNAL_MENU_ITEM(SIGTERM)
ADD_SIGNAL_MENU_ITEM(SIGTTIN)
ADD_SIGNAL_MENU_ITEM(SIGTTOU)
ADD_SIGNAL_MENU_ITEM(SIGUSR1)
ADD_SIGNAL_MENU_ITEM(SIGUSR2)
ADD_SIGNAL_MENU_ITEM(SIGWINCH)
ADD_SIGNAL_MENU_ITEM(SIGKILLTHR)
ADD_SIGNAL_MENU_ITEM(SIGTRAP)
ADD_SIGNAL_MENU_ITEM(SIGPOLL)
ADD_SIGNAL_MENU_ITEM(SIGPROF)
ADD_SIGNAL_MENU_ITEM(SIGSYS)
ADD_SIGNAL_MENU_ITEM(SIGURG)
ADD_SIGNAL_MENU_ITEM(SIGVTALRM)
ADD_SIGNAL_MENU_ITEM(SIGXCPU)
ADD_SIGNAL_MENU_ITEM(SIGXFSZ)
ADD_SIGNAL_MENU_ITEM(SIGBUS)
BString signalName;
for (int32 i = SIGRTMIN; i <= SIGRTMAX; i++) {
menu->AddItem((item = new BMenuItem(UiUtils::SignalNameToString(i,
signalName), new BMessage(MSG_SELECTED_SIGNAL_CHANGED))));
item->Message()->AddInt32("signal", i);
}
return menu;
}
void
SignalDispositionEditWindow::_UpdateState()
{
if (fCurrentSignal <= 0)
fCurrentSignal = SIGHUP;
fSignalSelectionField->Menu()->ItemAt(fCurrentSignal - 1)->SetMarked(true);
fCurrentDisposition = fTeam->SignalDispositionFor(fCurrentSignal);
fDispositionSelectionField->Menu()->ItemAt(fCurrentDisposition)->SetMarked(
true);
}
@@ -0,0 +1,62 @@
/*
* Copyright 2015, Rene Gollent, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef SIGNAL_DISPOSITION_EDIT_WINDOW_H
#define SIGNAL_DISPOSITION_EDIT_WINDOW_H
#include <Window.h>
#include "Team.h"
#include "types/Types.h"
class BButton;
class BMenu;
class BMenuField;
class Team;
class UserInterfaceListener;
class SignalDispositionEditWindow : public BWindow {
public:
SignalDispositionEditWindow(
::Team* team,
int32 signal,
UserInterfaceListener* listener,
BHandler* target);
~SignalDispositionEditWindow();
static SignalDispositionEditWindow* Create(::Team* team,
int32 signal,
UserInterfaceListener* listener,
BHandler* target);
// throws
virtual void MessageReceived(BMessage* message);
virtual void Show();
private:
void _Init();
BMenu* _BuildSignalSelectionMenu();
void _UpdateState();
private:
::Team* fTeam;
UserInterfaceListener* fListener;
bool fEditMode;
int32 fCurrentSignal;
int32 fCurrentDisposition;
BButton* fSaveButton;
BButton* fCancelButton;
BMenuField* fSignalSelectionField;
BMenuField* fDispositionSelectionField;
BHandler* fTarget;
};
#endif // SIGNAL_DISPOSITION_EDIT_WINDOW
@@ -562,6 +562,61 @@ UiUtils::FormatSIMDValue(const BVariant& value, uint32 bitSize,
} }
const char*
UiUtils::SignalNameToString(int32 signal, BString& _output)
{
#undef DEFINE_SIGNAL_STRING
#define DEFINE_SIGNAL_STRING(x) \
case x: \
_output = #x; \
return _output.String();
switch (signal) {
DEFINE_SIGNAL_STRING(SIGHUP)
DEFINE_SIGNAL_STRING(SIGINT)
DEFINE_SIGNAL_STRING(SIGQUIT)
DEFINE_SIGNAL_STRING(SIGILL)
DEFINE_SIGNAL_STRING(SIGCHLD)
DEFINE_SIGNAL_STRING(SIGABRT)
DEFINE_SIGNAL_STRING(SIGPIPE)
DEFINE_SIGNAL_STRING(SIGFPE)
DEFINE_SIGNAL_STRING(SIGKILL)
DEFINE_SIGNAL_STRING(SIGSTOP)
DEFINE_SIGNAL_STRING(SIGSEGV)
DEFINE_SIGNAL_STRING(SIGCONT)
DEFINE_SIGNAL_STRING(SIGTSTP)
DEFINE_SIGNAL_STRING(SIGALRM)
DEFINE_SIGNAL_STRING(SIGTERM)
DEFINE_SIGNAL_STRING(SIGTTIN)
DEFINE_SIGNAL_STRING(SIGTTOU)
DEFINE_SIGNAL_STRING(SIGUSR1)
DEFINE_SIGNAL_STRING(SIGUSR2)
DEFINE_SIGNAL_STRING(SIGWINCH)
DEFINE_SIGNAL_STRING(SIGKILLTHR)
DEFINE_SIGNAL_STRING(SIGTRAP)
DEFINE_SIGNAL_STRING(SIGPOLL)
DEFINE_SIGNAL_STRING(SIGPROF)
DEFINE_SIGNAL_STRING(SIGSYS)
DEFINE_SIGNAL_STRING(SIGURG)
DEFINE_SIGNAL_STRING(SIGVTALRM)
DEFINE_SIGNAL_STRING(SIGXCPU)
DEFINE_SIGNAL_STRING(SIGXFSZ)
DEFINE_SIGNAL_STRING(SIGBUS)
default:
break;
}
if (signal == SIGRTMIN)
_output = "SIGRTMIN";
else if (signal == SIGRTMAX)
_output = "SIGRTMAX";
else
_output.SetToFormat("SIGRTMIN+%" B_PRId32, signal - SIGRTMIN);
return _output.String();
}
const char* const char*
UiUtils::SignalDispositionToString(int disposition) UiUtils::SignalDispositionToString(int disposition)
{ {
@@ -75,6 +75,8 @@ public:
uint32 bitSize, uint32 format, uint32 bitSize, uint32 format,
BString& _output); BString& _output);
static const char* SignalNameToString(int32 signal,
BString& _output);
static const char* SignalDispositionToString(int disposition); static const char* SignalDispositionToString(int disposition);
}; };