]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/wx-console/wxbmainframe.cpp
- Fix ANSI labels to put EOF1 and EOF2 after each file mark.
[bacula/bacula] / bacula / src / wx-console / wxbmainframe.cpp
index 4a6623495d762e216f380138f81b9632bda8cf29..5f03634826dd03801857d8d19287d9ea43297ed5 100644 (file)
@@ -2,8 +2,9 @@
  *
  *   Main frame
  *
- *    Nicolas Boichat, April 2004
+ *    Nicolas Boichat, July 2004
  *
+ *    Version $Id$
  */
 /*
    Copyright (C) 2004 Kern Sibbald and John Walker
@@ -27,6 +28,8 @@
 
 #include "wxbrestorepanel.h"
 
+#include "wxbconfigfileeditor.h"
+
 #include "csprint.h"
 
 #include "wxwin16x16.xpm"
 #include <wx/arrimpl.cpp>
 
 #include <wx/stattext.h>
+#include <wx/statline.h>
+#include <wx/config.h>
+
+#include <wx/filename.h>
+
+#undef Yield /* MinGW defines Yield */
 
 // ----------------------------------------------------------------------------
 // event tables and other macros for wxWindows
@@ -53,9 +62,14 @@ enum
    // this standard value as otherwise it won't be handled properly under Mac
    // (where it is special and put into the "Apple" menu)
    Minimal_About = wxID_ABOUT,
