2 Bacula® - The Network Backup Solution
4 Copyright (C) 2004-2007 Free Software Foundation Europe e.V.
6 The main author of Bacula is Kern Sibbald, with contributions from
7 many others, a complete list can be found in the file AUTHORS.
8 This program is Free Software; you can redistribute it and/or
9 modify it under the terms of version two of the GNU General Public
10 License as published by the Free Software Foundation and included
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 Bacula® is a registered trademark of John Walker.
24 The licensor of Bacula is the Free Software Foundation Europe
25 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26 Switzerland, email:ftf@fsfeurope.org.
32 * Nicolas Boichat, July 2004
37 /* Windows debug builds set _DEBUG which is used by wxWidgets to select their
38 * debug memory allocator. Unfortunately it conflicts with Bacula's SmartAlloc.
39 * So we turn _DEBUG off since we aren't interested in things it enables.
46 #include "wxbmainframe.h" // class's header file
48 #include "wxbrestorepanel.h"
50 #include "wxbconfigfileeditor.h"
54 #include "wxwin16x16.xpm"
56 #include <wx/arrimpl.cpp>
58 #include <wx/stattext.h>
59 #include <wx/statline.h>
60 #include <wx/config.h>
62 #include <wx/filename.h>
64 #undef Yield /* MinGW defines Yield */
66 // ----------------------------------------------------------------------------
67 // event tables and other macros for wxWindows
68 // ----------------------------------------------------------------------------
70 // ----------------------------------------------------------------------------
72 // ----------------------------------------------------------------------------
74 // IDs for the controls and the menu commands
80 // it is important for the id corresponding to the "About" command to have
81 // this standard value as otherwise it won't be handled properly under Mac
82 // (where it is special and put into the "Apple" menu)
83 Minimal_About = wxID_ABOUT,
95 * wxbTHREAD_EVENT declaration, used by csprint
98 DEFINE_EVENT_TYPE(wxbTHREAD_EVENT)
100 typedef void (wxEvtHandler::*wxThreadEventFunction)(wxbThreadEvent&);
102 #define EVT_THREAD_EVENT(id, fn) \
103 DECLARE_EVENT_TABLE_ENTRY( \
104 wxbTHREAD_EVENT, id, wxID_ANY, \
105 (wxObjectEventFunction)(wxEventFunction)(wxThreadEventFunction)&fn, \
109 // the event tables connect the wxWindows events with the functions (event
110 // handlers) which process them. It can be also done at run-time, but for the
111 // simple menu events like this the static method is much simpler.
112 BEGIN_EVENT_TABLE(wxbMainFrame, wxFrame)
113 EVT_MENU(Minimal_Quit, wxbMainFrame::OnQuit)
114 EVT_MENU(Minimal_About, wxbMainFrame::OnAbout)
115 EVT_MENU(ChangeConfigFile, wxbMainFrame::OnChangeConfig)
116 EVT_MENU(EditConfigFile, wxbMainFrame::OnEditConfig)
117 EVT_MENU(MenuConnect, wxbMainFrame::OnConnect)
118 EVT_MENU(MenuDisconnect, wxbMainFrame::OnDisconnect)
119 EVT_TEXT_ENTER(TypeText, wxbMainFrame::OnEnter)
120 EVT_THREAD_EVENT(Thread, wxbMainFrame::OnPrint)
121 EVT_BUTTON(SendButton, wxbMainFrame::OnEnter)
124 // ----------------------------------------------------------------------------
126 // ----------------------------------------------------------------------------
129 * wxbThreadEvent constructor
131 wxbThreadEvent::wxbThreadEvent(int id): wxEvent(id, wxbTHREAD_EVENT) {
132 m_eventObject = NULL;
136 * wxbThreadEvent destructor
138 wxbThreadEvent::~wxbThreadEvent()
140 if (m_eventObject != NULL) {
141 delete m_eventObject;
146 * wxbThreadEvent copy constructor
148 wxbThreadEvent::wxbThreadEvent(const wxbThreadEvent& te)
150 this->m_eventType = te.m_eventType;
151 this->m_id = te.m_id;
152 if (te.m_eventObject != NULL) {
153 this->m_eventObject = new wxbPrintObject(*((wxbPrintObject*)te.m_eventObject));
156 this->m_eventObject = NULL;
158 this->m_skipped = te.m_skipped;
159 this->m_timeStamp = te.m_timeStamp;
163 * Must be implemented (abstract in wxEvent)
165 wxEvent* wxbThreadEvent::Clone() const
167 return new wxbThreadEvent(*this);
171 * Gets the wxbPrintObject attached to this event, containing data sent by director
173 wxbPrintObject* wxbThreadEvent::GetEventPrintObject()
175 return (wxbPrintObject*)m_eventObject;
179 * Sets the wxbPrintObject attached to this event
181 void wxbThreadEvent::SetEventPrintObject(wxbPrintObject* object)
183 m_eventObject = (wxObject*)object;
186 // ----------------------------------------------------------------------------
188 // ----------------------------------------------------------------------------
190 wxbMainFrame *wxbMainFrame::frame = NULL;
193 * Singleton constructor
195 wxbMainFrame* wxbMainFrame::CreateInstance(const wxString& title, const wxPoint& pos, const wxSize& size, long style)
197 frame = new wxbMainFrame(title, pos, size, style);
202 * Returns singleton instance
204 wxbMainFrame* wxbMainFrame::GetInstance()
212 wxbMainFrame::~wxbMainFrame()
214 wxConfig::Get()->Write(wxT("/Position/X"), (long)GetPosition().x);
215 wxConfig::Get()->Write(wxT("/Position/Y"), (long)GetPosition().y);
216 wxConfig::Get()->Write(wxT("/Size/Width"), (long)GetSize().GetWidth());
217 wxConfig::Get()->Write(wxT("/Size/Height"), (long)GetSize().GetHeight());
219 if (ct != NULL) { // && (!ct->IsRunning())
226 * Private constructor
228 wxbMainFrame::wxbMainFrame(const wxString& title, const wxPoint& pos, const wxSize& size, long style)
229 : wxFrame(NULL, -1, title, pos, size, style)
231 lockedbyconsole = false;
237 // set the frame icon
238 SetIcon(wxIcon(wxwin16x16_xpm));
242 menuFile = new wxMenu;
244 // the "About" item should be in the help menu
245 wxMenu *helpMenu = new wxMenu;
246 helpMenu->Append(Minimal_About, _("&About...\tF1"), _("Show about dialog"));
248 menuFile->Append(MenuConnect, _("Connect"), _("Connect to the director"));
249 menuFile->Append(MenuDisconnect, _("Disconnect"), _("Disconnect of the director"));
250 menuFile->AppendSeparator();
251 menuFile->Append(ChangeConfigFile, _("Change of configuration file"), _("Change your default configuration file"));
252 menuFile->Append(EditConfigFile, _("Edit your configuration file"), _("Edit your configuration file"));
253 menuFile->AppendSeparator();
254 menuFile->Append(Minimal_Quit, _("E&xit\tAlt-X"), _("Quit this program"));
256 // now append the freshly created menu to the menu bar...
257 wxMenuBar *menuBar = new wxMenuBar();
258 menuBar->Append(menuFile, _("&File"));
259 menuBar->Append(helpMenu, _("&Help"));
261 // ... and attach this menu bar to the frame
263 #endif // wxUSE_MENUS
267 SetStatusText(wxString::Format(_("Welcome to bacula bwx-console %s (%s)!\n"), wxT(VERSION), wxT(BDATE)));
269 wxPanel* global = new wxPanel(this, -1);
271 notebook = new wxNotebook(global, -1);
275 wxPanel* consolePanel = new wxPanel(notebook, -1);
276 notebook->AddPage(consolePanel, _("Console"));
278 consoleCtrl = new wxTextCtrl(consolePanel,-1,wxT(""),wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxTE_READONLY | wxTE_RICH);
279 wxFont font(10, wxMODERN, wxNORMAL, wxNORMAL);
280 #if defined __WXGTK12__ && !defined __WXGTK20__ // Fix for "chinese" fonts under gtk+ 1.2
281 font.SetDefaultEncoding(wxFONTENCODING_ISO8859_1);
282 consoleCtrl->SetDefaultStyle(wxTextAttr(*wxBLACK, wxNullColour, font));
283 Print(_("Warning : Unicode is disabled because you are using wxWidgets for GTK+ 1.2.\n"), CS_DEBUG);
285 consoleCtrl->SetDefaultStyle(wxTextAttr(*wxBLACK, wxNullColour, font));
286 #if (wxUSE_UNICODE == 0) && __WXGTK20__
287 Print(_("Warning : There is a problem with wxWidgets for GTK+ 2.0 without Unicode support when handling non-ASCII filenames: Every non-ASCII character in such filenames will be replaced by an interrogation mark.\nIf this behaviour disturbs you, please build bwx-console against a Unicode version of wxWidgets for GTK+ 2.0.\n---\n"), CS_DEBUG);
291 helpCtrl = new wxStaticText(consolePanel, -1, _("Type your command below:"));
293 wxFlexGridSizer *consoleSizer = new wxFlexGridSizer(4, 1, 0, 0);
294 consoleSizer->AddGrowableCol(0);
295 consoleSizer->AddGrowableRow(0);
297 typeCtrl = new wxbHistoryTextCtrl(helpCtrl, consolePanel,TypeText,wxT(""),wxDefaultPosition,wxSize(200,20));
298 sendButton = new wxButton(consolePanel, SendButton, _("Send"));
300 wxFlexGridSizer *typeSizer = new wxFlexGridSizer(1, 2, 0, 0);
301 typeSizer->AddGrowableCol(0);
302 typeSizer->AddGrowableRow(0);
304 //typeSizer->Add(new wxStaticText(consolePanel, -1, _("Command: ")), 0, wxALIGN_CENTER | wxALL, 0);
305 typeSizer->Add(typeCtrl, 1, wxEXPAND | wxALL, 0);
306 typeSizer->Add(sendButton, 1, wxEXPAND | wxLEFT, 5);
308 consoleSizer->Add(consoleCtrl, 1, wxEXPAND | wxALL, 0);
309 consoleSizer->Add(new wxStaticLine(consolePanel, -1), 0, wxEXPAND | wxALL, 0);
310 consoleSizer->Add(helpCtrl, 1, wxEXPAND | wxALL, 2);
311 consoleSizer->Add(typeSizer, 0, wxEXPAND | wxALL, 2);
313 consolePanel->SetAutoLayout( TRUE );
314 consolePanel->SetSizer( consoleSizer );
315 consoleSizer->SetSizeHints( consolePanel );
317 // Creates the list of panels which are included in notebook, and that need to receive director information
319 panels = new wxbPanel* [2];
320 panels[0] = new wxbRestorePanel(notebook);
323 for (int i = 0; panels[i] != NULL; i++) {
324 notebook->AddPage(panels[i], panels[i]->GetTitle());
327 wxBoxSizer* globalSizer = new wxBoxSizer(wxHORIZONTAL);
329 #if wxCHECK_VERSION(2, 6, 0)
330 globalSizer->Add(notebook, 1, wxEXPAND, 0);
332 globalSizer->Add(new wxNotebookSizer(notebook), 1, wxEXPAND, 0);
335 global->SetSizer( globalSizer );
336 globalSizer->SetSizeHints( global );
338 wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
340 sizer->Add(global, 1, wxEXPAND | wxALL, 0);
343 sizer->SetSizeHints( this );
345 EnableConsole(false);
347 consoleBuffer = wxT("");
349 configfile = wxT("");
353 * Starts the thread interacting with the director
354 * If config is not empty, uses this config file.
356 void wxbMainFrame::StartConsoleThread(const wxString& config) {
357 menuFile->Enable(MenuConnect, false);
358 menuFile->Enable(MenuDisconnect, false);
359 menuFile->Enable(ChangeConfigFile, false);
360 menuFile->Enable(EditConfigFile, false);
367 if (promptparser == NULL) {
368 promptparser = new wxbPromptParser();
371 if (config == wxT("")) {
372 configfile = wxT("");
374 if (((wxTheApp->argc % 2) != 1)) {
375 Print(_("Error while parsing command line arguments, using defaults.\n"), CS_DEBUG);
376 Print(_("Usage: bwx-console [-c configfile] [-w tmp]\n"), CS_DEBUG);
379 for (int c = 1; c < wxTheApp->argc; c += 2) {
380 if ((wxTheApp->argc >= c+2) && (wxString(wxTheApp->argv[c]) == wxT("-c"))) {
381 configfile = wxTheApp->argv[c+1];
383 if ((wxTheApp->argc >= c+2) && (wxString(wxTheApp->argv[c]) == wxT("-w"))) {
384 console_thread::SetWorkingDirectory(wxTheApp->argv[c+1]);
386 if (wxTheApp->argv[c][0] != '-') {
387 Print(_("Error while parsing command line arguments, using defaults.\n"), CS_DEBUG);
388 Print(_("Usage: bwx-console [-c configfile] [-w tmp]\n"), CS_DEBUG);
394 if (configfile == wxT("")) {
395 wxConfig::Set(new wxConfig(wxT("bwx-console"), wxT("bacula")));
396 if (!wxConfig::Get()->Read(wxT("/ConfigFile"), &configfile)) {
398 wxFileName filename(::wxGetHomeDir());
399 filename.MakeAbsolute();
400 configfile = filename.GetLongPath();
401 if (!IsPathSeparator(configfile.Last())) {
404 configfile += L"Library/Preferences/org.bacula.wxconsole.conf";
406 wxFileName filename(::wxGetCwd(), wxT("bwx-console.conf"));
407 filename.MakeAbsolute();
408 configfile = filename.GetLongPath();
410 configfile.Replace(wxT("\\"), wxT("/"));
413 wxConfig::Get()->Write(wxT("/ConfigFile"), configfile);
415 int answer = wxMessageBox(
417 "It seems that it is the first time you run bwx-console.\nThis file (%s) has been choosen as default configuration file.\nDo you want to edit it? (if you click No you will have to select another file)"),
420 wxYES_NO | wxICON_QUESTION, this);
421 if (answer == wxYES) {
422 wxbConfigFileEditor(this, configfile).ShowModal();
431 wxString err = console_thread::LoadConfig(configfile);
433 while (err != wxT("")) {
434 int answer = wxMessageBox(
436 "Unable to read %s\nError: %s\nDo you want to choose another one? (Press no to edit this file)"),
437 configfile.c_str(), err.c_str()),
438 _("Unable to read configuration file"),
439 wxYES_NO | wxCANCEL | wxICON_ERROR, this);
440 if (answer == wxNO) {
441 wxbConfigFileEditor(this, configfile).ShowModal();
442 err = console_thread::LoadConfig(configfile);
444 else if (answer == wxCANCEL) {
449 else { // (answer == wxYES)
450 configfile = wxFileSelector(_("Please choose a configuration file to use"));
451 if ( !configfile.empty() ) {
452 err = console_thread::LoadConfig(configfile);
461 if ((err == wxT("")) && (config == wxT(""))) {
462 answer = wxMessageBox(
463 _("This configuration file has been successfully read, use it as default?"),
464 _("Configuration file read successfully"),
465 wxYES_NO | wxICON_QUESTION, this);
466 if (answer == wxYES) {
467 wxConfigBase::Get()->Write(wxT("/ConfigFile"), configfile);
473 // former was csprint
474 Print(wxString::Format(_("Using this configuration file: %s\n"), configfile.c_str()), CS_DEBUG);
476 ct = new console_thread();
479 SetStatusText(_("Connecting to the director..."));
482 /* Register a new wxbDataParser */
483 void wxbMainFrame::Register(wxbDataParser* dp) {
487 /* Unregister a wxbDataParser */
488 void wxbMainFrame::Unregister(wxbDataParser* dp) {
490 if ((index = parsers.Index(dp)) != wxNOT_FOUND) {
491 parsers.RemoveAt(index);
494 Print(_("Failed to unregister a data parser !"), CS_DEBUG);
500 void wxbMainFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
502 Print(_("Quitting.\n"), CS_DEBUG);
508 console_thread::FreeLib();
514 void wxbMainFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
517 msg.Printf(_("Welcome to Bacula bwx-console.\n"
518 "Written by Nicolas Boichat <nicolas@boichat.ch>\n"
519 "Copyright (C), 2005-2007 Free Software Foundation Europe, e.V.\n"));
521 wxMessageBox(msg, _("About Bacula bwx-console"), wxOK | wxICON_INFORMATION, this);
524 void wxbMainFrame::OnChangeConfig(wxCommandEvent& event) {
525 wxString oriconfigfile;
526 wxConfig::Get()->Read(wxT("/ConfigFile"), &oriconfigfile);
527 wxString configfile = wxFileSelector(_("Please choose your default configuration file"));
528 if ( !configfile.empty() ) {
529 if (oriconfigfile != configfile) {
530 int answer = wxMessageBox(
531 _("Use this configuration file as default?"),
532 _("Configuration file"),
533 wxYES_NO | wxICON_QUESTION, this);
534 if (answer == wxYES) {
535 wxConfigBase::Get()->Write(wxT("/ConfigFile"), configfile);
536 wxConfigBase::Get()->Flush();
537 StartConsoleThread(wxT(""));
542 StartConsoleThread(configfile);
546 void wxbMainFrame::OnEditConfig(wxCommandEvent& event) {
548 wxConfig::Get()->Read(wxT("/ConfigFile"), &configfile);
549 int stat = wxbConfigFileEditor(this, configfile).ShowModal();
551 StartConsoleThread(configfile);
555 void wxbMainFrame::OnConnect(wxCommandEvent& event) {
556 StartConsoleThread(configfile);
559 void wxbMainFrame::OnDisconnect(wxCommandEvent& event) {
566 void wxbMainFrame::OnEnter(wxCommandEvent& WXUNUSED(event))
568 lockedbyconsole = true;
570 typeCtrl->HistoryAdd(typeCtrl->GetValue());
571 wxString str = typeCtrl->GetValue() + wxT("\n");
576 * Called when data is arriving from director
578 void wxbMainFrame::OnPrint(wxbThreadEvent& event) {
579 wxbPrintObject* po = event.GetEventPrintObject();
581 Print(po->str, po->status);
585 * Prints data received from director to the console, and forwards it to the panels
587 void wxbMainFrame::Print(wxString str, int status)
589 if (lockedbyconsole) {
590 EnableConsole(false);
593 if (status == CS_REMOVEPROMPT) {
594 if (consoleCtrl->GetLastPosition() > 0) {
595 consoleCtrl->Remove(consoleCtrl->GetLastPosition()-1, consoleCtrl->GetLastPosition()+1);
600 if (status == CS_TERMINATED) {
601 consoleCtrl->AppendText(consoleBuffer);
602 consoleBuffer = wxT("");
603 SetStatusText(_("Console thread terminated."));
605 consoleCtrl->PageDown();
607 consoleCtrl->ScrollLines(1);
611 int answer = wxMessageBox( _("Connection to the director lost. Quit program?"),
612 _("Connection lost"),
613 wxYES_NO | wxICON_EXCLAMATION, this);
614 if (answer == wxYES) {
618 menuFile->Enable(MenuConnect, true);
619 menuFile->SetLabel(MenuConnect, _("Connect"));
620 menuFile->SetHelpString(MenuConnect, _("Connect to the director"));
621 menuFile->Enable(MenuDisconnect, false);
622 menuFile->Enable(ChangeConfigFile, true);
623 menuFile->Enable(EditConfigFile, true);
627 if (status == CS_CONNECTED) {
628 SetStatusText(_("Connected to the director."));
629 typeCtrl->ClearCommandList();
632 wxbDataTokenizer* dt = wxbUtils::WaitForEnd(wxT(".help"), true);
636 for (i = 0; i < (int)dt->GetCount(); i++) {
639 if ((j = str.Find(' ')) > -1) {
640 typeCtrl->AddCommand(str.Mid(0, j), str.Mid(j+1));
645 if ((parsed) || (!retries))
647 dt = wxbUtils::WaitForEnd(wxT(""), true);
650 menuFile->Enable(MenuConnect, true);
651 menuFile->SetLabel(MenuConnect, _("Reconnect"));
652 menuFile->SetHelpString(MenuConnect, _("Reconnect to the director"));
653 menuFile->Enable(MenuDisconnect, true);
654 menuFile->Enable(ChangeConfigFile, true);
655 menuFile->Enable(EditConfigFile, true);
658 if (status == CS_DISCONNECTED) {
659 consoleCtrl->AppendText(consoleBuffer);
660 consoleBuffer = wxT("");
662 consoleCtrl->PageDown();
664 consoleCtrl->ScrollLines(1);
666 SetStatusText(_("Disconnected of the director."));
671 // CS_DEBUG is often sent by panels,
672 // and resend it to them would sometimes cause infinite loops
674 /* One promptcaught is normal, so we must have two true Print values to be
675 * sure that the prompt has effectively been caught.
677 int promptcaught = -1;
679 if (status != CS_DEBUG) {
680 for (unsigned int i = 0; i < parsers.GetCount(); i++) {
681 promptcaught += parsers[i]->Print(str, status) ? 1 : 0;
684 if ((status == CS_PROMPT) && (promptcaught < 1) && (promptparser->isPrompt())) {
685 Print(_("Unexpected question has been received.\n"), CS_DEBUG);
686 // Print(wxString("(") << promptparser->getIntroString() << "/-/" << promptparser->getQuestionString() << ")\n", CS_DEBUG);
689 if (promptparser->getIntroString() != wxT("")) {
690 message << promptparser->getIntroString() << wxT("\n");
692 message << promptparser->getQuestionString();
694 if (promptparser->getChoices()) {
695 wxString *choices = new wxString[promptparser->getChoices()->GetCount()];
696 int *numbers = new int[promptparser->getChoices()->GetCount()];
699 for (unsigned int i = 0; i < promptparser->getChoices()->GetCount(); i++) {
700 if ((*promptparser->getChoices())[i] != wxT("")) {
701 choices[n] = (*promptparser->getChoices())[i];
707 int res = ::wxGetSingleChoiceIndex(message,
708 _("bwx-console: unexpected director's question."), n, choices, this);
709 if (res == -1) { //Cancel pressed
713 if (promptparser->isNumericalChoice()) {
714 Send(wxString() << numbers[res] << wxT("\n"));
717 Send(wxString() << choices[res] << wxT("\n"));
724 Send(::wxGetTextFromUser(message,
725 _("bwx-console: unexpected director's question."),
726 wxT(""), this) + wxT("\n"));
731 if (status == CS_END) {
732 if (lockedbyconsole) {
734 lockedbyconsole = false;
739 if (status == CS_DEBUG) {
740 consoleCtrl->AppendText(consoleBuffer);
741 consoleBuffer = wxT("");
743 consoleCtrl->PageDown();
745 consoleCtrl->ScrollLines(1);
747 consoleCtrl->SetDefaultStyle(wxTextAttr(wxColour(0, 128, 0)));
750 consoleCtrl->SetDefaultStyle(wxTextAttr(*wxBLACK));
752 consoleBuffer << wxbUtils::ConvertToPrintable(str);
753 if (status == CS_PROMPT) {
754 if (lockedbyconsole) {
757 //consoleBuffer << wxT("<P>");
760 if ((status == CS_END) || (status == CS_PROMPT) || (str.Find(wxT("\n")) > -1)) {
761 consoleCtrl->AppendText(consoleBuffer);
762 consoleBuffer = wxT("");
765 consoleCtrl->PageDown();
767 consoleCtrl->ScrollLines(1);
771 //consoleCtrl->ShowPosition(consoleCtrl->GetLastPosition());
773 /*if (status != CS_DEBUG) {
774 consoleCtrl->AppendText("@");
776 //consoleCtrl->SetInsertionPointEnd();
780 * Sends data to the director
782 void wxbMainFrame::Send(wxString str)
785 /* wxString may contain everything in UNICODE
786 * -> convert to UTF-8 and send to director
788 ct->Write (str.mb_str(wxConvUTF8));
789 typeCtrl->SetValue(wxT(""));
790 consoleCtrl->SetDefaultStyle(wxTextAttr(*wxRED));
791 consoleCtrl->AppendText(wxbUtils::ConvertToPrintable(str));
792 //consoleCtrl->PageDown();
795 /* if ((consoleCtrl->GetNumberOfLines()-1) > nlines) {
796 nlines = consoleCtrl->GetNumberOfLines()-1;
799 consoleCtrl->ShowPosition(nlines);*/
803 void wxbMainFrame::EnablePanels() {
804 for (int i = 0; panels[i] != NULL; i++) {
805 panels[i]->EnablePanel(true);
810 /* Disable panels, except the one passed as parameter */
811 void wxbMainFrame::DisablePanels(void* except) {
812 for (int i = 0; panels[i] != NULL; i++) {
813 if (panels[i] != except) {
814 panels[i]->EnablePanel(false);
817 panels[i]->EnablePanel(true);
820 if (this != except) {
821 EnableConsole(false);
825 /* Enable or disable console typing */
826 void wxbMainFrame::EnableConsole(bool enable) {
827 typeCtrl->Enable(enable);
828 sendButton->Enable(enable);
830 typeCtrl->SetFocus();
835 * Used by csprint, which is called by console thread.
837 * In GTK and perhaps X11, only the main thread is allowed to interact with
838 * graphical components, so by firing an event, the main loop will call OnPrint.
840 * Calling OnPrint directly from console thread produces "unexpected async replies".
842 void firePrintEvent(wxString str, int status)
844 wxbPrintObject* po = new wxbPrintObject(str, status);
846 wxbThreadEvent evt(Thread);
847 evt.SetEventPrintObject(po);
849 if (wxbMainFrame::GetInstance()) {
850 wxbMainFrame::GetInstance()->AddPendingEvent(evt);
854 //wxString csBuffer; /* Temporary buffer for receiving data from console thread */
857 * Called by console thread, this function forwards data line by line and end
858 * signals to the GUI.
861 void csprint(wxString str, int status)
863 firePrintEvent(str, status);
867 void csprint(const char* str, int status)
870 firePrintEvent(wxString(str,wxConvUTF8), status);
873 firePrintEvent(wxT(""), status);