Better looking toolbar styles (especially on Windows)
[qemu-gui.git] / mainframe.cpp
blobcaed5a9c4094872b0ce8d1c32cea99a3588d05f6
1 #include <wx/wx.h>
2 #include <wx/arrimpl.cpp>
3 #include <wx/docview.h>
4 #include "mainframe.h"
5 #include "wizard.h"
6 #include "qemu-ui.h"
7 #include "console.h"
8 #include "vm.h"
9 #include "config.h"
10 #include "notebook.h"
11 #include "menubar.h"
12 #include "toolbar.h"
13 #include "statusbar.h"
14 #include "vncpanel.h"
15 #include "vmdialog.h"
16 #include "events.h"
18 #if defined __WXDEBUG__
19 #include <wx/debug.h>
20 #include <wx/memory.h>
21 #endif
23 #if !defined(__WXMSW__) && !defined(__WXPM__)
24 #include "icons/icon.xpm"
25 #endif
27 BEGIN_EVENT_TABLE(QemuMainFrame, wxFrame)
28 EVT_MENU(QEMU_NEW, QemuMainFrame::OnNewVM)
29 EVT_COMMAND(wxID_ANY,EVT_NEW_VM,QemuMainFrame::OnNewVM)
30 EVT_MENU(QEMU_OPEN, QemuMainFrame::OnOpenVM)
31 EVT_COMMAND(wxID_ANY,EVT_OPEN_VM,QemuMainFrame::OnOpenVM)
32 EVT_MENU_RANGE(wxID_FILE1, wxID_FILE9, QemuMainFrame::OnReOpenVM)
34 EVT_MENU(QEMU_CLOSE, QemuMainFrame::OnNotebookPageClosed)
35 EVT_MENU(QEMU_QUIT, QemuMainFrame::OnQuitCommandEvent)
36 EVT_CLOSE(QemuMainFrame::OnQuit)
38 EVT_MENU(QEMU_HOMEPAGE, QemuMainFrame::OnShowHomepage)
39 EVT_MENU(QEMU_FULLSCREEN, QemuMainFrame::OnFullScreen)
40 EVT_MENU(QEMU_TOGGLE_TOOLBAR, QemuMainFrame::OnToggleToolBar)
41 EVT_MENU(QEMU_TOOLBAR_TEXT, QemuMainFrame::OnToolBarSettingChange)
42 EVT_MENU(QEMU_TOOLBAR_ICONS, QemuMainFrame::OnToolBarSettingChange)
43 EVT_MENU(QEMU_TOOLBAR_BOTH, QemuMainFrame::OnToolBarSettingChange)
44 EVT_MENU(QEMU_TOGGLE_STATUSBAR, QemuMainFrame::OnToggleStatusBar)
46 EVT_MENU(QEMU_VM_SETTINGS,QemuMainFrame::OnVMSettings)
47 EVT_MENU(QEMU_VM_SEND_CTRL_ALT_DEL,QemuMainFrame::OnVMSendCtrlAltDel)
49 EVT_MENU(QEMU_VM_START,QemuMainFrame::OnPowerOnVM)
50 EVT_MENU(QEMU_VM_PAUSE,QemuMainFrame::OnPauseVM)
51 EVT_MENU(QEMU_VM_SHUTDOWN,QemuMainFrame::OnPowerOffVM)
52 EVT_MENU(QEMU_VM_RESET,QemuMainFrame::OnResetVM)
53 EVT_MENU(QEMU_VM_KILL,QemuMainFrame::OnKillVM)
55 EVT_MENU(QEMU_VM_SNAPSHOT,QemuMainFrame::OnSnapshot)
56 EVT_MENU(QEMU_VM_REVERT_SNAPSHOT,QemuMainFrame::OnRevertSnapshot)
58 EVT_MENU(QEMU_TOOLBAR_DISPLAY_INFO,QemuMainFrame::OnToggleDisplay)
59 EVT_MENU(QEMU_TOOLBAR_DISPLAY_SCREEN,QemuMainFrame::OnToggleDisplay)
60 EVT_MENU(QEMU_TOOLBAR_DISPLAY_CONSOLE,QemuMainFrame::OnToggleDisplay)
62 EVT_MENU(QEMU_TOOLBAR_SEND_VM_COMMAND,QemuMainFrame::OnSendCommandToVM)
64 EVT_MENU(QEMU_WINDOW_NEXT, QemuMainFrame::OnNextWindow)
65 EVT_MENU(QEMU_WINDOW_PREV, QemuMainFrame::OnPrevWindow)
66 EVT_MENU(QEMU_DOC, QemuMainFrame::OnOpenQemuDoc)
67 EVT_MENU(QEMU_ABOUT, QemuMainFrame::OnAbout)
69 EVT_NOTEBOOK_PAGE_CHANGED(QEMU_VM_NOTEBOOK,QemuMainFrame::OnNotebookPageChanged)
70 EVT_MENU(QEMU_VM_NOTEBOOK_CONTEXT_CLOSE,QemuMainFrame::OnNotebookPageClosed)
71 EVT_MENU(ID_STATUSBAR_CDROM_CONNECT,QemuMainFrame::OnConnectCdRom)
72 END_EVENT_TABLE()
74 QemuMainFrame::QemuMainFrame(const wxString& title)
75 :wxFrame(NULL, wxID_ANY, title)
77 this->toolbarStyle = 0;
78 SetIcon(wxICON(sample));
80 #if wxUSE_MENUS
81 this->menubar = new QemuUIMenuBar();
82 SetMenuBar(this->menubar);
83 this->filehistory = new wxFileHistory(5);
84 this->filehistory->UseMenu(menubar->GetFileMenu());
85 #endif
87 #if wxUSE_TOOLBAR
88 this->toolbar = new QemuUIToolBar(this);
89 SetToolBar(this->toolbar);
90 #endif
92 this->mainwindow = new wxScrolledWindow(this);
93 mainwindow->SetScrollRate(10,10);
94 mainwindow->SetScrollbars(20, 20, 50, 50);
96 #if wxUSE_STATUSBAR
97 this->statusbar = new QemuUIStatusBar(this);
98 SetStatusBar(this->statusbar);
99 #endif
101 this->notebook = new QemuUINotebook(mainwindow);
102 this->CreateHomepage();
103 this->DoLayout();
106 void QemuMainFrame::DoLayout(){
107 wxBoxSizer *notebookSizer = new wxBoxSizer(wxHORIZONTAL );
108 notebookSizer->Add(notebook,1,wxEXPAND,0);
109 mainwindow->SetAutoLayout(true);
110 mainwindow->SetSizer(notebookSizer);
111 notebookSizer->Fit(mainwindow);
112 notebookSizer->SetSizeHints(mainwindow);
113 notebookSizer->Layout();
115 wxBoxSizer *frameSizer = new wxBoxSizer(wxVERTICAL);
116 frameSizer->Add(mainwindow,1,wxEXPAND,0);
117 frameSizer->Fit(this);
118 frameSizer->SetSizeHints(this);
120 SetAutoLayout(true);
121 SetSizer(frameSizer);
122 Layout();
123 SetSize(800,700);
124 Centre();
127 void QemuMainFrame::CreateHomepage(){
128 notebook->CreateHomepage();
129 menubar->PrependWindowMenuEntry(_("Homepage"));
130 toolbar->Disable();
131 statusbar->Disable();
134 void QemuMainFrame::OnQuitCommandEvent(wxCommandEvent& WXUNUSED(event)){
135 Close();
138 void QemuMainFrame::OnQuit(wxCloseEvent& event)
140 #if wxUSE_MEMORY_TRACING
141 wxDebugContext::SetFile(wxT("log.txt"));
142 wxDebugContext::Dump();
143 wxDebugContext::PrintStatistics();
144 #endif
145 for(int i = 0; i < vms.GetCount(); i++){
146 if(vms.Item(i)->IsRunning()){
147 if(wxMessageBox(
148 _("Some virtual machines are still running, "
149 "are you sure you wan't to close QEMU?"),
150 _("Warning"),
151 wxICON_WARNING | wxYES_NO,
152 this
153 ) == wxNO){
154 event.Veto();
155 return;
160 Destroy();
163 void QemuMainFrame::OnOpenQemuDoc(wxCommandEvent& WXUNUSED(event))
165 if(!wxLaunchDefaultBrowser(QEMU_GUI_DOC)){
166 wxLogError(_("Could not open qemu documentation."));
170 void QemuMainFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
174 wxTextCtrl* contentText = new wxTextCtrl;
175 contentText->Create( mainwindow, wxID_ANY, wxT("TEST TEST http://www.wxwidgets.org/"), wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_AUTO_URL|wxTE_CENTRE|wxTE_WORDWRAP|wxTE_READONLY);
178 wxString msg;
179 msg << _("QEMU GUI version");
180 msg << wxT(" "QEMU_GUI_VERSION"\n");
181 msg << QEMU_GUI_BUILD_INFO;
182 msg << _("\n\nThis is free software licensed under the GNU GPL.\n");
183 msg << _("(c) 2006 Marc Tanner\n");
184 msg << _("<"QEMU_GUI_MAIL">");
186 wxMessageBox(msg, _("About QEMU GUI"), wxOK | wxICON_INFORMATION, this);
190 void QemuMainFrame::OnToggleStatusBar(wxCommandEvent& event)
192 if(event.IsChecked())
193 statusbar->Show();
194 else
195 statusbar->Hide();
197 PositionStatusBar();
200 void QemuMainFrame::OnToggleToolBar(wxCommandEvent& event){
201 if(event.IsChecked() && !this->toolbar){
202 this->toolbar = new QemuUIToolBar(this);
203 SetToolBar(this->toolbar);
204 if(this->toolbarStyle != 0){
205 toolbar->SetWindowStyle(toolbarStyle);
206 toolbar->Layout();
208 } else {
209 this->toolbarStyle = toolbar->GetWindowStyle();
210 delete this->toolbar;
211 this->toolbar = NULL;
212 SetToolBar(NULL);
214 menubar->EnableToolbar(event.IsChecked());
217 void QemuMainFrame::OnToolBarSettingChange(wxCommandEvent& event){
218 long style = wxTB_HORIZONTAL | wxNO_BORDER | wxTB_FLAT;
219 switch(event.GetId()){
220 case QEMU_TOOLBAR_TEXT:
221 style |= wxTB_TEXT | wxTB_NOICONS;
222 break;
223 case QEMU_TOOLBAR_ICONS:
224 break;
225 case QEMU_TOOLBAR_BOTH:
226 style |= wxTB_TEXT;
227 break;
230 toolbar->SetWindowStyle(style);
231 toolbar->Layout();
234 void QemuMainFrame::OnFullScreen(wxCommandEvent &WXUNUSED(event)){
235 ShowFullScreen(!IsFullScreen());
238 void QemuMainFrame::OnShowHomepage(wxCommandEvent &WXUNUSED(event)){
239 ShowHomepage();
242 void QemuMainFrame::ShowHomepage(){
243 if(notebook->HasHomepage()){
244 const int pos = notebook->ShowHomepage();
245 menubar->CheckWindowMenuEntry(pos);
246 } else {
247 CreateHomepage();
250 toolbar->Disable();
251 statusbar->Disable();
254 void QemuMainFrame::OnChangeWindow(wxCommandEvent& event){
255 notebook->SetSelection(menubar->GetCheckedWindowMenuEntry());
258 void QemuMainFrame::OnNextWindow(wxCommandEvent& WXUNUSED(event)){
259 notebook->AdvanceSelection();
262 void QemuMainFrame::OnPrevWindow(wxCommandEvent& WXUNUSED(event)){
263 notebook->AdvanceSelection(false);
266 void QemuMainFrame::OnNewVM(wxCommandEvent& WXUNUSED(event)){
267 QemuUINewVMWizard *wizard = new QemuUINewVMWizard(this);
268 QemuVM *vm = wizard->RunIt();
269 wizard->Destroy();
270 if(vm){
271 OpenVM(vm);
275 void QemuMainFrame::OnOpenVM(wxCommandEvent& WXUNUSED(event)){
276 wxFileDialog *dialog = new wxFileDialog(
277 this,
278 _("Select a VM configuration file to open"),
279 wxEmptyString,wxEmptyString,
280 _("VM configuration (*.qvmc)|*.qvmc")
283 dialog->SetDirectory(wxGetHomeDir());
284 dialog->CentreOnParent();
286 if(dialog->ShowModal() == wxID_OK){
287 OpenVM(dialog->GetPath());
290 dialog->Destroy();
293 void QemuMainFrame::OnReOpenVM(wxCommandEvent& event){
294 OpenVM(filehistory->GetHistoryFile(event.GetId() - wxID_FILE1));
297 void QemuMainFrame::OpenVM(const wxString& config){
298 QemuVM *vm = new QemuVM(config);
299 if(!OpenVM(vm)){
300 delete vm;
304 bool QemuMainFrame::OpenVM(QemuVM *vm){
305 const wxString config = vm->GetConfigFile();
306 for(int i = 0; i < vms.GetCount(); i++){
307 if(vms.Item(i)->GetConfigFile().Cmp(config) == 0){
308 wxMessageBox(
309 _("This virutal machine is already open."),
310 _("Error"),
311 wxICON_ERROR | wxOK,
312 this
314 return false;
318 filehistory->AddFileToHistory(config);
319 menubar->UpdateFileHistory(filehistory->GetCount());
320 // it is important that the window menu entry gets created
321 // before a new notebook page is added, because within the
322 // OnNotebookChange event handler the new item will be checked.
323 menubar->AppendWindowMenuEntry(vm->GetTitle());
324 notebook->AddVM(vm);
326 // add to the array of open vm's
327 vms.Add(vm);
329 return true;
332 QemuUINotebookPage* QemuMainFrame::GetCurrentVMTab(){
333 return notebook->GetCurrentVMTab();
336 QemuVM* QemuMainFrame::GetCurrentVM(){
337 return notebook->GetCurrentVM();
340 void QemuMainFrame::OnVMSettings(wxCommandEvent& WXUNUSED(event)){
341 QemuVM *vm = GetCurrentVM();
342 if(!vm)
343 return;
345 QemuVMConfigDialog *dialog = new QemuVMConfigDialog(this,vm);
346 if(dialog->ShowModal() == wxID_OK){
347 dialog->Save();
351 void QemuMainFrame::OnVMSendCtrlAltDel(wxCommandEvent& WXUNUSED(event)){
352 QemuVM *vm = GetCurrentVM();
353 if(!vm)
354 return;
355 vm->SendKey(wxT("ctrl-alt-delete"));
358 void QemuMainFrame::OnPowerOnVM(wxCommandEvent& WXUNUSED(event)){
359 QemuUINotebookPage *tab = GetCurrentVMTab();
360 QemuVM *vm = tab->GetVM();
361 if(tab && vm){
362 bool paused = vm->IsPaused();
363 if(vm->PowerOn() < 0){
364 wxMessageBox(_("Could not start qemu"),_("Error"),
365 wxICON_ERROR | wxOK, this);
366 return;
369 #if 1
370 if(!paused){
371 // give qemu some time to set up it's vnc server
372 //wxMilliSleep(1000);
373 if(tab->GetScreen()->Connect(vm->GetCurrentVNCDisplay())){
374 vm->AddEventHandler(tab->GetScreen());
375 tab->ShowScreen();
376 } else {
377 wxLogError(_("Could not connect to vnc display."));
380 #endif
381 UpdateState();
386 void QemuMainFrame::OnPauseVM(wxCommandEvent& WXUNUSED(event)){
387 QemuVM *vm = GetCurrentVM();
388 if(vm){
389 vm->Pause();
390 UpdateState();
394 void QemuMainFrame::OnPowerOffVM(wxCommandEvent& WXUNUSED(event)){
395 QemuVM *vm = GetCurrentVM();
396 if(vm){
397 vm->PowerOff();
398 UpdateState();
402 void QemuMainFrame::OnResetVM(wxCommandEvent& WXUNUSED(event)){
403 QemuVM *vm = GetCurrentVM();
404 if(vm){
405 vm->Reset();
409 void QemuMainFrame::OnKillVM(wxCommandEvent& WXUNUSED(event)){
410 QemuVM *vm = GetCurrentVM();
411 if(vm){
412 if(wxMessageBox(_("Do you really want to kill this VM?"),
413 _("Warning"),wxICON_QUESTION | wxYES_NO, this) == wxYES){
414 vm->Kill();
419 void QemuMainFrame::OnSnapshot(wxCommandEvent& WXUNUSED(event)){
420 QemuVM *vm = GetCurrentVM();
421 if(vm){
422 vm->Snapshot();
423 UpdateState();
427 void QemuMainFrame::OnRevertSnapshot(wxCommandEvent& WXUNUSED(event)){
428 QemuVM *vm = GetCurrentVM();
429 if(vm){
430 vm->Revert();
431 UpdateState();
435 void QemuMainFrame::OnToggleDisplay(wxCommandEvent& event){
436 QemuUINotebookPage* tab = notebook->GetCurrentVMTab();
437 switch(event.GetId()){
438 case QEMU_TOOLBAR_DISPLAY_INFO:
439 toolbar->ShowInfo();
440 tab->ShowInfo();
441 break;
442 case QEMU_TOOLBAR_DISPLAY_SCREEN:
443 toolbar->ShowScreen();
444 tab->ShowScreen();
445 break;
446 case QEMU_TOOLBAR_DISPLAY_CONSOLE:
447 toolbar->ShowConsole();
448 tab->ShowConsole();
449 break;
453 void QemuMainFrame::OnSendCommandToVM(wxCommandEvent& WXUNUSED(event)){
454 QemuVM *vm = GetCurrentVM();
455 if(!vm) return;
456 wxTextEntryDialog dialog(this,
457 _T("Please enter a command which will be send to the qemu monitor."),
458 _T("Please enter a command"),
459 _T(""),
460 wxOK | wxCANCEL
463 if (dialog.ShowModal() == wxID_OK){
464 wxMessageBox(vm->SendCommand(dialog.GetValue(),true), wxT("Response"), wxOK | wxICON_INFORMATION, this);
465 //wxLogError(vm->SendCommand(dialog.GetValue()));
469 void QemuMainFrame::OnNotebookPageChanged(wxNotebookEvent& event){
470 const size_t pos = event.GetSelection();
471 menubar->CheckWindowMenuEntry(pos);
472 UpdateState();
475 void QemuMainFrame::CloseNotebookPage(const int pos){
476 QemuVM *vm = GetCurrentVM();
478 if(!vm){
479 notebook->CloseHomepage();
480 menubar->RemoveWindowMenuEntry(pos);
481 return;
484 if(vm->IsRunning() &&
485 wxMessageBox(_("Do you really want to close this VM?"),_("Question"),
486 wxICON_QUESTION | wxYES_NO, this) != wxYES){
487 return;
490 wxNotebookPage *page = notebook->GetCurrentPage();
491 if(page){
492 vm->PowerOff();
493 vms.Remove(vm);
494 delete vm;
495 menubar->RemoveWindowMenuEntry(pos);
496 notebook->RemovePage(pos);
497 delete page;
498 UpdateState();
502 void QemuMainFrame::OnNotebookPageClosed(wxCommandEvent& WXUNUSED(event)){
503 CloseNotebookPage(notebook->GetSelection());
506 void QemuMainFrame::UpdateState(){
507 QemuUINotebookPage *tab = GetCurrentVMTab();
509 if(!tab){
510 menubar->Disable();
511 toolbar->Disable();
512 statusbar->Disable();
513 return;
516 QemuVM *vm = tab->GetVM();
517 menubar->Settings(!vm->IsRunning());
518 menubar->PowerOn(!vm->IsRunning());
519 menubar->PowerOff(vm->IsRunning() || vm->IsPaused());
520 menubar->Pause(vm->IsRunning());
521 menubar->Reset(vm->IsRunning() || vm->IsPaused());
522 toolbar->PowerOn(!vm->IsRunning());
523 toolbar->PowerOff(vm->IsRunning() || vm->IsPaused());
524 toolbar->Pause(vm->IsRunning());
525 toolbar->Reset(vm->IsRunning() || vm->IsPaused());
526 toolbar->Kill(vm->IsRunning());
527 toolbar->Snapshot(vm->IsRunning());
528 toolbar->RevertSnapshot(vm->GetPID() > 0 && vm->HasSnapshot());
529 toolbar->EnableDisplayArea();
530 toolbar->EnableDisplayScreen(!vm->IsPoweredOff());
531 toolbar->SendVMCommand(!vm->IsPoweredOff());
533 if(tab->IsConsoleActive())
534 toolbar->ShowConsole();
535 else if(tab->IsScreenActive())
536 toolbar->ShowScreen();
537 else
538 toolbar->ShowInfo();
540 tab->GetConsole()->SetState(!vm->IsPoweredOff());
542 if(vm->IsRunning())
543 statusbar->Enable();
544 else
545 statusbar->Disable();
548 void QemuMainFrame::OnConnectCdRom(wxCommandEvent& event){
549 GetCurrentVM()->ConnectCdRom(event.IsChecked());
552 void QemuMainFrame::SaveFileHistory(wxConfigBase *config){
553 //config->SetPath(wxT("/filehistory"));
554 filehistory->Save(*config);
555 //config->SetPath(wxT("/"));
558 void QemuMainFrame::LoadFileHistory(wxConfigBase *config){
559 //config->SetPath(wxT("/filehistory"));
560 filehistory->Load(*config);
561 menubar->UpdateFileHistory(filehistory->GetCount());
562 //config->SetPath(wxT("/"));