-   TypeText = 2,
-   SendButton = 3,
-   Thread = 4
+   
+   ChangeConfigFile = 2,
+   EditConfigFile = 3,
+   MenuConnect = 4,
+   MenuDisconnect = 5,
+   TypeText = 6,
+   SendButton = 7,
+   Thread = 8
 };
 
 /*
@@ -67,15 +81,28 @@ END_DECLARE_EVENT_TYPES()
 
 DEFINE_EVENT_TYPE(wxbTHREAD_EVENT)
 
+typedef void (wxEvtHandler::*wxThreadEventFunction)(wxbThreadEvent&);
+
+#define EVT_THREAD_EVENT(id, fn) \
+    DECLARE_EVENT_TABLE_ENTRY( \
+        wxbTHREAD_EVENT, id, wxID_ANY, \
+        (wxObjectEventFunction)(wxEventFunction)(wxThreadEventFunction)&fn, \
+        (wxObject *) NULL \
+    ),
+
 // the event tables connect the wxWindows events with the functions (event
 // handlers) which process them. It can be also done at run-time, but for the
 // simple menu events like this the static method is much simpler.
 BEGIN_EVENT_TABLE(wxbMainFrame, wxFrame)
    EVT_MENU(Minimal_Quit,  wxbMainFrame::OnQuit)
    EVT_MENU(Minimal_About, wxbMainFrame::OnAbout)
+   EVT_MENU(ChangeConfigFile, wxbMainFrame::OnChangeConfig)
+   EVT_MENU(EditConfigFile, wxbMainFrame::OnEditConfig)
+   EVT_MENU(MenuConnect, wxbMainFrame::OnConnect)
+   EVT_MENU(MenuDisconnect, wxbMainFrame::OnDisconnect)
    EVT_TEXT_ENTER(TypeText, wxbMainFrame::OnEnter)
+   EVT_THREAD_EVENT(Thread, wxbMainFrame::OnPrint)
    EVT_BUTTON(SendButton, wxbMainFrame::OnEnter)
-   EVT_CUSTOM(wxbTHREAD_EVENT, Thread, wxbMainFrame::OnPrint)
 END_EVENT_TABLE()
 
 // ----------------------------------------------------------------------------
@@ -171,6 +198,7 @@ wxbMainFrame::~wxbMainFrame()
    if (ct != NULL) { // && (!ct->IsRunning())
       ct->Delete();
    }
+   frame = NULL;
 }
 
 /*
@@ -180,18 +208,26 @@ wxbMainFrame::wxbMainFrame(const wxString& title, const wxPoint& pos, const wxSi
       : wxFrame(NULL, -1, title, pos, size, style)
 {
    ct = NULL;
+   
+   promptparser = NULL;
 
    // set the frame icon
    SetIcon(wxIcon(wxwin16x16_xpm));
 
 #if wxUSE_MENUS
    // create a menu bar
-   wxMenu *menuFile = new wxMenu;
+   menuFile = new wxMenu;
 
    // the "About" item should be in the help menu
    wxMenu *helpMenu = new wxMenu;
    helpMenu->Append(Minimal_About, _T("&About...\tF1"), _T("Show about dialog"));
 
+   menuFile->Append(MenuConnect, _T("Connect"), _T("Connect to the director"));
+   menuFile->Append(MenuDisconnect, _T("Disconnect"), _T("Disconnect of the director"));
+   menuFile->AppendSeparator();
+   menuFile->Append(ChangeConfigFile, _T("Change of configuration file"), _T("Change your default configuration file"));
+   menuFile->Append(EditConfigFile, _T("Edit your configuration file"), _T("Edit your configuration file"));
+   menuFile->AppendSeparator();
    menuFile->Append(Minimal_Quit, _T("E&xit\tAlt-X"), _T("Quit this program"));
 
    // now append the freshly created menu to the menu bar...
@@ -216,25 +252,36 @@ wxbMainFrame::wxbMainFrame(const wxString& title, const wxPoint& pos, const wxSi
    notebook->AddPage(consolePanel, "Console");
 
    consoleCtrl = new wxTextCtrl(consolePanel,-1,"",wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxTE_READONLY | wxTE_RICH);
-   consoleCtrl->SetDefaultStyle(wxTextAttr(*wxBLACK, wxNullColour, wxFont(10, wxMODERN, wxNORMAL, wxNORMAL)));
-
-   wxFlexGridSizer *consoleSizer = new wxFlexGridSizer(2, 1, 0, 0);
+   wxFont font(10, wxMODERN, wxNORMAL, wxNORMAL);
+#if defined __WXGTK12__ && !defined __WXGTK20__ // Fix for "chinese" fonts under gtk+ 1.2
+   font.SetDefaultEncoding(wxFONTENCODING_ISO8859_1);
+   consoleCtrl->SetDefaultStyle(wxTextAttr(*wxBLACK, wxNullColour, font));
+   Print("Warning : Unicode is disabled because you are using wxWidgets for GTK+ 1.2.\n", CS_DEBUG);
+#else
+   consoleCtrl->SetDefaultStyle(wxTextAttr(*wxBLACK, wxNullColour, font));
+#endif
+
+   helpCtrl = new wxStaticText(consolePanel, -1, "Type your command below:");
+
+   wxFlexGridSizer *consoleSizer = new wxFlexGridSizer(4, 1, 0, 0);
    consoleSizer->AddGrowableCol(0);
    consoleSizer->AddGrowableRow(0);
 
-   typeCtrl = new wxTextCtrl(consolePanel,TypeText,"",wxDefaultPosition,wxSize(200,20), wxTE_PROCESS_ENTER);
+   typeCtrl = new wxbHistoryTextCtrl(helpCtrl, consolePanel,TypeText,"",wxDefaultPosition,wxSize(200,20));
    sendButton = new wxButton(consolePanel, SendButton, "Send");
    
-   wxFlexGridSizer *typeSizer = new wxFlexGridSizer(1, 3, 0, 0);
-   typeSizer->AddGrowableCol(1);
+   wxFlexGridSizer *typeSizer = new wxFlexGridSizer(1, 2, 0, 0);
+   typeSizer->AddGrowableCol(0);
    typeSizer->AddGrowableRow(0);
 
-   typeSizer->Add(new wxStaticText(consolePanel, -1, "Command: "), 0, wxALIGN_CENTER | wxALL, 0);
+   //typeSizer->Add(new wxStaticText(consolePanel, -1, "Command: "), 0, wxALIGN_CENTER | wxALL, 0);
    typeSizer->Add(typeCtrl, 1, wxEXPAND | wxALL, 0);
    typeSizer->Add(sendButton, 1, wxEXPAND | wxLEFT, 5);
 
    consoleSizer->Add(consoleCtrl, 1, wxEXPAND | wxALL, 0);
-   consoleSizer->Add(typeSizer, 0, wxEXPAND | wxALL, 0);
+   consoleSizer->Add(new wxStaticLine(consolePanel, -1), 0, wxEXPAND | wxALL, 0);
+   consoleSizer->Add(helpCtrl, 1, wxEXPAND | wxALL, 2);
+   consoleSizer->Add(typeSizer, 0, wxEXPAND | wxALL, 2);
 
    consolePanel->SetAutoLayout( TRUE );
    consolePanel->SetSizer( consoleSizer );
@@ -269,19 +316,131 @@ wxbMainFrame::wxbMainFrame(const wxString& title, const wxPoint& pos, const wxSi
    lockedbyconsole = false;
    
    consoleBuffer = "";
+   
+   configfile = "";
 }
 
 /*
  *  Starts the thread interacting with the director
+ *  If config is not empty, uses this config file.
  */
