Implemented log viewer dialog for the wx gui
- added new class LogViewDialog based on the already removed DebugLogDialog - log output is only sent to the viewer if visible to avoid performance trouble - text buffer is limited to 48k, older lines are removed if necessary - red text color is used for error and panic messages and black for others - minor related code cleanups
This commit is contained in:
parent
a1e397b5a2
commit
71feea84ed
@ -547,6 +547,109 @@ void PluginControlDialog::ShowHelp()
|
||||
wxMessageBox(MSG_NO_HELP, MSG_NO_HELP_CAPTION, wxOK | wxICON_ERROR, this);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// LogViewDialog implementation
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
// all events go to OnEvent method
|
||||
BEGIN_EVENT_TABLE(LogViewDialog, wxDialog)
|
||||
EVT_BUTTON(-1, LogViewDialog::OnEvent)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
LogViewDialog::LogViewDialog(
|
||||
wxWindow* parent,
|
||||
wxWindowID id)
|
||||
: wxDialog(parent, id, wxT(""), wxDefaultPosition, wxDefaultSize,
|
||||
wxDEFAULT_DIALOG_STYLE)
|
||||
{
|
||||
lengthMax = LOG_VIEW_DEFAULT_LENGTH_MAX;
|
||||
lengthTolerance = LOG_VIEW_DEFAULT_TOLERANCE;
|
||||
SetTitle(wxT("Bochs Log Viewer"));
|
||||
mainSizer = new wxBoxSizer(wxVERTICAL);
|
||||
logSizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
buttonSizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
mainSizer->Add(logSizer, 0, wxALIGN_CENTER);
|
||||
mainSizer->Add(buttonSizer, 0, wxALIGN_CENTER);
|
||||
log = new wxTextCtrl(this, -1, "",
|
||||
wxDefaultPosition, wxSize(575, 300),
|
||||
wxTE_MULTILINE | wxTE_RICH | wxTE_READONLY);
|
||||
wxFont font(8, wxFONTFAMILY_TELETYPE, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
|
||||
wxTextAttr attr;
|
||||
attr.SetFont(font);
|
||||
log->SetDefaultStyle(attr);
|
||||
logSizer->Add(log, 1, wxALL|wxGROW, 10);
|
||||
// buttonSizer contents
|
||||
wxButton *btn = new wxButton(this, wxID_OK, BTNLABEL_CLOSE);
|
||||
buttonSizer->Add(btn, 0, wxALL, 5);
|
||||
}
|
||||
|
||||
void LogViewDialog::Init()
|
||||
{
|
||||
SetSizer(mainSizer);
|
||||
mainSizer->Fit(this);
|
||||
wxSize size = mainSizer->GetMinSize();
|
||||
int margin = 5;
|
||||
SetSizeHints(size.GetWidth() + margin, size.GetHeight() + margin);
|
||||
Center();
|
||||
}
|
||||
|
||||
bool LogViewDialog::Show(bool val)
|
||||
{
|
||||
SIM->set_log_viewer(val);
|
||||
if (val) wxDialog::Raise();
|
||||
return wxDialog::Show(val);
|
||||
}
|
||||
|
||||
void LogViewDialog::CheckLogLength()
|
||||
{
|
||||
// truncate the text control periodically to avoid a
|
||||
// serious memory leak.
|
||||
wxString str = log->GetValue();
|
||||
Bit32u len = str.Length();
|
||||
if (len > lengthMax + lengthTolerance) {
|
||||
// Truncate the string. Start from length - lengthMax, search
|
||||
// forward until we find the first \n.
|
||||
for (Bit32u i = len - lengthMax; i<len-1; i++) {
|
||||
if (str.GetChar(i) == '\n') {
|
||||
// remove the \n and everything before it.
|
||||
log->Remove(0, i+1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// no newline found?!
|
||||
log->Remove(0, len - lengthMax);
|
||||
}
|
||||
}
|
||||
|
||||
void LogViewDialog::AppendText(int level, wxString prefix, wxString msg)
|
||||
{
|
||||
if ((level == LOGLEV_ERROR) || (level == LOGLEV_PANIC)) {
|
||||
log->SetDefaultStyle(wxTextAttr(*wxRED));
|
||||
} else {
|
||||
log->SetDefaultStyle(wxTextAttr(*wxBLACK));
|
||||
}
|
||||
log->AppendText(prefix);
|
||||
log->AppendText(wxT(" "));
|
||||
log->AppendText(msg);
|
||||
log->AppendText(wxT("\n"));
|
||||
int n = log->GetLastPosition();
|
||||
if (n>0) n--;
|
||||
log->ShowPosition(n);
|
||||
CheckLogLength();
|
||||
}
|
||||
|
||||
void LogViewDialog::OnEvent(wxCommandEvent& event)
|
||||
{
|
||||
int id = event.GetId();
|
||||
switch (id) {
|
||||
case wxID_OK:
|
||||
Show(false);
|
||||
break;
|
||||
default:
|
||||
event.Skip();
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// ParamDialog
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
@ -33,6 +33,7 @@
|
||||
#define BTNLABEL_HELP wxT("Help")
|
||||
#define BTNLABEL_CANCEL wxT("Cancel")
|
||||
#define BTNLABEL_OK wxT("Ok")
|
||||
#define BTNLABEL_CLOSE wxT("Close")
|
||||
#define BTNLABEL_CREATE_IMG wxT("Create Image")
|
||||
#define BTNLABEL_BROWSE wxT("<--Browse")
|
||||
|
||||
@ -198,6 +199,29 @@ public:
|
||||
DECLARE_EVENT_TABLE()
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// LogViewDialog
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
class LogViewDialog: public wxDialog
|
||||
{
|
||||
private:
|
||||
wxBoxSizer *mainSizer, *logSizer, *buttonSizer;
|
||||
wxTextCtrl *log;
|
||||
Bit32u lengthMax;
|
||||
Bit32u lengthTolerance;
|
||||
#define LOG_VIEW_DEFAULT_LENGTH_MAX (400*80)
|
||||
#define LOG_VIEW_DEFAULT_TOLERANCE (200*80)
|
||||
void CheckLogLength();
|
||||
public:
|
||||
LogViewDialog(wxWindow* parent, wxWindowID id);
|
||||
~LogViewDialog() {}
|
||||
void Init();
|
||||
bool Show(bool val);
|
||||
void AppendText(int level, wxString prefix, wxString msg);
|
||||
void OnEvent(wxCommandEvent& event);
|
||||
DECLARE_EVENT_TABLE()
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// ParamDialog is a general purpose dialog box that displays and edits
|
||||
// any combination of parameters. It's always made up of a
|
||||
|
@ -288,8 +288,8 @@ BxEvent *MyApp::DefaultCallback(void *thisptr, BxEvent *event)
|
||||
fprintf(stderr, "%s\n", (const char *)text.mb_str(wxConvUTF8));
|
||||
} else {
|
||||
wxMessageBox(text, wxT("Error"), wxOK | wxICON_ERROR);
|
||||
// maybe I can make OnLogMsg display something that looks appropriate.
|
||||
// theFrame->OnLogMsg(event);
|
||||
// maybe I can make OnLogAsk display something that looks appropriate.
|
||||
// theFrame->OnLogAsk(event);
|
||||
}
|
||||
event->retcode = BX_LOG_ASK_CHOICE_DIE;
|
||||
// There is only one thread at this point. if I choose DIE here, it will
|
||||
@ -350,6 +350,7 @@ BEGIN_EVENT_TABLE(MyFrame, wxFrame)
|
||||
EVT_MENU(ID_Edit_Other, MyFrame::OnEditOther)
|
||||
EVT_MENU(ID_Log_Prefs, MyFrame::OnLogPrefs)
|
||||
EVT_MENU(ID_Log_PrefsDevice, MyFrame::OnLogPrefsDevice)
|
||||
EVT_MENU(ID_Log_View, MyFrame::OnLogView)
|
||||
// toolbar events
|
||||
EVT_TOOL(ID_Edit_FD_0, MyFrame::OnToolbarClick)
|
||||
EVT_TOOL(ID_Edit_FD_1, MyFrame::OnToolbarClick)
|
||||
@ -360,7 +361,6 @@ BEGIN_EVENT_TABLE(MyFrame, wxFrame)
|
||||
EVT_TOOL(ID_Toolbar_Copy, MyFrame::OnToolbarClick)
|
||||
EVT_TOOL(ID_Toolbar_Paste, MyFrame::OnToolbarClick)
|
||||
EVT_TOOL(ID_Toolbar_Snapshot, MyFrame::OnToolbarClick)
|
||||
/*EVT_TOOL(ID_Toolbar_Config, MyFrame::OnToolbarClick)*/
|
||||
EVT_TOOL(ID_Toolbar_Mouse_en, MyFrame::OnToolbarClick)
|
||||
EVT_TOOL(ID_Toolbar_User, MyFrame::OnToolbarClick)
|
||||
END_EVENT_TABLE()
|
||||
@ -481,8 +481,6 @@ MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size,
|
||||
menuBar->Append(menuHelp, wxT("&Help"));
|
||||
SetMenuBar(menuBar);
|
||||
|
||||
// disable things that don't work yet
|
||||
menuLog->Enable(ID_Log_View, FALSE); // not implemented
|
||||
// enable ATA channels in menu
|
||||
menuEdit->Enable(ID_Edit_ATA1, BX_MAX_ATA_CHANNEL > 1);
|
||||
menuEdit->Enable(ID_Edit_ATA2, BX_MAX_ATA_CHANNEL > 2);
|
||||
@ -514,9 +512,6 @@ MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size,
|
||||
BX_ADD_TOOL(ID_Toolbar_Copy, copy_xpm, wxT("Copy to clipboard"));
|
||||
BX_ADD_TOOL(ID_Toolbar_Paste, paste_xpm, wxT("Paste from clipboard"));
|
||||
BX_ADD_TOOL(ID_Toolbar_Snapshot, snapshot_xpm, wxT("Save screen snapshot"));
|
||||
// Omit config button because the whole wxWidgets interface is like
|
||||
// one really big config button.
|
||||
//BX_ADD_TOOL(ID_Toolbar_Config, configbutton_xpm, "Runtime Configuration");
|
||||
BX_ADD_TOOL(ID_Toolbar_Mouse_en, mouse_xpm, wxT("Enable mouse capture\nThere is also a shortcut for this: a CTRL key + the middle mouse button."));
|
||||
BX_ADD_TOOL(ID_Toolbar_User, userbutton_xpm, wxT("Keyboard shortcut"));
|
||||
|
||||
@ -531,11 +526,16 @@ MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size,
|
||||
sz->Add(panel, 0, wxGROW);
|
||||
SetAutoLayout(TRUE);
|
||||
SetSizer(sz);
|
||||
|
||||
// create modeless logfile viewer
|
||||
showLogView = new LogViewDialog(this, -1);
|
||||
showLogView->Init();
|
||||
}
|
||||
|
||||
MyFrame::~MyFrame()
|
||||
{
|
||||
delete panel;
|
||||
delete showLogView;
|
||||
wxLogDebug(wxT("MyFrame destructor"));
|
||||
theFrame = NULL;
|
||||
}
|
||||
@ -784,6 +784,12 @@ void MyFrame::OnLogPrefsDevice(wxCommandEvent& WXUNUSED(event))
|
||||
dlg.ShowModal();
|
||||
}
|
||||
|
||||
void MyFrame::OnLogView(wxCommandEvent& WXUNUSED(event))
|
||||
{
|
||||
wxASSERT(showLogView != NULL);
|
||||
showLogView->Show(true);
|
||||
}
|
||||
|
||||
void MyFrame::OnQuit(wxCommandEvent& event)
|
||||
{
|
||||
wxBochsClosing = true;
|
||||
@ -1112,9 +1118,14 @@ void MyFrame::OnSim2CIEvent(wxCommandEvent& event)
|
||||
sim_thread->SendSyncResponse(be);
|
||||
wxLogDebug(wxT("after SendSyncResponse"));
|
||||
break;
|
||||
case BX_SYNC_EVT_LOG_ASK:
|
||||
case BX_ASYNC_EVT_LOG_MSG:
|
||||
OnLogMsg(be);
|
||||
showLogView->AppendText(be->u.logmsg.level, wxString(be->u.logmsg.prefix, wxConvUTF8),
|
||||
wxString(be->u.logmsg.msg, wxConvUTF8));
|
||||
free((void*)be->u.logmsg.prefix);
|
||||
free((void*)be->u.logmsg.msg);
|
||||
break;
|
||||
case BX_SYNC_EVT_LOG_ASK:
|
||||
OnLogAsk(be);
|
||||
break;
|
||||
case BX_ASYNC_EVT_QUIT_SIM:
|
||||
wxMessageBox(wxT("Bochs simulation has stopped."), wxT("Bochs Stopped"),
|
||||
@ -1133,16 +1144,13 @@ void MyFrame::OnSim2CIEvent(wxCommandEvent& event)
|
||||
delete be;
|
||||
}
|
||||
|
||||
void MyFrame::OnLogMsg(BxEvent *be)
|
||||
void MyFrame::OnLogAsk(BxEvent *be)
|
||||
{
|
||||
wxLogDebug(wxT("log msg: level=%d, prefix='%s', msg='%s'"),
|
||||
be->u.logmsg.level,
|
||||
be->u.logmsg.prefix,
|
||||
be->u.logmsg.msg);
|
||||
if (be->type == BX_ASYNC_EVT_LOG_MSG)
|
||||
return; // we don't have any place to display log messages
|
||||
else
|
||||
wxASSERT(be->type == BX_SYNC_EVT_LOG_ASK);
|
||||
wxASSERT(be->type == BX_SYNC_EVT_LOG_ASK);
|
||||
wxString levelName(SIM->get_log_level_name(be->u.logmsg.level), wxConvUTF8);
|
||||
LogMsgAskDialog dlg(this, -1, levelName); // panic, error, etc.
|
||||
#if !BX_DEBUGGER && !BX_GDBSTUB
|
||||
@ -1161,9 +1169,9 @@ void MyFrame::OnLogMsg(BxEvent *be)
|
||||
wxLogDebug(wxT("you chose %d"), n);
|
||||
// This can be called from two different contexts:
|
||||
// 1) before sim_thread starts, the default application callback can
|
||||
// call OnLogMsg to display messages.
|
||||
// call OnLogAsk to display messages.
|
||||
// 2) after the sim_thread starts, the sim_thread callback can call
|
||||
// OnLogMsg to display messages
|
||||
// OnLogAsk to display messages
|
||||
if (sim_thread)
|
||||
sim_thread->SendSyncResponse(be); // only for case #2
|
||||
}
|
||||
|
@ -29,9 +29,7 @@ class MyFrame;
|
||||
class MyPanel;
|
||||
class SimThread;
|
||||
class ParamDialog;
|
||||
#if BX_DEBUGGER
|
||||
class DebugLogDialog;
|
||||
#endif
|
||||
class LogViewDialog;
|
||||
|
||||
//hack alert; yuck; FIXME
|
||||
extern MyFrame *theFrame;
|
||||
@ -85,7 +83,6 @@ enum
|
||||
ID_Toolbar_Copy,
|
||||
ID_Toolbar_Paste,
|
||||
ID_Toolbar_Snapshot,
|
||||
/*ID_Toolbar_Config,*/
|
||||
ID_Toolbar_Mouse_en,
|
||||
ID_Toolbar_User,
|
||||
ID_Toolbar_SaveRestore,
|
||||
@ -187,7 +184,7 @@ public:
|
||||
bx_bool SimThreadControl(bx_bool resume);
|
||||
void OnKillSim(wxCommandEvent& event);
|
||||
void OnSim2CIEvent(wxCommandEvent& event);
|
||||
void OnLogMsg(BxEvent *logMsgEvent);
|
||||
void OnLogAsk(BxEvent *be);
|
||||
void OnEditPluginCtrl(wxCommandEvent& event);
|
||||
void OnEditCPU(wxCommandEvent& event);
|
||||
void OnEditCPUID(wxCommandEvent& event);
|
||||
@ -203,6 +200,7 @@ public:
|
||||
void OnEditOther(wxCommandEvent& event);
|
||||
void OnLogPrefs(wxCommandEvent& event);
|
||||
void OnLogPrefsDevice(wxCommandEvent& event);
|
||||
void OnLogView(wxCommandEvent& event);
|
||||
void OnEditATA(wxCommandEvent& event);
|
||||
void editFloppyConfig(int drive);
|
||||
void editFirstCdrom();
|
||||
@ -227,6 +225,7 @@ private:
|
||||
wxMenu *menuLog;
|
||||
wxMenu *menuHelp;
|
||||
wxToolBar *bxToolBar;
|
||||
LogViewDialog *showLogView;
|
||||
public:
|
||||
|
||||
DECLARE_EVENT_TABLE()
|
||||
|
Loading…
Reference in New Issue
Block a user