5 * Nicolas Boichat, April 2004
9 Copyright (C) 2004 Kern Sibbald and John Walker
11 This program is free software; you can redistribute it and/or
12 modify it under the terms of the GNU General Public License
13 as published by the Free Software Foundation; either version 2
14 of the License, or (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 #include "wxbmainframe.h" // class's header file
28 #include "wxbrestorepanel.h"
32 #include "wxwin16x16.xpm"
34 #include <wx/arrimpl.cpp>
36 // ----------------------------------------------------------------------------
37 // event tables and other macros for wxWindows
38 // ----------------------------------------------------------------------------
40 // ----------------------------------------------------------------------------
42 // ----------------------------------------------------------------------------
44 // IDs for the controls and the menu commands
50 // it is important for the id corresponding to the "About" command to have
51 // this standard value as otherwise it won't be handled properly under Mac
52 // (where it is special and put into the "Apple" menu)
53 Minimal_About = wxID_ABOUT,
59 * wxbTHREAD_EVENT declaration, used by csprint
61 BEGIN_DECLARE_EVENT_TYPES()
62 DECLARE_EVENT_TYPE(wxbTHREAD_EVENT, 1)
63 END_DECLARE_EVENT_TYPES()
65 DEFINE_EVENT_TYPE(wxbTHREAD_EVENT)
67 // the event tables connect the wxWindows events with the functions (event
68 // handlers) which process them. It can be also done at run-time, but for the
69 // simple menu events like this the static method is much simpler.
70 BEGIN_EVENT_TABLE(wxbMainFrame, wxFrame)
71 EVT_MENU(Minimal_Quit, wxbMainFrame::OnQuit)
72 EVT_MENU(Minimal_About, wxbMainFrame::OnAbout)
73 EVT_TEXT_ENTER(TypeText, wxbMainFrame::OnEnter)
74 EVT_CUSTOM(wxbTHREAD_EVENT, Thread, wxbMainFrame::OnPrint)
77 // ----------------------------------------------------------------------------
79 // ----------------------------------------------------------------------------
82 * wxbThreadEvent constructor
84 wxbThreadEvent::wxbThreadEvent(int id): wxEvent(id, wxbTHREAD_EVENT) {
89 * wxbThreadEvent destructor
91 wxbThreadEvent::~wxbThreadEvent()
93 if (m_eventObject != NULL) {
99 * wxbThreadEvent copy constructor
101 wxbThreadEvent::wxbThreadEvent(const wxbThreadEvent& te)
103 this->m_eventType = te.m_eventType;
104 this->m_id = te.m_id;
105 if (te.m_eventObject != NULL) {
106 this->m_eventObject = new wxbPrintObject(*((wxbPrintObject*)te.m_eventObject));
109 this->m_eventObject = NULL;
111 this->m_skipped = te.m_skipped;
112 this->m_timeStamp = te.m_timeStamp;
116 * Must be implemented (abstract in wxEvent)
118 wxEvent* wxbThreadEvent::Clone() const
120 return new wxbThreadEvent(*this);
124 * Gets the wxbPrintObject attached to this event, containing data sent by director
126 wxbPrintObject* wxbThreadEvent::GetEventPrintObject()
128 return (wxbPrintObject*)m_eventObject;
132 * Sets the wxbPrintObject attached to this event
134 void wxbThreadEvent::SetEventPrintObject(wxbPrintObject* object)
136 m_eventObject = (wxObject*)object;
139 // ----------------------------------------------------------------------------
141 // ----------------------------------------------------------------------------
143 wxbMainFrame *wxbMainFrame::frame = NULL;
146 * Singleton constructor
148 wxbMainFrame* wxbMainFrame::CreateInstance(const wxString& title, const wxPoint& pos, const wxSize& size, long style)
150 frame = new wxbMainFrame(title, pos, size, style);
155 * Returns singleton instance
157 wxbMainFrame* wxbMainFrame::GetInstance()
165 wxbMainFrame::~wxbMainFrame()
167 if ((ct != NULL) && (!ct->IsRunning())) {
173 * Private constructor
175 wxbMainFrame::wxbMainFrame(const wxString& title, const wxPoint& pos, const wxSize& size, long style)
176 : wxFrame(NULL, -1, title, pos, size, style)
180 // set the frame icon
181 SetIcon(wxIcon(wxwin16x16_xpm));
185 wxMenu *menuFile = new wxMenu;
187 // the "About" item should be in the help menu
188 wxMenu *helpMenu = new wxMenu;
189 helpMenu->Append(Minimal_About, _T("&About...\tF1"), _T("Show about dialog"));
191 menuFile->Append(Minimal_Quit, _T("E&xit\tAlt-X"), _T("Quit this program"));
193 // now append the freshly created menu to the menu bar...
194 wxMenuBar *menuBar = new wxMenuBar();
195 menuBar->Append(menuFile, _T("&File"));
196 menuBar->Append(helpMenu, _T("&Help"));
198 // ... and attach this menu bar to the frame
200 #endif // wxUSE_MENUS
203 // create a status bar just for fun (by default with 1 pane only)
205 SetStatusText(_T("Welcome to Bacula wx-console!"));
206 #endif // wxUSE_STATUSBAR
208 wxPanel* global = new wxPanel(this, -1);
210 notebook = new wxNotebook(global, -1);
214 wxPanel* consolePanel = new wxPanel(notebook, -1);
215 notebook->AddPage(consolePanel, "Console");
217 consoleCtrl = new wxTextCtrl(consolePanel,-1,"",wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxTE_READONLY | wxTE_RICH);
218 consoleCtrl->SetDefaultStyle(wxTextAttr(*wxBLACK, wxNullColour, wxFont(10, wxMODERN, wxNORMAL, wxNORMAL)));
220 typeCtrl = new wxTextCtrl(consolePanel,TypeText,"",wxDefaultPosition,wxSize(200,20), wxTE_PROCESS_ENTER);
222 wxFlexGridSizer *consoleSizer = new wxFlexGridSizer(2, 1, 0, 0);
223 consoleSizer->AddGrowableCol(0);
224 consoleSizer->AddGrowableRow(0);
226 consoleSizer->Add(consoleCtrl, 1, wxEXPAND | wxALL, 0);
227 consoleSizer->Add(typeCtrl, 0, wxEXPAND | wxALL, 0);
229 consolePanel->SetAutoLayout( TRUE );
230 consolePanel->SetSizer( consoleSizer );
231 consoleSizer->SetSizeHints( consolePanel );
233 // Creates the list of panels which are included in notebook, and that need to receive director information
235 panels = new wxbPanel* [2];
236 panels[0] = new wxbRestorePanel(notebook);
239 for (int i = 0; panels[i] != NULL; i++) {
240 notebook->AddPage(panels[i], panels[i]->GetTitle());
243 wxBoxSizer* globalSizer = new wxBoxSizer(wxHORIZONTAL);
245 globalSizer->Add(new wxNotebookSizer(notebook), 1, wxEXPAND, 0);
247 global->SetSizer( globalSizer );
248 globalSizer->SetSizeHints( global );
250 wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
252 sizer->Add(global, 1, wxEXPAND | wxALL, 0);
255 sizer->SetSizeHints( this );
257 EnableConsole(false);
263 * Starts the thread interacting with the director
265 void wxbMainFrame::StartConsoleThread()
271 promptparser = new wxbPromptParser();
273 ct = new console_thread();
278 /* Register a new wxbDataParser */
279 void wxbMainFrame::Register(wxbDataParser* dp) {
283 /* Unregister a wxbDataParser */
284 void wxbMainFrame::Unregister(wxbDataParser* dp) {
286 if ((index = parsers.Index(dp)) != wxNOT_FOUND) {
287 parsers.RemoveAt(index);
290 Print("Failed to unregister a data parser !", CS_DEBUG);
296 void wxbMainFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
298 // TRUE is to force the frame to close
302 void wxbMainFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
305 msg.Printf( _T("Welcome to Bacula wx-console.\nWritten by Nicolas Boichat <nicolas@boichat.ch>\n(C) 2004 Kern Sibbald and John Walker\n"));
307 wxMessageBox(msg, _T("About Bacula wx-console"), wxOK | wxICON_INFORMATION, this);
310 void wxbMainFrame::OnEnter(wxCommandEvent& WXUNUSED(event))
312 wxString str = typeCtrl->GetValue() + "\n";
317 * Called when data is arriving from director
319 void wxbMainFrame::OnPrint(wxbThreadEvent& event) {
320 wxbPrintObject* po = event.GetEventPrintObject();
322 Print(po->str, po->status);
326 * Prints data received from director to the console, and forwards it to the panels
328 void wxbMainFrame::Print(wxString str, int status)
330 if (status == CS_CONNECTED) {
334 if (status == CS_DISCONNECTED) {
339 // CS_DEBUG is often sent by panels,
340 // and resend it to them would sometimes cause infinite loops
342 /* One promptcaught is normal, so we must have two true Print values to be
343 * sure that the prompt has effectively been caught.
345 int promptcaught = -1;
347 if (status != CS_DEBUG) {
348 for (unsigned int i = 0; i < parsers.GetCount(); i++) {
349 promptcaught += parsers[i]->Print(str, status) ? 1 : 0;
352 if ((status == CS_PROMPT) && (promptcaught < 1) && (promptparser->isPrompt())) {
353 Print("Unexpected question has been received.\n", CS_DEBUG);
354 // Print(wxString("(") << promptparser->getIntroString() << "/-/" << promptparser->getQuestionString() << ")\n", CS_DEBUG);
357 if (promptparser->getIntroString() != "") {
358 message << promptparser->getIntroString() << "\n";
360 message << promptparser->getQuestionString();
362 if (promptparser->getChoices()) {
363 wxString *choices = new wxString[promptparser->getChoices()->GetCount()];
364 int *numbers = new int[promptparser->getChoices()->GetCount()];
367 for (unsigned int i = 0; i < promptparser->getChoices()->GetCount(); i++) {
368 if ((*promptparser->getChoices())[i] != "") {
369 choices[n] = (*promptparser->getChoices())[i];
375 int res = ::wxGetSingleChoiceIndex(message,
376 "wx-console: unexpected director's question.", n, choices, this);
381 Send(wxString() << numbers[res] << "\n");
385 Send(::wxGetTextFromUser(message,
386 "wx-console: unexpected director's question.", "", this) + "\n");
391 if (status == CS_END) {
395 if (status == CS_DEBUG) {
396 consoleCtrl->SetDefaultStyle(wxTextAttr(wxColour(0, 128, 0)));
399 consoleCtrl->SetDefaultStyle(wxTextAttr(*wxBLACK));
401 (*consoleCtrl) << str;
402 if (status == CS_PROMPT) {
403 (*consoleCtrl) << "<P>";
405 /*if (status != CS_DEBUG) {
406 (*consoleCtrl) << "@";
408 //consoleCtrl->SetInsertionPointEnd();
410 /* if ((consoleCtrl->GetNumberOfLines()-1) > nlines) {
411 nlines = consoleCtrl->GetNumberOfLines()-1;
414 if (status == CS_END) {
415 consoleCtrl->ShowPosition(nlines);
420 * Sends data to the director
422 void wxbMainFrame::Send(wxString str)
424 ct->Write((const char*)str);
425 typeCtrl->SetValue("");
426 consoleCtrl->SetDefaultStyle(wxTextAttr(*wxRED));
427 (*consoleCtrl) << str;
429 /* if ((consoleCtrl->GetNumberOfLines()-1) > nlines) {
430 nlines = consoleCtrl->GetNumberOfLines()-1;
433 consoleCtrl->ShowPosition(nlines);*/
437 void wxbMainFrame::EnablePanels() {
438 for (int i = 0; panels[i] != NULL; i++) {
439 panels[i]->EnablePanel(true);
444 /* Disable panels, except the one passed as parameter */
445 void wxbMainFrame::DisablePanels(void* except) {
446 for (int i = 0; panels[i] != NULL; i++) {
447 if (panels[i] != except) {
448 panels[i]->EnablePanel(false);
451 panels[i]->EnablePanel(true);
454 if (this != except) {
455 EnableConsole(false);
459 /* Enable or disable console typing */
460 void wxbMainFrame::EnableConsole(bool enable) {
461 typeCtrl->Enable(enable);
465 * Used by csprint, which is called by console thread.
467 * In GTK and perhaps X11, only the main thread is allowed to interact with
468 * graphical components, so by firing an event, the main loop will call OnPrint.
470 * Calling OnPrint directly from console thread produces "unexpected async replies".
472 void firePrintEvent(wxString str, int status)
474 wxbPrintObject* po = new wxbPrintObject(str, status);
476 wxbThreadEvent evt(Thread);
477 evt.SetEventPrintObject(po);
479 wxbMainFrame::GetInstance()->AddPendingEvent(evt);
482 //wxString csBuffer; /* Temporary buffer for receiving data from console thread */
485 * Called by console thread, this function forwards data line by line and end
486 * signals to the GUI.
488 void csprint(char* str, int status)
491 firePrintEvent(wxString(str), status);
494 firePrintEvent("", status);