-void wxbMainFrame::StartConsoleThread()
-{
+void wxbMainFrame::StartConsoleThread(const wxString& config) {
+   menuFile->Enable(MenuConnect, false);
+   menuFile->Enable(MenuDisconnect, false);
+   menuFile->Enable(ChangeConfigFile, false);
+   menuFile->Enable(EditConfigFile, false);
+
    if (ct != NULL) {
       ct->Delete();
+      ct = NULL;
+      wxTheApp->Yield();
    }
-   else {
+   if (promptparser == NULL) {
       promptparser = new wxbPromptParser();      
    }
+   
+   if (config == "") {
+      configfile = "";
+      
+      if (((wxTheApp->argc % 2) != 1)) {
+         Print("Error while parsing command line arguments, using defaults.\n", CS_DEBUG);
+         Print("Usage: wx-console [-c configfile] [-w tmp]\n", CS_DEBUG);
+      }
+      else {
+         for (int c = 1; c < wxTheApp->argc; c += 2) {
+            if ((wxTheApp->argc >= c+2) && (wxString(wxTheApp->argv[c]) == "-c")) {
+               configfile = wxTheApp->argv[c+1];
+            }
+            if ((wxTheApp->argc >= c+2) && (wxString(wxTheApp->argv[c]) == "-w")) {
+               console_thread::SetWorkingDirectory(wxTheApp->argv[c+1]);
+            }
+            if (wxTheApp->argv[c][0] != '-') {
+               Print("Error while parsing command line arguments, using defaults.\n", CS_DEBUG);
+               Print("Usage: wx-console [-c configfile] [-w tmp]\n", CS_DEBUG);
+               break;
+            }
+         }
+      }
+      
+      if (configfile == "") {
+         wxConfig::Set(new wxConfig("wx-console", "bacula"));
+         if (!wxConfig::Get()->Read("/ConfigFile", &configfile)) {
+#ifdef HAVE_MACOSX
+            wxFileName filename(::wxGetHomeDir());
+            filename.MakeAbsolute();
+            configfile = filename.GetLongPath();
+            if (configfile.Last() != '/')
+               configfile += '/';
+            configfile += "Library/Preferences/org.bacula.wxconsole.conf";
+#else
+            wxFileName filename(::wxGetCwd(), "wx-console.conf");
+            filename.MakeAbsolute();
+            configfile = filename.GetLongPath();
+#ifdef HAVE_WIN32
+            configfile.Replace("\\", "/");
+#endif //HAVE_WIN32
+#endif //HAVE_MACOSX
+            wxConfig::Get()->Write("/ConfigFile", configfile);
+   
+            int answer = wxMessageBox(
+                              wxString("It seems that it is the first time you run wx-console.\n") <<
+                                 "This file (" << configfile << ") has been choosen as default configuration file.\n" << 
+                                 "Do you want to edit it? (if you click No you will have to select another file)",
+                              "First run",
+                              wxYES_NO | wxICON_QUESTION, this);
+            if (answer == wxYES) {
+               wxbConfigFileEditor(this, configfile).ShowModal();
+            }
+         }
+      }
+   }
+   else {
+      configfile = config;
+   }
+   
+   wxString err = console_thread::LoadConfig(configfile);
+   
+   while (err != "") {
+      int answer = wxMessageBox(
+                        wxString("Unable to read ") << configfile << "\n" << 
+                           err << "\nDo you want to choose another one? (Press no to edit this file)",
+                        "Unable to read configuration file",
+                        wxYES_NO | wxCANCEL | wxICON_ERROR, this);
+      if (answer == wxNO) {
+         wxbConfigFileEditor(this, configfile).ShowModal();
+         err = console_thread::LoadConfig(configfile);
+      }
+      else if (answer == wxCANCEL) {
+         frame = NULL;
+         Close(true);
+         return;
+      }
+      else { // (answer == wxYES)
+         configfile = wxFileSelector("Please choose a configuration file to use");
+         if ( !configfile.empty() ) {
+            err = console_thread::LoadConfig(configfile);
+         }
+         else {
+            frame = NULL;
+            Close(true);
+            return;
+         }
+      }
+      
+      if ((err == "") && (config == "")) {
+         answer = wxMessageBox(
+                           "This configuration file has been successfully read, use it as default?",
+                           "Configuration file read successfully",
+                           wxYES_NO | wxICON_QUESTION, this);
+         if (answer == wxYES) {
+              wxConfigBase::Get()->Write("/ConfigFile", configfile);
+         }
+         break;
+      }
+   }
+   
+   csprint(wxString("Using this configuration file: ") << configfile << "\n", CS_DEBUG);
+   
    ct = new console_thread();
    ct->Create();
    ct->Run();
@@ -308,7 +467,15 @@ void wxbMainFrame::Unregister(wxbDataParser* dp) {
 
 void wxbMainFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
 {
-   // TRUE is to force the frame to close
+   Print("Quitting.\n", CS_DEBUG);
+   if (ct != NULL) {
+      ct->Delete();
+      ct = NULL;
+      wxTheApp->Yield();
+   }
+   console_thread::FreeLib();
+   frame = NULL;
+   wxTheApp->Yield();
    Close(TRUE);
 }
 
@@ -320,10 +487,53 @@ void wxbMainFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
    wxMessageBox(msg, _T("About Bacula wx-console"), wxOK | wxICON_INFORMATION, this);
 }
 
+void wxbMainFrame::OnChangeConfig(wxCommandEvent& event) {
+   wxString oriconfigfile;
+   wxConfig::Get()->Read("/ConfigFile", &oriconfigfile);
+   wxString configfile = wxFileSelector("Please choose your default configuration file");
+   if ( !configfile.empty() ) {
+      if (oriconfigfile != configfile) {
+         int answer = wxMessageBox(
+                           "Use this configuration file as default?",
+                           "Configuration file",
+                           wxYES_NO | wxICON_QUESTION, this);
+         if (answer == wxYES) {
+              wxConfigBase::Get()->Write("/ConfigFile", configfile);
+              wxConfigBase::Get()->Flush();
+              StartConsoleThread("");
+              return;
+         }
+      }
+   
+      StartConsoleThread(configfile);
+   }
+}
+
+void wxbMainFrame::OnEditConfig(wxCommandEvent& event) {
+   wxString configfile;
+   wxConfig::Get()->Read("/ConfigFile", &configfile);
+   int stat = wxbConfigFileEditor(this, configfile).ShowModal();
+   if (stat == wxOK) {
+      StartConsoleThread(configfile);
+   }
+}
+
+void wxbMainFrame::OnConnect(wxCommandEvent& event) {
+   StartConsoleThread(configfile);
+}
+
+void wxbMainFrame::OnDisconnect(wxCommandEvent& event) {
+   if (ct != NULL) {
+      ct->Delete();
+      ct = NULL;
+   }
+}
+
 void wxbMainFrame::OnEnter(wxCommandEvent& WXUNUSED(event))
 {
    lockedbyconsole = true;
    DisablePanels();
+   typeCtrl->HistoryAdd(typeCtrl->GetValue());
    wxString str = typeCtrl->GetValue() + "\n";
    Send(str);
 }
@@ -350,19 +560,50 @@ void wxbMainFrame::Print(wxString str, int status)
       consoleCtrl->AppendText(consoleBuffer);
       consoleBuffer = "";
       SetStatusText("Console thread terminated.");
+      consoleCtrl->ScrollLines(3);
       ct = NULL;
       DisablePanels();
+      int answer = wxMessageBox("Connection to the director lost. Quit program?", "Connection lost",
+                        wxYES_NO | wxICON_EXCLAMATION, this);
+      if (answer == wxYES) {
+         frame = NULL;
+         Close(true);
+      }
+      menuFile->Enable(MenuConnect, true);
+      menuFile->SetLabel(MenuConnect, "Connect");
+      menuFile->SetHelpString(MenuConnect, "Connect to the director");
+      menuFile->Enable(MenuDisconnect, false);
+      menuFile->Enable(ChangeConfigFile, true);
+      menuFile->Enable(EditConfigFile, true);
       return;
    }
    
    if (status == CS_CONNECTED) {
       SetStatusText("Connected to the director.");
+      typeCtrl->ClearCommandList();
+      wxbDataTokenizer* dt = wxbUtils::WaitForEnd(".help", true);
+      int i, j;
+      wxString str;
+      for (i = 0; i < (int)dt->GetCount(); i++) {
+         str = (*dt)[i];
+         str.RemoveLast();
+         if ((j = str.Find(' ')) > -1) {
+            typeCtrl->AddCommand(str.Mid(0, j), str.Mid(j+1));
+         }
+      }
       EnablePanels();
+      menuFile->Enable(MenuConnect, true);
+      menuFile->SetLabel(MenuConnect, "Reconnect");
+      menuFile->SetHelpString(MenuConnect, "Reconnect to the director");
+      menuFile->Enable(MenuDisconnect, true);
+      menuFile->Enable(ChangeConfigFile, true);
+      menuFile->Enable(EditConfigFile, true);
       return;
    }
    if (status == CS_DISCONNECTED) {
       consoleCtrl->AppendText(consoleBuffer);
       consoleBuffer = "";
+      consoleCtrl->ScrollLines(3);
       SetStatusText("Disconnected of the director.");
       DisablePanels();
       return;
@@ -406,11 +647,16 @@ void wxbMainFrame::Print(wxString str, int status)
             
             int res = ::wxGetSingleChoiceIndex(message,
                "wx-console: unexpected director's question.", n, choices, this);
-            if (res == -1) {
-               Send("\n");
+            if (res == -1) { //Cancel pressed
+               Send(".\n");
             }
             else {
-               Send(wxString() << numbers[res] << "\n");
+               if (promptparser->isNumericalChoice()) {
+                  Send(wxString() << numbers[res] << "\n");
+               }
+               else {
+                  Send(wxString() << choices[res] << "\n");
+               }
             }
          }
          else {
@@ -431,6 +677,7 @@ void wxbMainFrame::Print(wxString str, int status)
    if (status == CS_DEBUG) {
       consoleCtrl->AppendText(consoleBuffer);
       consoleBuffer = "";
+      consoleCtrl->ScrollLines(3);
       consoleCtrl->SetDefaultStyle(wxTextAttr(wxColour(0, 128, 0)));
    }
    else {
@@ -441,7 +688,7 @@ void wxbMainFrame::Print(wxString str, int status)
       if (lockedbyconsole) {
          EnableConsole(true);
       }
-      consoleBuffer << "<P>";
+      //consoleBuffer << "<P>";
    }
    
    if ((status == CS_END) || (status == CS_PROMPT) || (str.Find("\n") > -1)) {
@@ -513,6 +760,7 @@ void wxbMainFrame::DisablePanels(void* except) {
 /* Enable or disable console typing */
 void wxbMainFrame::EnableConsole(bool enable) {
    typeCtrl->Enable(enable);
+   sendButton->Enable(enable);
    if (enable) {
       typeCtrl->SetFocus();
    }
@@ -532,8 +780,10 @@ void firePrintEvent(wxString str, int status)
 
    wxbThreadEvent evt(Thread);
    evt.SetEventPrintObject(po);
-
-   wxbMainFrame::GetInstance()->AddPendingEvent(evt);
+   
+   if (wxbMainFrame::GetInstance()) {
+      wxbMainFrame::GetInstance()->AddPendingEvent(evt);
+   }
 }
 
 //wxString csBuffer; /* Temporary buffer for receiving data from console thread */
@@ -551,4 +801,3 @@ void csprint(const char* str, int status)
       firePrintEvent("", status);
    }
 }
-