MainFrame.cpp

Go to the documentation of this file.
00001 // -*- c-basic-offset: 4 -*-
00002 
00027 #include <config.h>
00028 #include <exiv2/exif.hpp>
00029 #include <exiv2/image.hpp>
00030 
00031 #include <wx/dir.h>
00032 #include <wx/stdpaths.h>
00033 #include "panoinc_WX.h"
00034 #include "panoinc.h"
00035 
00036 #include "base_wx/platform.h"
00037 #include "base_wx/wxPlatform.h"
00038 
00039 #include "vigra/imageinfo.hxx"
00040 #include "vigra_ext/Correlation.h"
00041 
00042 #include "hugin/config_defaults.h"
00043 #include "hugin/PreferencesDialog.h"
00044 #include "hugin/MainFrame.h"
00045 #include "base_wx/wxPanoCommand.h"
00046 #include "base_wx/CommandHistory.h"
00047 #include "hugin/PanoPanel.h"
00048 #include "hugin/ImagesPanel.h"
00049 #include "hugin/MaskEditorPanel.h"
00050 #include "hugin/OptimizePanel.h"
00051 #include "hugin/OptimizePhotometricPanel.h"
00052 #include "hugin/PreviewFrame.h"
00053 #include "hugin/GLPreviewFrame.h"
00054 #include "hugin/huginApp.h"
00055 #include "hugin/CPEditorPanel.h"
00056 #include "hugin/CPListFrame.h"
00057 #include "hugin/LocalizedFileTipProvider.h"
00058 #include "algorithms/control_points/CleanCP.h"
00059 #include "hugin/PanoOperation.h"
00060 #include "hugin/PapywizardImport.h"
00061 
00062 #include "base_wx/MyProgressDialog.h"
00063 #include "base_wx/RunStitchPanel.h"
00064 #include "base_wx/wxImageCache.h"
00065 #include "base_wx/PTWXDlg.h"
00066 #include "base_wx/MyExternalCmdExecDialog.h"
00067 #include "base_wx/AssistantExecutor.h"
00068 #include "algorithms/optimizer/ImageGraph.h"
00069 
00070 #include "base_wx/huginConfig.h"
00071 #include "hugin/AboutDialog.h"
00072 
00073 #if HUGIN_HSI
00074 #include "PluginItems.h"
00075 #endif
00076 
00077 #ifdef __MINGW32__
00078 // fixes for mingw compilation...
00079 #undef FindWindow
00080 #endif
00081 
00086 class HuginSplashScreen : public wxFrame
00087 {
00088 public:
00089     HuginSplashScreen() {};
00090     HuginSplashScreen(wxWindow* parent, wxBitmap bitmap) : 
00091         wxFrame(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxFRAME_TOOL_WINDOW | wxFRAME_NO_TASKBAR | wxSTAY_ON_TOP)
00092     {
00093         SetExtraStyle(GetExtraStyle() | wxWS_EX_TRANSIENT);
00094         wxSizer* topSizer=new wxBoxSizer(wxVERTICAL);
00095         wxStaticBitmap* staticBitmap=new wxStaticBitmap(this,wxID_ANY,bitmap);
00096         topSizer->Add(staticBitmap,1,wxEXPAND);
00097         SetSizerAndFit(topSizer);
00098         SetClientSize(bitmap.GetWidth(), bitmap.GetHeight());
00099         CenterOnScreen();
00100         Show(true);
00101         SetFocus();
00102 #if defined(__WXMSW__) || defined(__WXMAC__)
00103         Update();
00104 #elif defined(__WXGTK20__)
00105         //do nothing
00106 #else
00107         wxYieldIfNeeded();
00108 #endif
00109     };
00110     DECLARE_DYNAMIC_CLASS(HuginSplashScreen)
00111     DECLARE_EVENT_TABLE()
00112 };
00113 
00114 IMPLEMENT_DYNAMIC_CLASS(HuginSplashScreen, wxFrame)
00115 BEGIN_EVENT_TABLE(HuginSplashScreen, wxFrame)
00116 END_EVENT_TABLE()
00117 
00119 bool PanoDropTarget::OnDropFiles(wxCoord x, wxCoord y, const wxArrayString& filenames)
00120 {
00121     DEBUG_TRACE("OnDropFiles");
00122     MainFrame * mf = MainFrame::Get();
00123     if (!mf) return false;
00124 
00125     if (!m_imageOnly && filenames.GetCount() == 1) {
00126         wxFileName file(filenames[0]);
00127         if (file.GetExt().CmpNoCase(wxT("pto")) == 0 ||
00128             file.GetExt().CmpNoCase(wxT("ptp")) == 0 ||
00129             file.GetExt().CmpNoCase(wxT("pts")) == 0 )
00130         {
00131             // load project
00132             if (mf->CloseProject(true)) {
00133                 mf->LoadProjectFile(file.GetFullPath());
00134                 // remove old images from cache
00135                 ImageCache::getInstance().flush();
00136             }
00137             return true;
00138         }
00139     }
00140 
00141     // try to add as images
00142     std::vector<std::string> filesv;
00143     wxArrayString invalidFiles;
00144     for (unsigned int i=0; i< filenames.GetCount(); i++) {
00145         wxFileName file(filenames[i]);
00146 
00147         if (file.GetExt().CmpNoCase(wxT("jpg")) == 0 ||
00148             file.GetExt().CmpNoCase(wxT("jpeg")) == 0 ||
00149             file.GetExt().CmpNoCase(wxT("tif")) == 0 ||
00150             file.GetExt().CmpNoCase(wxT("tiff")) == 0 ||
00151             file.GetExt().CmpNoCase(wxT("png")) == 0 ||
00152             file.GetExt().CmpNoCase(wxT("bmp")) == 0 ||
00153             file.GetExt().CmpNoCase(wxT("gif")) == 0 ||
00154             file.GetExt().CmpNoCase(wxT("pnm")) == 0 ||
00155             file.GetExt().CmpNoCase(wxT("sun")) == 0 ||
00156             file.GetExt().CmpNoCase(wxT("hdr")) == 0 ||
00157             file.GetExt().CmpNoCase(wxT("viff")) == 0 )
00158         {
00159             if(containsInvalidCharacters(filenames[i]))
00160             {
00161                 invalidFiles.Add(file.GetFullPath());
00162             }
00163             else
00164             {
00165                 filesv.push_back((const char *)filenames[i].mb_str(HUGIN_CONV_FILENAME));
00166             };
00167         }
00168     }
00169     // we got some images to add.
00170     if (filesv.size() > 0)
00171     {
00172         // use a Command to ensure proper undo and updating of GUI parts
00173         wxBusyCursor();
00174         if(pano.getNrOfCtrlPoints()>0)
00175         {
00176             PanoCommand::GlobalCmdHist::getInstance().addCommand(new PanoCommand::wxAddImagesCmd(pano, filesv));
00177         }
00178         else
00179         {
00180             std::vector<PanoCommand::PanoCommand*> cmds;
00181             cmds.push_back(new PanoCommand::wxAddImagesCmd(pano, filesv));
00182             cmds.push_back(new PanoCommand::DistributeImagesCmd(pano));
00183             cmds.push_back(new PanoCommand::CenterPanoCmd(pano));
00184             PanoCommand::GlobalCmdHist::getInstance().addCommand(new PanoCommand::CombinedPanoCommand(pano, cmds));
00185         };
00186 
00187     }
00188     if(invalidFiles.size()>0)
00189     {
00190         ShowFilenameWarning(mf, invalidFiles);
00191     }
00192 
00193     return true;
00194 }
00195 
00196 
00197 
00198 // event table. this frame will recieve mostly global commands.
00199 BEGIN_EVENT_TABLE(MainFrame, wxFrame)
00200     EVT_MENU(XRCID("action_new_project"),  MainFrame::OnNewProject)
00201     EVT_MENU(XRCID("action_load_project"),  MainFrame::OnLoadProject)
00202     EVT_MENU(XRCID("action_save_project"),  MainFrame::OnSaveProject)
00203     EVT_MENU(XRCID("action_save_as_project"),  MainFrame::OnSaveProjectAs)
00204     EVT_MENU(XRCID("action_save_as_ptstitcher"),  MainFrame::OnSavePTStitcherAs)
00205     EVT_MENU(XRCID("action_open_batch_processor"),  MainFrame::OnOpenPTBatcher)
00206     EVT_MENU(XRCID("action_import_project"), MainFrame::OnMergeProject)
00207     EVT_MENU(XRCID("action_import_papywizard"), MainFrame::OnReadPapywizard)
00208     EVT_MENU(XRCID("action_apply_template"),  MainFrame::OnApplyTemplate)
00209     EVT_MENU(XRCID("action_exit_hugin"),  MainFrame::OnUserQuit)
00210     EVT_MENU_RANGE(wxID_FILE1, wxID_FILE9, MainFrame::OnMRUFiles)
00211     EVT_MENU(XRCID("action_show_about"),  MainFrame::OnAbout)
00212     EVT_MENU(XRCID("action_show_help"),  MainFrame::OnHelp)
00213     EVT_MENU(XRCID("action_show_tip"),  MainFrame::OnTipOfDay)
00214     EVT_MENU(XRCID("action_show_shortcuts"),  MainFrame::OnKeyboardHelp)
00215     EVT_MENU(XRCID("action_show_faq"),  MainFrame::OnFAQ)
00216     EVT_MENU(XRCID("action_show_donate"),  MainFrame::OnShowDonate)
00217     EVT_MENU(XRCID("action_show_prefs"), MainFrame::OnShowPrefs)
00218     EVT_MENU(XRCID("action_assistant"), MainFrame::OnRunAssistant)
00219     EVT_MENU(XRCID("action_batch_assistant"), MainFrame::OnSendToAssistantQueue)
00220     EVT_MENU(XRCID("action_gui_simple"), MainFrame::OnSetGuiSimple)
00221     EVT_MENU(XRCID("action_gui_advanced"), MainFrame::OnSetGuiAdvanced)
00222     EVT_MENU(XRCID("action_gui_expert"), MainFrame::OnSetGuiExpert)
00223 #ifdef HUGIN_HSI
00224     EVT_MENU(XRCID("action_python_script"), MainFrame::OnPythonScript)
00225 #endif
00226     EVT_MENU(XRCID("ID_EDITUNDO"), MainFrame::OnUndo)
00227     EVT_MENU(XRCID("ID_EDITREDO"), MainFrame::OnRedo)
00228     EVT_MENU(XRCID("ID_SHOW_FULL_SCREEN"), MainFrame::OnFullScreen)
00229     EVT_MENU(XRCID("ID_SHOW_PREVIEW_FRAME"), MainFrame::OnTogglePreviewFrame)
00230     EVT_MENU(XRCID("ID_SHOW_GL_PREVIEW_FRAME"), MainFrame::OnToggleGLPreviewFrame)
00231     EVT_BUTTON(XRCID("ID_SHOW_PREVIEW_FRAME"),MainFrame::OnTogglePreviewFrame)
00232     EVT_BUTTON(XRCID("ID_SHOW_GL_PREVIEW_FRAME"), MainFrame::OnToggleGLPreviewFrame)
00233 
00234     EVT_MENU(XRCID("action_optimize"),  MainFrame::OnOptimize)
00235     EVT_MENU(XRCID("action_optimize_only_active"), MainFrame::OnOnlyActiveImages)
00236     EVT_BUTTON(XRCID("action_optimize"),  MainFrame::OnOptimize)
00237     EVT_MENU(XRCID("action_finetune_all_cp"), MainFrame::OnFineTuneAll)
00238 //    EVT_BUTTON(XRCID("action_finetune_all_cp"), MainFrame::OnFineTuneAll)
00239     EVT_MENU(XRCID("action_remove_cp_in_masks"), MainFrame::OnRemoveCPinMasks)
00240 
00241     EVT_MENU(XRCID("ID_CP_TABLE"), MainFrame::OnShowCPFrame)
00242     EVT_BUTTON(XRCID("ID_CP_TABLE"),MainFrame::OnShowCPFrame)
00243 
00244     EVT_MENU(XRCID("ID_SHOW_PANEL_IMAGES"), MainFrame::OnShowPanel)
00245     EVT_MENU(XRCID("ID_SHOW_PANEL_MASK"), MainFrame::OnShowPanel)
00246     EVT_MENU(XRCID("ID_SHOW_PANEL_CP_EDITOR"), MainFrame::OnShowPanel)
00247     EVT_MENU(XRCID("ID_SHOW_PANEL_OPTIMIZER"), MainFrame::OnShowPanel)
00248     EVT_MENU(XRCID("ID_SHOW_PANEL_OPTIMIZER_PHOTOMETRIC"), MainFrame::OnShowPanel)
00249     EVT_MENU(XRCID("ID_SHOW_PANEL_PANORAMA"), MainFrame::OnShowPanel)
00250     EVT_MENU(XRCID("action_stitch"), MainFrame::OnDoStitch)
00251     EVT_MENU(XRCID("action_stitch_userdefined"), MainFrame::OnUserDefinedStitch)
00252     EVT_MENU(XRCID("action_add_images"),  MainFrame::OnAddImages)
00253     EVT_BUTTON(XRCID("action_add_images"),  MainFrame::OnAddImages)
00254     EVT_MENU(XRCID("action_add_time_images"),  MainFrame::OnAddTimeImages)
00255     EVT_BUTTON(XRCID("action_add_time_images"),  MainFrame::OnAddTimeImages)
00256     EVT_CLOSE(  MainFrame::OnExit)
00257     EVT_SIZE(MainFrame::OnSize)
00258 END_EVENT_TABLE()
00259 
00260 // change this variable definition
00261 //wxTextCtrl *itemProjTextMemo;
00262 // image preview
00263 //wxBitmap *p_img = (wxBitmap *) NULL;
00264 //WX_DEFINE_ARRAY()
00265 
00266 MainFrame::MainFrame(wxWindow* parent, HuginBase::Panorama & pano)
00267     : cp_frame(0), pano(pano)
00268 {
00269     preview_frame = 0;
00270     svmModel=NULL;
00271 
00272     bool disableOpenGL=false;
00273 #if wxCHECK_VERSION(2,9,4)
00274     if(wxGetKeyState(WXK_COMMAND))
00275 #else
00276     if(wxGetKeyState(WXK_CONTROL))
00277 #endif
00278     {
00279         wxDialog dlg;
00280         wxXmlResource::Get()->LoadDialog(&dlg, NULL, wxT("disable_opengl_dlg"));
00281         long noOpenGL=wxConfigBase::Get()->Read(wxT("DisableOpenGL"), 0l);
00282         if(noOpenGL==1)
00283         {
00284             XRCCTRL(dlg, "disable_dont_ask_checkbox", wxCheckBox)->SetValue(true);
00285         };
00286         if(dlg.ShowModal()==wxID_OK)
00287         {
00288             if(XRCCTRL(dlg, "disable_dont_ask_checkbox", wxCheckBox)->IsChecked())
00289             {
00290                 wxConfigBase::Get()->Write(wxT("DisableOpenGL"), 1l);
00291             }
00292             else
00293             {
00294                 wxConfigBase::Get()->Write(wxT("DisableOpenGL"), 0l);
00295             };
00296             disableOpenGL=true;
00297         }
00298         else
00299         {
00300             wxConfigBase::Get()->Write(wxT("DisableOpenGL"), 0l);
00301         };
00302     }
00303     else
00304     {
00305         long noOpenGL=wxConfigBase::Get()->Read(wxT("DisableOpenGL"), 0l);
00306         disableOpenGL=(noOpenGL==1);
00307     };
00308 
00309     wxBitmap bitmap;
00310     HuginSplashScreen* splash = 0;
00311     wxYield();
00312 
00313     if (bitmap.LoadFile(huginApp::Get()->GetXRCPath() + wxT("data/splash.png"), wxBITMAP_TYPE_PNG))
00314     {
00315         // embed package version into string.
00316         {
00317             wxMemoryDC dc;
00318             dc.SelectObject(bitmap);
00319 #ifdef __WXMAC__
00320             wxFont font(9, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
00321 #else
00322             wxFont font(8, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
00323 #endif
00324             dc.SetFont(font);
00325             dc.SetTextForeground(*wxBLACK);
00326             dc.SetTextBackground(*wxWHITE);
00327             int tw, th;
00328             wxString version;
00329             version.Printf(_("Version %s"), wxString(hugin_utils::GetHuginVersion().c_str(), wxConvLocal).c_str());
00330             dc.GetTextExtent(version, &tw, &th);
00331             // place text on bitmap.
00332             dc.DrawText(version, bitmap.GetWidth() - tw - 3, bitmap.GetHeight() - th - 3);
00333             dc.SelectObject(wxNullBitmap);
00334         }
00335 
00336         splash = new HuginSplashScreen(NULL, bitmap);
00337     } else {
00338         wxLogFatalError(_("Fatal installation error\nThe file data/splash.png was not found at:") + huginApp::Get()->GetXRCPath());
00339         abort();
00340     }
00341     //splash->Refresh();
00342     wxYield();
00343 
00344     // save our pointer
00345     m_this = this;
00346 
00347     DEBUG_TRACE("");
00348     // load our children. some children might need special
00349     // initialization. this will be done later.
00350     wxXmlResource::Get()->LoadFrame(this, parent, wxT("main_frame"));
00351     DEBUG_TRACE("");
00352 
00353     // load our menu bar
00354 #ifdef __WXMAC__
00355     wxApp::s_macAboutMenuItemId = XRCID("action_show_about");
00356     wxApp::s_macPreferencesMenuItemId = XRCID("action_show_prefs");
00357     wxApp::s_macExitMenuItemId = XRCID("action_exit_hugin");
00358     wxApp::s_macHelpMenuTitleName = _("&Help");
00359 #endif
00360     wxMenuBar* mainMenu=wxXmlResource::Get()->LoadMenuBar(this, wxT("main_menubar"));
00361     m_menu_file_simple=wxXmlResource::Get()->LoadMenu(wxT("file_menu_simple"));
00362     m_menu_file_advanced=wxXmlResource::Get()->LoadMenu(wxT("file_menu_advanced"));
00363     mainMenu->Insert(0, m_menu_file_simple, _("&File"));
00364     SetMenuBar(mainMenu);
00365     SetOptimizeOnlyActiveImages(m_optOnlyActiveImages);
00366 
00367 #ifdef HUGIN_HSI
00368     wxMenuBar* menubar=GetMenuBar();
00369     // the plugin menu will be generated dynamically
00370     wxMenu *pluginMenu=new wxMenu();
00371     // search for all .py files in plugins directory
00372     wxDir dir(GetDataPath()+wxT("plugins"));
00373     if (dir.IsOpened())
00374     {
00375         wxString filename;
00376         bool cont = dir.GetFirst(&filename, wxT("*.py"), wxDIR_FILES | wxDIR_HIDDEN);
00377         PluginItems items;
00378         while (cont)
00379         {
00380             wxFileName file(dir.GetName(), filename);
00381             file.MakeAbsolute();
00382             PluginItem item(file);
00383             if (item.IsAPIValid())
00384             {
00385                 items.push_back(item);
00386             };
00387             cont = dir.GetNext(&filename);
00388         };
00389         items.sort(comparePluginItem);
00390 
00391         int pluginID = wxID_HIGHEST + 2000;
00392         for (PluginItems::const_iterator it = items.begin(); it != items.end(); ++it)
00393         {
00394             PluginItem item = *it;
00395             int categoryID = pluginMenu->FindItem(item.GetCategory());
00396             wxMenu* categoryMenu;
00397             if (categoryID == wxNOT_FOUND)
00398             {
00399                 categoryMenu = new wxMenu();
00400                 pluginMenu->AppendSubMenu(categoryMenu, item.GetCategory());
00401             }
00402             else
00403             {
00404                 categoryMenu = pluginMenu->FindItem(categoryID)->GetSubMenu();
00405             };
00406             categoryMenu->Append(pluginID, item.GetName(), item.GetDescription());
00407             m_plugins[pluginID] = item.GetFilename();
00408             Connect(pluginID, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::OnPlugin));
00409             pluginID++;
00410         };
00411         // show the new menu
00412         if (pluginMenu->GetMenuItemCount() > 0)
00413         {
00414             menubar->Insert(menubar->GetMenuCount() - 2, pluginMenu, _("&Actions"));
00415         };
00416     };
00417 #else
00418     GetMenuBar()->Enable(XRCID("action_python_script"), false);
00419 #endif
00420 
00421     // create tool bar
00422     SetToolBar(wxXmlResource::Get()->LoadToolBar(this, wxT("main_toolbar")));
00423 
00424     // Disable tools by default
00425     enableTools(false);
00426 
00427     // put an "unknown" object in an xrc file and
00428     // take as wxObject (second argument) the return value of wxXmlResource::Get
00429     // finish the images_panel
00430     DEBUG_TRACE("");
00431 
00432     // image_panel
00433     images_panel = XRCCTRL(*this, "images_panel_unknown", ImagesPanel);
00434     assert(images_panel);
00435     images_panel->Init(&pano);
00436     DEBUG_TRACE("");
00437 
00438     m_notebook = XRCCTRL((*this), "controls_notebook", wxNotebook);
00439 //    m_notebook = ((wxNotebook*) ((*this).FindWindow(XRCID("controls_notebook"))));
00440 //    m_notebook = ((wxNotebook*) (FindWindow(XRCID("controls_notebook"))));
00441     DEBUG_ASSERT(m_notebook);
00442 
00443     // the mask panel
00444     mask_panel = XRCCTRL(*this, "mask_panel_unknown", MaskEditorPanel);
00445     assert(mask_panel);
00446     mask_panel->Init(&pano);
00447 
00448     // the pano_panel
00449     DEBUG_TRACE("");
00450     pano_panel = XRCCTRL(*this, "panorama_panel_unknown", PanoPanel);
00451     assert(pano_panel);
00452     pano_panel->Init(&pano);
00453     pano_panel->panoramaChanged (pano); // initialize from pano
00454 
00455     cpe = XRCCTRL(*this, "cp_editor_panel_unknown", CPEditorPanel);
00456     assert(cpe);
00457     cpe->Init(&pano);
00458 
00459     opt_panel = XRCCTRL(*this, "optimizer_panel_unknown", OptimizePanel);
00460     assert(opt_panel);
00461     opt_panel->Init(&pano);
00462     m_show_opt_panel=true;
00463 
00464     opt_photo_panel = XRCCTRL(*this, "optimizer_photometric_panel_unknown", OptimizePhotometricPanel);
00465     assert(opt_photo_panel);
00466     opt_photo_panel->Init(&pano);
00467     m_show_opt_photo_panel=true;
00468 
00469     // generate list of most recently uses files and add it to menu
00470     // needs to be initialized before the fast preview, there we call AddFilesToMenu()
00471     wxConfigBase * config=wxConfigBase::Get();
00472     m_mruFiles.Load(*config);
00473     m_mruFiles.UseMenu(m_menu_file_advanced->FindItem(XRCID("menu_mru"))->GetSubMenu());
00474 
00475     preview_frame = new PreviewFrame(this, pano);
00476     if(disableOpenGL)
00477     {
00478         gl_preview_frame=NULL;
00479         DisableOpenGLTools();
00480         m_mruFiles.AddFilesToMenu();
00481     }
00482     else
00483     {
00484         gl_preview_frame = new GLPreviewFrame(this, pano);
00485     };
00486 
00487     // set the minimize icon
00488 #ifdef __WXMSW__
00489     wxIcon myIcon(GetXRCPath() + wxT("data/hugin.ico"),wxBITMAP_TYPE_ICO);
00490 #else
00491     wxIcon myIcon(GetXRCPath() + wxT("data/hugin.png"),wxBITMAP_TYPE_PNG);
00492 #endif
00493     SetIcon(myIcon);
00494 
00495     // create a new drop handler. wxwindows deletes the automaticall
00496     SetDropTarget(new PanoDropTarget(pano));
00497     DEBUG_TRACE("");
00498 
00499     PanoOperation::GeneratePanoOperationVector();
00500 
00501     // create a status bar
00502     const int fields (2);
00503     CreateStatusBar(fields);
00504     int widths[fields] = {-1, 85};
00505     SetStatusWidths( fields, &widths[0]);
00506     SetStatusText(_("Started"), 0);
00507     wxYield();
00508     DEBUG_TRACE("");
00509 
00510     // observe the panorama
00511     pano.addObserver(this);
00512 
00513     // Set sizing characteristics
00514     //set minumum size
00515 #if defined __WXMAC__ || defined __WXMSW__
00516     // a minimum nice looking size; smaller than this would clutter the layout.
00517     SetSizeHints(900, 675);
00518 #else
00519     // For ASUS eeePc
00520     SetSizeHints(780, 455); //set minumum size
00521 #endif
00522 
00523     // set progress display for image cache.
00524     ImageCache::getInstance().setProgressDisplay(this);
00525 #if defined __WXMSW__
00526     unsigned long long mem = HUGIN_IMGCACHE_UPPERBOUND;
00527     unsigned long mem_low = wxConfigBase::Get()->Read(wxT("/ImageCache/UpperBound"), HUGIN_IMGCACHE_UPPERBOUND);
00528     unsigned long mem_high = wxConfigBase::Get()->Read(wxT("/ImageCache/UpperBoundHigh"), (long) 0);
00529     if (mem_high > 0) {
00530       mem = ((unsigned long long) mem_high << 32) + mem_low;
00531     }
00532     else {
00533       mem = mem_low;
00534     }
00535     ImageCache::getInstance().SetUpperLimit(mem);
00536 #else
00537     ImageCache::getInstance().SetUpperLimit(wxConfigBase::Get()->Read(wxT("/ImageCache/UpperBound"), HUGIN_IMGCACHE_UPPERBOUND));
00538 #endif
00539 
00540     if(splash) {
00541         splash->Close();
00542         delete splash;
00543     }
00544     wxYield();
00545 
00546     // disable automatic Layout() calls, to it by hand
00547     SetAutoLayout(false);
00548 
00549 
00550 #ifdef __WXMSW__
00551     // wxFrame does have a strange background color on Windows, copy color from a child widget
00552     this->SetBackgroundColour(images_panel->GetBackgroundColour());
00553 #endif
00554 
00555 // By using /SUBSYSTEM:CONSOLE /ENTRY:"WinMainCRTStartup" in the linker
00556 // options for the debug build, a console window will be used for stdout
00557 // and stderr. No need to redirect to a file. Better security since we can't
00558 // guarantee that c: exists and writing a file to the root directory is
00559 // never a good idea. release build still uses /SUBSYSTEM:WINDOWS
00560 
00561 #if 0
00562 #ifdef DEBUG
00563 #ifdef __WXMSW__
00564 
00565     freopen("c:\\hugin_stdout.txt", "w", stdout);    // redirect stdout to file
00566     freopen("c:\\hugin_stderr.txt", "w", stderr);    // redirect stderr to file
00567 #endif
00568 #endif
00569 #endif
00570     //reload gui level
00571     m_guiLevel=GUI_ADVANCED;
00572     long guiLevel=config->Read(wxT("/GuiLevel"),(long)0);
00573     guiLevel = std::max<long>(0, std::min<long>(2, guiLevel));
00574     if(guiLevel==GUI_SIMPLE && disableOpenGL)
00575     {
00576         guiLevel=GUI_ADVANCED;
00577     };
00578     SetGuiLevel((GuiLevel)guiLevel);
00579 
00580     DEBUG_TRACE("");
00581 #ifdef __WXGTK__
00582     // set explicit focus to assistant panel for better processing key presses
00583     images_panel->SetFocus();
00584 #endif
00585 }
00586 
00587 MainFrame::~MainFrame()
00588 {
00589     DEBUG_TRACE("dtor");
00590     if(m_guiLevel==GUI_SIMPLE)
00591     {
00592         delete m_menu_file_advanced;
00593     }
00594     else
00595     {
00596         delete m_menu_file_simple;
00597     };
00598     ImageCache::getInstance().setProgressDisplay(NULL);
00599         delete & ImageCache::getInstance();
00600     delete & PanoCommand::GlobalCmdHist::getInstance();
00601 //    delete cpe;
00602 //    delete images_panel;
00603     DEBUG_DEBUG("removing observer");
00604     pano.removeObserver(this);
00605 
00606     // get the global config object
00607     wxConfigBase* config = wxConfigBase::Get();
00608 
00609     StoreFramePosition(this, wxT("MainFrame"));
00610 
00611     //store most recently used files
00612     m_mruFiles.Save(*config);
00613     //store gui level
00614     config->Write(wxT("/GuiLevel"),(long)m_guiLevel);
00615     config->Flush();
00616     if(svmModel!=NULL)
00617     {
00618         celeste::destroySVMmodel(svmModel);
00619     };
00620     PanoOperation::CleanPanoOperationVector();
00621 
00622     DEBUG_TRACE("dtor end");
00623 }
00624 
00625 void MainFrame::panoramaChanged(HuginBase::Panorama &pano)
00626 {
00627     wxToolBar* theToolBar = GetToolBar();
00628     wxMenuBar* theMenuBar = GetMenuBar();
00629     bool can_undo = PanoCommand::GlobalCmdHist::getInstance().canUndo();
00630     theMenuBar->Enable    (XRCID("ID_EDITUNDO"), can_undo);
00631     theToolBar->EnableTool(XRCID("ID_EDITUNDO"), can_undo);
00632     bool can_redo = PanoCommand::GlobalCmdHist::getInstance().canRedo();
00633     theMenuBar->Enable    (XRCID("ID_EDITREDO"), can_redo);
00634     theToolBar->EnableTool(XRCID("ID_EDITREDO"), can_redo);
00635 
00636     //show or hide optimizer and exposure optimizer tab depending on optimizer master switches
00637     if(pano.getOptimizerSwitch()==0 && !m_show_opt_panel)
00638     {
00639         m_notebook->InsertPage(3, opt_panel, _("Optimizer"));
00640         m_show_opt_panel=true;
00641     };
00642     if(pano.getOptimizerSwitch()!=0 && m_show_opt_panel)
00643     {
00644         m_notebook->RemovePage(3);
00645         m_show_opt_panel=false;
00646     };
00647     if(pano.getPhotometricOptimizerSwitch()==0 && !m_show_opt_photo_panel)
00648     {
00649         if(m_show_opt_panel)
00650         {
00651             m_notebook->InsertPage(4, opt_photo_panel, _("Exposure"));
00652         }
00653         else
00654         {
00655             m_notebook->InsertPage(3, opt_photo_panel, _("Exposure"));
00656         }
00657         m_show_opt_photo_panel=true;
00658     };
00659     if(pano.getPhotometricOptimizerSwitch()!=0 && m_show_opt_photo_panel)
00660     {
00661         if(m_show_opt_panel)
00662         {
00663             m_notebook->RemovePage(4);
00664         }
00665         else
00666         {
00667             m_notebook->RemovePage(3);
00668         };
00669         m_show_opt_photo_panel=false;
00670     };
00671     theMenuBar->Enable(XRCID("ID_SHOW_PANEL_OPTIMIZER"), m_show_opt_panel);
00672     theMenuBar->Enable(XRCID("ID_SHOW_PANEL_OPTIMIZER_PHOTOMETRIC"), m_show_opt_photo_panel);
00673 }
00674 
00675 //void MainFrame::panoramaChanged(HuginBase::Panorama &panorama)
00676 void MainFrame::panoramaImagesChanged(HuginBase::Panorama &panorama, const HuginBase::UIntSet & changed)
00677 {
00678     DEBUG_TRACE("");
00679     assert(&pano == &panorama);
00680     if (pano.getNrOfImages() == 0) {
00681           enableTools(false);
00682         } else {
00683           enableTools(true);
00684         }
00685     GetMenuBar()->Enable(XRCID("action_assistant"), pano.getNrOfImages()>=2);
00686     GetMenuBar()->Enable(XRCID("action_batch_assistant"), pano.getNrOfImages()>=2);
00687 }
00688 
00689 void MainFrame::OnUserQuit(wxCommandEvent & e)
00690 {
00691     Close();
00692 }
00693 
00694 bool MainFrame::CloseProject(bool cancelable)
00695 {
00696     if (pano.isDirty()) {
00697         wxMessageDialog message(wxGetActiveWindow(),
00698                                 _("Save changes to the panorama before closing?"),
00699 #ifdef _WIN32
00700                                 _("Hugin"),
00701 #else
00702                                 wxT(""),
00703 #endif
00704                                 wxICON_EXCLAMATION | wxYES_NO | (cancelable? (wxCANCEL):0));
00705 #if wxCHECK_VERSION(2, 9, 0)
00706     message.SetExtendedMessage(_("If you close without saving, changes since your last save will be discarded"));
00707     #if defined __WXMAC__ || defined __WXMSW__
00708         // Apple human interface guidelines and Windows user experience interaction guidelines
00709         message.SetYesNoLabels(wxID_SAVE, _("Don't Save"));
00710     #else
00711         // Gnome human interface guidelines:
00712         message.SetYesNoLabels(wxID_SAVE, _("Close without saving"));
00713     #endif
00714 #endif
00715         int answer = message.ShowModal();
00716         switch (answer){
00717             case wxID_YES:
00718             {
00719                 wxCommandEvent dummy;
00720                 OnSaveProject(dummy);
00721                 return !pano.isDirty();
00722             }
00723             case wxID_CANCEL:
00724                 return false;
00725             default: //no save
00726                 return true;
00727         }
00728     }
00729     else return true;
00730 }
00731 
00732 void MainFrame::OnExit(wxCloseEvent & e)
00733 {
00734     DEBUG_TRACE("");
00735     if(m_guiLevel!=GUI_SIMPLE)
00736     {
00737         if(!CloseProject(e.CanVeto()))
00738         {
00739            if (e.CanVeto())
00740            {
00741                 e.Veto();
00742                 return;
00743            }
00744            wxLogError(_("forced close"));
00745         }
00746     }
00747     else
00748     {
00749         if(e.CanVeto())
00750         {
00751             Hide();
00752             e.Veto();
00753             return;
00754         };
00755     };
00756 
00757     if(preview_frame)
00758     {
00759        preview_frame->Close(true);
00760     }
00761 
00762     ImageCache::getInstance().flush();
00763     Destroy();
00764     DEBUG_TRACE("");
00765 }
00766 
00767 void MainFrame::OnSaveProject(wxCommandEvent & e)
00768 {
00769     DEBUG_TRACE("");
00770     try {
00771     wxFileName scriptName = m_filename;
00772     if (m_filename == wxT("")) {
00773         OnSaveProjectAs(e);
00774         scriptName = m_filename;
00775     } else {
00776         // the project file is just a PTOptimizer script...
00777         std::string path = hugin_utils::getPathPrefix(std::string(scriptName.GetFullPath().mb_str(HUGIN_CONV_FILENAME)));
00778         DEBUG_DEBUG("stripping " << path << " from image filenames");
00779         std::ofstream script(scriptName.GetFullPath().mb_str(HUGIN_CONV_FILENAME));
00780         script.exceptions ( std::ofstream::eofbit | std::ofstream::failbit | std::ofstream::badbit );
00781         HuginBase::UIntSet all;
00782         if (pano.getNrOfImages() > 0) {
00783            fill_set(all, 0, pano.getNrOfImages()-1);
00784         }
00785         pano.printPanoramaScript(script, pano.getOptimizeVector(), pano.getOptions(), all, false, path);
00786         script.close();
00787 
00788         SetStatusText(wxString::Format(_("saved project %s"), m_filename.c_str()),0);
00789         if(m_guiLevel==GUI_SIMPLE)
00790         {
00791             if(gl_preview_frame)
00792             {
00793                 gl_preview_frame->SetTitle(scriptName.GetName() + wxT(".") + scriptName.GetExt() + wxT(" - ") + _("Hugin - Panorama Stitcher"));
00794             };
00795             SetTitle(scriptName.GetName() + wxT(".") + scriptName.GetExt() + wxT(" - ") + _("Panorama editor"));
00796         }
00797         else
00798         {
00799             SetTitle(scriptName.GetName() + wxT(".") + scriptName.GetExt() + wxT(" - ") + _("Hugin - Panorama Stitcher"));
00800         };
00801 
00802         pano.clearDirty();
00803     }
00804     } catch (std::exception & e) {
00805         wxString err(e.what(), wxConvLocal);
00806             wxMessageBox(wxString::Format(_("Could not save project file \"%s\".\nMaybe the file or the folder is read-only.\n\n(Error code: %s)"),m_filename.c_str(),err.c_str()),_("Error"),wxOK|wxICON_ERROR);
00807     }
00808 }
00809 
00810 void MainFrame::OnSaveProjectAs(wxCommandEvent & e)
00811 {
00812     DEBUG_TRACE("");
00813     wxFileName scriptName;
00814     if (m_filename.IsEmpty())
00815     {
00816         scriptName.Assign(getDefaultProjectName(pano) + wxT(".pto"));
00817     }
00818     else
00819     {
00820         scriptName=m_filename;
00821     };
00822     scriptName.Normalize();
00823     wxFileDialog dlg(wxGetActiveWindow(),
00824                      _("Save project file"),
00825                      scriptName.GetPath(), scriptName.GetFullName(),
00826                      _("Project files (*.pto)|*.pto|All files (*)|*"),
00827                      wxFD_SAVE | wxFD_OVERWRITE_PROMPT, wxDefaultPosition);
00828     if (dlg.ShowModal() == wxID_OK) {
00829         wxConfig::Get()->Write(wxT("/actualPath"), dlg.GetDirectory());  // remember for later
00830         wxString fn = dlg.GetPath();
00831         if (fn.Right(4).CmpNoCase(wxT(".pto"))!=0)
00832         {
00833             fn.Append(wxT(".pto"));
00834             if (wxFile::Exists(fn)) {
00835                 int d = wxMessageBox(wxString::Format(_("File %s exists. Overwrite?"), fn.c_str()),
00836                     _("Save project"), wxYES_NO | wxICON_QUESTION);
00837                 if (d != wxYES) {
00838                     return;
00839                 }
00840             }
00841         }
00842         m_filename = fn;
00843         m_mruFiles.AddFileToHistory(m_filename);
00844         OnSaveProject(e);
00845     }
00846 }
00847 
00848 void MainFrame::OnSavePTStitcherAs(wxCommandEvent & e)
00849 {
00850     DEBUG_TRACE("");
00851     wxString scriptName = m_filename;
00852     if (m_filename == wxT("")) {
00853         scriptName = getDefaultProjectName(pano);
00854     }
00855     wxFileName scriptNameFN(scriptName);
00856     wxString fn = scriptNameFN.GetName() + wxT(".txt");
00857     wxFileDialog dlg(wxGetActiveWindow(),
00858                      _("Save PTmender script file"),
00859                      wxConfigBase::Get()->Read(wxT("/actualPath"),wxT("")), fn,
00860                      _("PTmender files (*.txt)|*.txt"),
00861                      wxFD_SAVE | wxFD_OVERWRITE_PROMPT, wxDefaultPosition);
00862     if (dlg.ShowModal() == wxID_OK) {
00863         wxString fname = dlg.GetPath();
00864         // the project file is just a PTStitcher script...
00865         wxFileName scriptName = fname;
00866         HuginBase::UIntSet all;
00867         if (pano.getNrOfImages() > 0) {
00868             fill_set(all, 0, pano.getNrOfImages()-1);
00869         }
00870         std::ofstream script(scriptName.GetFullPath().mb_str(HUGIN_CONV_FILENAME));
00871         pano.printStitcherScript(script, pano.getOptions(), all);
00872         script.close();
00873     }
00874 
00875 }
00876 
00877 void MainFrame::LoadProjectFile(const wxString & filename)
00878 {
00879     DEBUG_TRACE("");
00880     m_filename = filename;
00881 
00882     // remove old images from cache
00883     // hmm probably not a good idea, if the project is reloaded..
00884     // ImageCache::getInstance().flush();
00885 
00886     SetStatusText( _("Open project:   ") + filename);
00887 
00888     wxFileName fname(filename);
00889     wxString path = fname.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR);
00890     if (fname.IsOk() && fname.FileExists()) {
00891         wxBusyCursor wait;
00892         deregisterPTWXDlgFcn();
00893         PanoCommand::GlobalCmdHist::getInstance().addCommand(
00894             new PanoCommand::wxLoadPTProjectCmd(pano, (const char *)filename.mb_str(HUGIN_CONV_FILENAME), (const char *)path.mb_str(HUGIN_CONV_FILENAME), true)
00895            );
00896         PanoCommand::GlobalCmdHist::getInstance().clear();
00897         registerPTWXDlgFcn();
00898         DEBUG_DEBUG("project contains " << pano.getNrOfImages() << " after load");
00899         GuiLevel reqGuiLevel=GetMinimumGuiLevel(pano);
00900         if(reqGuiLevel>m_guiLevel)
00901         {
00902             SetGuiLevel(reqGuiLevel);
00903         };
00904         SetStatusText(_("Project opened"));
00905         m_mruFiles.AddFileToHistory(fname.GetFullPath());
00906         if(m_guiLevel==GUI_SIMPLE)
00907         {
00908             if(gl_preview_frame)
00909             {
00910                 gl_preview_frame->SetTitle(fname.GetName() + wxT(".") + fname.GetExt() + wxT(" - ") + _("Hugin - Panorama Stitcher"));
00911             };
00912             SetTitle(fname.GetName() + wxT(".") + fname.GetExt() + wxT(" - ") + _("Panorama editor"));
00913         }
00914         else
00915         {
00916             SetTitle(fname.GetName() + wxT(".") + fname.GetExt() + wxT(" - ") + _("Hugin - Panorama Stitcher"));
00917         };
00918         if (! (fname.GetExt() == wxT("pto"))) {
00919             // do not remember filename if its not a hugin project
00920             // to avoid overwriting the original project with an
00921             // incompatible one
00922             m_filename = wxT("");
00923         }
00924         // get the global config object
00925         wxConfigBase* config = wxConfigBase::Get();
00926         config->Write(wxT("/actualPath"), path);  // remember for later
00927     } else {
00928         SetStatusText( _("Error opening project:   ") + filename);
00929         DEBUG_ERROR("Could not open file " << filename);
00930     }
00931 
00932     // force update of preview window
00933     if ( !(preview_frame->IsIconized() ||(! preview_frame->IsShown()) ) ) {
00934         wxCommandEvent dummy;
00935         preview_frame->OnUpdate(dummy);
00936     }
00937 }
00938 
00939 #ifdef __WXMAC__
00940 void MainFrame::MacOnOpenFile(const wxString & filename)
00941 {
00942     if(!CloseProject(true)) return; //if closing old project is canceled do nothing.
00943 
00944     ImageCache::getInstance().flush();
00945     LoadProjectFile(filename);
00946 }
00947 #endif
00948 
00949 void MainFrame::OnLoadProject(wxCommandEvent & e)
00950 {
00951     DEBUG_TRACE("");
00952 
00953     if(CloseProject(true)) //if closing old project is canceled do nothing.
00954     {
00955         // get the global config object
00956         wxConfigBase* config = wxConfigBase::Get();
00957 
00958         wxString defaultdir = config->Read(wxT("/actualPath"),wxT(""));
00959         wxFileDialog dlg(wxGetActiveWindow(),
00960                          _("Open project file"),
00961                          defaultdir, wxT(""),
00962                          _("Project files (*.pto)|*.pto|All files (*)|*"),
00963                          wxFD_OPEN, wxDefaultPosition);
00964         dlg.SetDirectory(defaultdir);
00965         if (dlg.ShowModal() == wxID_OK)
00966         {
00967             wxString filename = dlg.GetPath();
00968             if(vigra::isImage(filename.mb_str(HUGIN_CONV_FILENAME)))
00969             {
00970                 if(wxMessageBox(wxString::Format(_("File %s is an image file and not a project file.\nThis file can't be open with File, Open.\nDo you want to add this image file to the current project?"),filename.c_str()),
00971 #ifdef __WXMSW__
00972                     _("Hugin"),
00973 #else
00974                     wxT(""),
00975 #endif
00976                     wxYES_NO | wxICON_QUESTION)==wxYES)
00977                 {
00978                     wxArrayString filenameArray;
00979                     filenameArray.Add(filename);
00980                     AddImages(filenameArray);
00981                 };
00982                 return;
00983             }
00984             else
00985             {
00986                 // remove old images from cache
00987                 ImageCache::getInstance().flush();
00988 
00989                 LoadProjectFile(filename);
00990                 return;
00991             };
00992         }
00993     }
00994     // do not close old project
00995     // nothing to open
00996     SetStatusText( _("Open project: cancel"));
00997 }
00998 
00999 void MainFrame::OnNewProject(wxCommandEvent & e)
01000 {
01001     if(!CloseProject(true)) return; //if closing current project is canceled
01002 
01003     m_filename = wxT("");
01004     PanoCommand::GlobalCmdHist::getInstance().addCommand(new PanoCommand::wxNewProjectCmd(pano));
01005     PanoCommand::GlobalCmdHist::getInstance().clear();
01006     // remove old images from cache
01007     ImageCache::getInstance().flush();
01008     if(m_guiLevel==GUI_SIMPLE)
01009     {
01010         if(gl_preview_frame)
01011         {
01012             gl_preview_frame->SetTitle(_("Hugin - Panorama Stitcher"));
01013         };
01014         SetTitle(_("Panorama editor"));
01015     }
01016     else
01017     {
01018         SetTitle(_("Hugin - Panorama Stitcher"));
01019     };
01020 
01021     wxCommandEvent dummy;
01022     preview_frame->OnUpdate(dummy);
01023 }
01024 
01025 void MainFrame::OnAddImages( wxCommandEvent& event )
01026 {
01027     DEBUG_TRACE("");
01028     PanoOperation::AddImageOperation addImage;
01029     HuginBase::UIntSet images;
01030     PanoCommand::PanoCommand* cmd = addImage.GetCommand(wxGetActiveWindow(), pano, images, m_guiLevel);
01031     if(cmd!=NULL)
01032     {
01033         PanoCommand::GlobalCmdHist::getInstance().addCommand(cmd);
01034     }
01035     else
01036     {
01037         // nothing to open
01038         SetStatusText( _("Add Image: cancel"));
01039     }
01040 
01041     DEBUG_TRACE("");
01042 }
01043 
01044 void MainFrame::AddImages(wxArrayString& filenameArray)
01045 {
01046     wxArrayString invalidFiles;
01047     for(unsigned int i=0;i<filenameArray.GetCount(); i++)
01048     {
01049         if(containsInvalidCharacters(filenameArray[i]))
01050         {
01051             invalidFiles.Add(filenameArray[i]);
01052         };
01053     };
01054     if(invalidFiles.size()>0)
01055     {
01056         ShowFilenameWarning(this, invalidFiles);
01057     }
01058     else
01059     {
01060         std::vector<std::string> filesv;
01061         for (unsigned int i=0; i< filenameArray.GetCount(); i++) {
01062             filesv.push_back((const char *)filenameArray[i].mb_str(HUGIN_CONV_FILENAME));
01063         }
01064 
01065         // we got some images to add.
01066         if (filesv.size() > 0) {
01067             // use a Command to ensure proper undo and updating of GUI
01068             // parts
01069             wxBusyCursor();
01070             PanoCommand::GlobalCmdHist::getInstance().addCommand(
01071                 new PanoCommand::wxAddImagesCmd(pano, filesv)
01072                 );
01073         };
01074     };
01075 };
01076 
01077 void MainFrame::OnAddTimeImages( wxCommandEvent& event )
01078 {
01079     PanoOperation::AddImagesSeriesOperation imageSeriesOp;
01080     HuginBase::UIntSet images;
01081     PanoCommand::PanoCommand* cmd = imageSeriesOp.GetCommand(wxGetActiveWindow(), pano, images, m_guiLevel);
01082     if(cmd!=NULL)
01083     {
01084         PanoCommand::GlobalCmdHist::getInstance().addCommand(cmd);
01085     };
01086 };
01087 
01088 void MainFrame::OnShowDonate(wxCommandEvent & e)
01089 {
01090     wxLaunchDefaultBrowser(wxT("http://sourceforge.net/project/project_donations.php?group_id=77506"));
01091 }
01092 
01093 
01094 void MainFrame::OnShowPanel(wxCommandEvent & e)
01095 {
01096     if(e.GetId()==XRCID("ID_SHOW_PANEL_MASK"))
01097         m_notebook->SetSelection(1);
01098     else
01099         if(e.GetId()==XRCID("ID_SHOW_PANEL_CP_EDITOR"))
01100             m_notebook->SetSelection(2);
01101         else
01102             if(e.GetId()==XRCID("ID_SHOW_PANEL_OPTIMIZER"))
01103                 m_notebook->SetSelection(3);
01104             else
01105                 if(e.GetId()==XRCID("ID_SHOW_PANEL_OPTIMIZER_PHOTOMETRIC"))
01106                 {
01107                     if(m_show_opt_panel)
01108                     {
01109                         m_notebook->SetSelection(4);
01110                     }
01111                     else
01112                     {
01113                         m_notebook->SetSelection(3);
01114                     };
01115                 }
01116                 else
01117                     if(e.GetId()==XRCID("ID_SHOW_PANEL_PANORAMA"))
01118                     {
01119                         if(m_show_opt_panel && m_show_opt_photo_panel)
01120                         {
01121                             m_notebook->SetSelection(5);
01122                         }
01123                         else
01124                         {
01125                             if(m_show_opt_panel || m_show_opt_photo_panel)
01126                             {
01127                                 m_notebook->SetSelection(4);
01128                             }
01129                             else
01130                             {
01131                                 m_notebook->SetSelection(3);
01132                             };
01133                         };
01134                     }
01135                     else
01136                         m_notebook->SetSelection(0);
01137 }
01138 
01139 
01140 void MainFrame::OnAbout(wxCommandEvent & e)
01141 {
01142     AboutDialog dlg(wxGetActiveWindow());
01143     dlg.ShowModal();
01144 }
01145 
01146 /*
01147 void MainFrame::OnAbout(wxCommandEvent & e)
01148 {
01149     DEBUG_TRACE("");
01150     wxDialog dlg;
01151         wxString strFile;
01152         wxString langCode;
01153 
01154     wxXmlResource::Get()->LoadDialog(&dlg, this, wxT("about_dlg"));
01155 
01156 #if __WXMAC__ && defined MAC_SELF_CONTAINED_BUNDLE
01157     //rely on the system's locale choice
01158     strFile = MacGetPathToBundledResourceFile(CFSTR("about.htm"));
01159     if(strFile!=wxT("")) XRCCTRL(dlg,"about_html",wxHtmlWindow)->LoadPage(strFile);
01160 #else
01161     //if the language is not default, load custom About file (if exists)
01162     langCode = huginApp::Get()->GetLocale().GetName().Left(2).Lower();
01163     DEBUG_INFO("Lang Code: " << langCode.mb_str(wxConvLocal));
01164     if(langCode != wxString(wxT("en")))
01165     {
01166         strFile = GetXRCPath() + wxT("data/about_") + langCode + wxT(".htm");
01167         if(wxFile::Exists(strFile))
01168         {
01169             DEBUG_TRACE("Using About: " << strFile.mb_str(wxConvLocal));
01170             XRCCTRL(dlg,"about_html",wxHtmlWindow)->LoadPage(strFile);
01171         }
01172     }
01173 #endif
01174     dlg.ShowModal();
01175 }
01176 */
01177 
01178 void MainFrame::OnHelp(wxCommandEvent & e)
01179 {
01180     DisplayHelp();
01181 }
01182 
01183 void MainFrame::OnKeyboardHelp(wxCommandEvent & e)
01184 {
01185     DisplayHelp(wxT("/Hugin_Keyboard_shortcuts.html"));
01186 }
01187 
01188 void MainFrame::OnFAQ(wxCommandEvent & e)
01189 {
01190     DisplayHelp(wxT("/Hugin_FAQ.html"));
01191 }
01192 
01193 
01194 void MainFrame::DisplayHelp(wxString section)
01195 {
01196     // TODO:
01197     // structure a frame with navigation on the left and content on the right
01198     // always load the same navigation on the left and the section into the frame
01199     // find a way to target always the same window rather than opening new window / tabs in the browser every time
01200     // make it look nicer with some CSS styling
01201 
01202     // section is the HTML document to be displayed, from inside the data folder
01203 
01204     DEBUG_TRACE("");
01205 
01206 #ifdef __WXMSW__
01207     if (section.IsEmpty())
01208     {
01209         // wxWidgets 3.x has a bug, that prevents DisplaySection to work on Win8/10 64 bit
01210         // see: http://trac.wxwidgets.org/ticket/14888
01211         // so using DisplayContents() and our own implementation of HuginCHMHelpController
01212         GetHelpController().DisplayContents();
01213     }
01214     else
01215     {
01216 #if wxCHECK_VERSION(3,1,1)
01217         GetHelpController().DisplaySection(section);
01218 #else
01219         GetHelpController().DisplayHelpPage(section);
01220 #endif
01221     };
01222 #else
01223     if (section.IsEmpty())
01224     {
01225         section = wxT("/Hugin.html");
01226     }
01227 #if defined __WXMAC__ && defined MAC_SELF_CONTAINED_BUNDLE
01228     // On Mac, xrc/data/help_LOCALE should be in the bundle as LOCALE.lproj/help
01229     // which we can rely on the operating sytem to pick the right locale's.
01230     wxString strFile = MacGetPathToBundledResourceFile(CFSTR("help"));
01231     if(strFile!=wxT(""))
01232     {
01233         strFile += section;
01234     } else {
01235         wxLogError(wxString::Format(wxT("Could not find help directory in the bundle"), strFile.c_str()));
01236         return;
01237     }
01238 #else
01239     // find base filename
01240     wxString helpFile = wxT("help_") + huginApp::Get()->GetLocale().GetCanonicalName() + section;
01241     DEBUG_INFO("help file candidate: " << helpFile.mb_str(wxConvLocal));
01242     //if the language is not default, load custom About file (if exists)
01243     wxString strFile = GetXRCPath() + wxT("data/") + helpFile;
01244     if(wxFile::Exists(strFile))
01245     {
01246         DEBUG_TRACE("Using About: " << strFile.mb_str(wxConvLocal));
01247     } else {
01248         strFile = GetXRCPath() + wxT("data/help_en_EN") + section;
01249     }
01250 #endif
01251     if(!wxFile::Exists(strFile))
01252     {
01253         wxLogError(wxString::Format(wxT("Could not open help file: %s"), strFile.c_str()));
01254         return;
01255     }
01256     DEBUG_INFO("help file: " << strFile.mb_str(wxConvLocal));
01257     if(!wxLaunchDefaultBrowser(strFile))
01258     {
01259         wxLogError(_("Can't start system's web browser"));
01260     }
01261 #endif
01262 }
01263 
01264 void MainFrame::OnTipOfDay(wxCommandEvent& WXUNUSED(e))
01265 {
01266     wxString strFile;
01267     bool bShowAtStartup;
01268 // DGSW FIXME - Unreferenced
01269 //      bool bTipsExist = false;
01270     int nValue;
01271 
01272     wxConfigBase * config = wxConfigBase::Get();
01273     nValue = config->Read(wxT("/MainFrame/ShowStartTip"),1l);
01274 
01275     //TODO: tips not localisable
01276     DEBUG_INFO("Tip index: " << nValue);
01277     strFile = GetXRCPath() + wxT("data/tips.txt");  //load default file
01278 
01279     DEBUG_INFO("Reading tips from " << strFile.mb_str(wxConvLocal));
01280     wxTipProvider *tipProvider = new LocalizedFileTipProvider(strFile, nValue);
01281     bShowAtStartup = wxShowTip(wxGetActiveWindow(), tipProvider, (nValue ? true : false));
01282 
01283     //store startup preferences
01284     nValue = (bShowAtStartup ? tipProvider->GetCurrentTip() : 0);
01285     DEBUG_INFO("Writing tip index: " << nValue);
01286     config->Write(wxT("/MainFrame/ShowStartTip"), nValue);
01287     delete tipProvider;
01288 }
01289 
01290 
01291 void MainFrame::OnShowPrefs(wxCommandEvent & e)
01292 {
01293     DEBUG_TRACE("");
01294     PreferencesDialog pref_dlg(wxGetActiveWindow());
01295     pref_dlg.ShowModal();
01296     //update image cache size
01297     wxConfigBase* cfg=wxConfigBase::Get();
01298 #if defined __WXMSW__
01299     unsigned long long mem = HUGIN_IMGCACHE_UPPERBOUND;
01300     unsigned long mem_low = cfg->Read(wxT("/ImageCache/UpperBound"), HUGIN_IMGCACHE_UPPERBOUND);
01301     unsigned long mem_high = cfg->Read(wxT("/ImageCache/UpperBoundHigh"), (long) 0);
01302     if (mem_high > 0)
01303     {
01304       mem = ((unsigned long long) mem_high << 32) + mem_low;
01305     }
01306     else
01307     {
01308       mem = mem_low;
01309     }
01310     ImageCache::getInstance().SetUpperLimit(mem);
01311 #else
01312     ImageCache::getInstance().SetUpperLimit(cfg->Read(wxT("/ImageCache/UpperBound"), HUGIN_IMGCACHE_UPPERBOUND));
01313 #endif
01314     images_panel->ReloadCPDetectorSettings();
01315     if(gl_preview_frame)
01316     {
01317         gl_preview_frame->SetShowProjectionHints(cfg->Read(wxT("/GLPreviewFrame/ShowProjectionHints"),HUGIN_SHOW_PROJECTION_HINTS)!=0);
01318     };
01319 }
01320 
01321 void MainFrame::UpdatePanels( wxCommandEvent& WXUNUSED(event) )
01322 {   // Maybe this can be invoced by the Panorama::Changed() or
01323     // something like this. So no everytime update would be needed.
01324     DEBUG_TRACE("");
01325 }
01326 
01327 void MainFrame::OnTogglePreviewFrame(wxCommandEvent & e)
01328 {
01329     DEBUG_TRACE("");
01330     if (preview_frame->IsIconized()) {
01331         preview_frame->Iconize(false);
01332     }
01333     preview_frame->Show();
01334     preview_frame->Raise();
01335 
01336         // we need to force an update since autoupdate fires
01337         // before the preview frame is shown
01338     wxCommandEvent dummy;
01339         preview_frame->OnUpdate(dummy);
01340 }
01341 
01342 void MainFrame::OnToggleGLPreviewFrame(wxCommandEvent & e)
01343 {
01344     if(gl_preview_frame==NULL)
01345     {
01346         return;
01347     };
01348 #if defined __WXMSW__ || defined __WXMAC__
01349     gl_preview_frame->InitPreviews();
01350 #endif
01351     if (gl_preview_frame->IsIconized()) {
01352         gl_preview_frame->Iconize(false);
01353     }
01354     gl_preview_frame->Show();
01355 #if defined __WXMSW__
01356     // on wxMSW Show() does not send OnShowEvent needed to update the
01357     // visibility state of the fast preview windows
01358     // so explicit calling this event handler
01359     wxShowEvent se;
01360     se.SetShow(true);
01361     gl_preview_frame->OnShowEvent(se);
01362 #elif defined __WXGTK__
01363     gl_preview_frame->LoadOpenGLLayout();
01364 #endif
01365     gl_preview_frame->Raise();
01366 }
01367 
01368 void MainFrame::OnShowCPFrame(wxCommandEvent & e)
01369 {
01370     DEBUG_TRACE("");
01371     if (cp_frame) {
01372         if (cp_frame->IsIconized()) {
01373             cp_frame->Iconize(false);
01374         }
01375         cp_frame->Show();
01376         cp_frame->Raise();
01377     } else {
01378         cp_frame = new CPListFrame(this, pano);
01379         cp_frame->Show();
01380     }
01381 }
01382 
01383 void MainFrame::OnCPListFrameClosed()
01384 {
01385     cp_frame = 0;
01386 }
01387 
01388 void MainFrame::OnOptimize(wxCommandEvent & e)
01389 {
01390     DEBUG_TRACE("");
01391     wxCommandEvent dummy;
01392     opt_panel->OnOptimizeButton(dummy);
01393 }
01394 
01395 void MainFrame::OnOnlyActiveImages(wxCommandEvent &e)
01396 {
01397     m_optOnlyActiveImages = GetMenuBar()->IsChecked(XRCID("action_optimize_only_active"));
01398     opt_panel->SetOnlyActiveImages(m_optOnlyActiveImages);
01399     // notify all observer so they can update their display
01400     pano.changeFinished();
01401 };
01402 
01403 void MainFrame::SetOptimizeOnlyActiveImages(const bool onlyActive)
01404 {
01405     m_optOnlyActiveImages = onlyActive;
01406     wxMenuBar* menubar = GetMenuBar();
01407     if (menubar)
01408     {
01409         menubar->Check(XRCID("action_optimize_only_active"), onlyActive);
01410         // notify all observer so they can update their display
01411         pano.changeFinished();
01412     };
01413 };
01414 
01415 const bool MainFrame::GetOptimizeOnlyActiveImages() const
01416 {
01417     return m_optOnlyActiveImages;
01418 };
01419 
01420 void MainFrame::OnPhotometricOptimize(wxCommandEvent & e)
01421 {
01422     wxCommandEvent dummy;
01423     opt_photo_panel->OnOptimizeButton(dummy);
01424 };
01425 
01426 void MainFrame::OnDoStitch(wxCommandEvent & e)
01427 {
01428     DEBUG_TRACE("");
01429     wxCommandEvent cmdEvt(wxEVT_COMMAND_BUTTON_CLICKED,XRCID("pano_button_stitch"));
01430     pano_panel->GetEventHandler()->AddPendingEvent(cmdEvt);
01431 }
01432 
01433 void MainFrame::OnUserDefinedStitch(wxCommandEvent & e)
01434 {
01435     pano_panel->DoUserDefinedStitch();
01436 }
01437 
01438 void MainFrame::OnMergeProject(wxCommandEvent & e)
01439 {
01440     // get the global config object
01441     wxConfigBase* config = wxConfigBase::Get();
01442 
01443     wxString defaultdir = config->Read(wxT("/actualPath"),wxT(""));
01444     wxFileDialog dlg(wxGetActiveWindow(),
01445                      _("Open project file"),
01446                      defaultdir, wxT(""),
01447                      _("Project files (*.pto)|*.pto|All files (*)|*"),
01448                      wxFD_OPEN, wxDefaultPosition);
01449     dlg.SetDirectory(defaultdir);
01450     if (dlg.ShowModal() == wxID_OK)
01451     {
01452         wxString filename = dlg.GetPath();
01453         wxFileName fname(filename);
01454         wxString path = fname.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR);
01455         if (fname.IsOk() && fname.FileExists())
01456         {
01457             wxBusyCursor wait;
01458             HuginBase::PanoramaMemento newPano;
01459             std::ifstream in((const char *)fname.GetFullPath().mb_str(HUGIN_CONV_FILENAME));
01460             int ptoversion=0;
01461             if (newPano.loadPTScript(in, ptoversion, (const char *)path.mb_str(HUGIN_CONV_FILENAME)))
01462             {
01463                 HuginBase::Panorama new_pano;
01464                 new_pano.setMemento(newPano);
01465                 PanoCommand::GlobalCmdHist::getInstance().addCommand(
01466                     new PanoCommand::MergePanoCmd(pano, new_pano)
01467                 );
01468                 m_mruFiles.AddFileToHistory(fname.GetFullPath());
01469                 // force update of preview window
01470                 if ( !(preview_frame->IsIconized() ||(! preview_frame->IsShown()) ) )
01471                 {
01472                     wxCommandEvent dummy;
01473                     preview_frame->OnUpdate(dummy);
01474                 };
01475             }
01476             else
01477             {
01478                 wxMessageBox(wxString::Format(_("Could not read project file %s."),fname.GetFullPath().c_str()),_("Error"),wxOK|wxICON_ERROR);
01479             };
01480         };
01481     }
01482 }
01483 
01484 void MainFrame::OnReadPapywizard(wxCommandEvent & e)
01485 {
01486     wxString currentDir = wxConfigBase::Get()->Read(wxT("/actualPath"), wxT(""));
01487     wxFileDialog dlg(wxGetActiveWindow(), _("Open Papywizard xml file"),
01488         currentDir, wxT(""), _("Papywizard xml files (*.xml)|*.xml|All files (*)|*"),
01489         wxFD_OPEN, wxDefaultPosition);
01490     dlg.SetDirectory(currentDir);
01491     if (dlg.ShowModal() == wxID_OK)
01492     {
01493         wxConfigBase::Get()->Write(wxT("/actualPath"), dlg.GetDirectory());
01494         Papywizard::ImportPapywizardFile(dlg.GetPath(), pano);
01495     };
01496 };
01497 
01498 void MainFrame::OnApplyTemplate(wxCommandEvent & e)
01499 {
01500     // get the global config object
01501     wxConfigBase* config = wxConfigBase::Get();
01502 
01503     wxFileDialog dlg(wxGetActiveWindow(),
01504                      _("Choose template project"),
01505                      config->Read(wxT("/templatePath"),wxT("")), wxT(""),
01506                      _("Project files (*.pto)|*.pto|All files (*)|*"),
01507                      wxFD_OPEN, wxDefaultPosition);
01508     dlg.SetDirectory(wxConfigBase::Get()->Read(wxT("/templatePath"),wxT("")));
01509     if (dlg.ShowModal() == wxID_OK) {
01510         wxString filename = dlg.GetPath();
01511         wxConfig::Get()->Write(wxT("/templatePath"), dlg.GetDirectory());  // remember for later
01512 
01513         std::ifstream file((const char *)filename.mb_str(HUGIN_CONV_FILENAME));
01514 
01515         PanoCommand::GlobalCmdHist::getInstance().addCommand(
01516             new PanoCommand::wxApplyTemplateCmd(pano, file));
01517 
01518     }
01519 }
01520 
01521 void MainFrame::OnOpenPTBatcher(wxCommandEvent & e)
01522 {
01523 #if defined __WXMAC__ && defined MAC_SELF_CONTAINED_BUNDLE
01524         // Original patch for OSX by Charlie Reiman dd. 18 June 2011
01525         // Slightly modified by HvdW. Errors in here are mine, not Charlie's. 
01526         FSRef appRef;
01527         FSRef actuallyLaunched;
01528         OSStatus err;
01529         FSRef documentArray[1]; // Don't really need an array if we only have 1 item
01530         LSLaunchFSRefSpec launchSpec;
01531         Boolean  isDir;
01532         
01533         err = LSFindApplicationForInfo(kLSUnknownCreator,
01534                                                                    CFSTR("net.sourceforge.hugin.PTBatcherGUI"),
01535                                                                    NULL,
01536                                                                    &appRef,
01537                                                                    NULL);
01538         if (err != noErr) {
01539                 // error, can't find PTBatcherGUI
01540                 wxMessageBox(wxString::Format(_("External program %s not found in the bundle, reverting to system path"), wxT("open")), _("Error"));
01541                 // Possibly a silly attempt otherwise the previous would have worked as well, but just try it.
01542                 wxExecute(_T("open -b net.sourceforge.hugin.PTBatcherGUI"));
01543         }
01544         else {
01545                 wxExecute(_T("open -b net.sourceforge.hugin.PTBatcherGUI"));
01546         }       
01547 #else
01548     const wxFileName exePath(wxStandardPaths::Get().GetExecutablePath());
01549         wxExecute(exePath.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR) + _T("PTBatcherGUI"));
01550 #endif
01551 }
01552 
01553 void MainFrame::OnFineTuneAll(wxCommandEvent & e)
01554 {
01555     DEBUG_TRACE("");
01556     // fine-tune all points
01557 
01558     HuginBase::CPVector cps = pano.getCtrlPoints();
01559 
01560     // create a map of all control points.
01561     std::set<unsigned int> unoptimized;
01562     for (unsigned int i=0; i < cps.size(); i++) {
01563         // create all control points.
01564         unoptimized.insert(i);
01565     }
01566 
01567     unsigned int nGood=0;
01568     unsigned int nBad=0;
01569 
01570     wxConfigBase *cfg = wxConfigBase::Get();
01571     double corrThresh=HUGIN_FT_CORR_THRESHOLD;
01572     cfg->Read(wxT("/Finetune/CorrThreshold"), &corrThresh, HUGIN_FT_CORR_THRESHOLD);
01573     double curvThresh = HUGIN_FT_CURV_THRESHOLD;
01574     cfg->Read(wxT("/Finetune/CurvThreshold"),&curvThresh, HUGIN_FT_CURV_THRESHOLD);
01575     // load parameters
01576     const long templWidth = cfg->Read(wxT("/Finetune/TemplateSize"), HUGIN_FT_TEMPLATE_SIZE);
01577     const long sWidth = templWidth + cfg->Read(wxT("/Finetune/LocalSearchWidth"), HUGIN_FT_LOCAL_SEARCH_WIDTH);
01578 
01579     {
01580         ProgressReporterDialog progress(unoptimized.size(), _("Fine-tuning all points"), _("Fine-tuning"), wxGetActiveWindow());
01581 
01582     ImageCache & imgCache = ImageCache::getInstance();
01583 
01584     // do not process the control points in random order,
01585     // but walk from image to image, to reduce image reloading
01586     // in low mem situations.
01587     for (unsigned int imgNr = 0 ; imgNr < pano.getNrOfImages(); imgNr++) {
01588         std::set<unsigned int>::iterator it=unoptimized.begin();
01589 
01590         imgCache.softFlush();
01591 
01592         while (it != unoptimized.end()) {
01593             if (cps[*it].image1Nr == imgNr || cps[*it].image2Nr == imgNr) {
01594                 if (!progress.updateDisplayValue())
01595                 {
01596                     return;
01597                 };
01598                 if (cps[*it].mode == HuginBase::ControlPoint::X_Y) {
01599                     // finetune only normal points
01600                     DEBUG_DEBUG("fine tuning point: " << *it);
01601                     wxImage wxSearchImg;
01602                     ImageCache::ImageCacheRGB8Ptr searchImg = imgCache.getImage(
01603                         pano.getImage(cps[*it].image2Nr).getFilename())->get8BitImage();
01604 
01605                     ImageCache::ImageCacheRGB8Ptr templImg = imgCache.getImage(
01606                         pano.getImage(cps[*it].image1Nr).getFilename())->get8BitImage();
01607 
01608                     vigra_ext::CorrelationResult res;
01609                     vigra::Diff2D roundP1(hugin_utils::roundi(cps[*it].x1), hugin_utils::roundi(cps[*it].y1));
01610                     vigra::Diff2D roundP2(hugin_utils::roundi(cps[*it].x2), hugin_utils::roundi(cps[*it].y2));
01611 
01612                     res = PointFineTuneProjectionAware(pano.getImage(cps[*it].image1Nr), *templImg, roundP1, templWidth,
01613                         pano.getImage(cps[*it].image2Nr), *searchImg, roundP2, sWidth);
01614 
01615                     // invert curvature. we always assume its a maxima, the curvature there is negative
01616                     // however, we allow the user to specify a positive threshold, so we need to
01617                     // invert it
01618                     res.curv.x = - res.curv.x;
01619                     res.curv.y = - res.curv.y;
01620 
01621                     if (res.maxi < corrThresh || res.curv.x < curvThresh || res.curv.y < curvThresh ||
01622                         res.maxpos.x < 0 || res.maxpos.y < 0 || res.corrPos.x < 0 || res.corrPos.y < 0)
01623                     {
01624                         // Bad correlation result.
01625                         nBad++;
01626                         if (res.maxi >= corrThresh) {
01627                             cps[*it].error = 0;
01628                         }
01629                         cps[*it].error = res.maxi;
01630                         DEBUG_DEBUG("low correlation: " << res.maxi << " curv: " << res.curv);
01631                     } else {
01632                         nGood++;
01633                         // only update if a good correlation was found
01634                         cps[*it].x1 = res.corrPos.x;
01635                         cps[*it].y1 = res.corrPos.y;
01636                         cps[*it].x2 = res.maxpos.x;
01637                         cps[*it].y2 = res.maxpos.y;
01638                         cps[*it].error = res.maxi;
01639                     }
01640                 }
01641                 unsigned int rm = *it;
01642                 ++it;
01643                 unoptimized.erase(rm);
01644             } else {
01645                 ++it;
01646             }
01647         }
01648     }
01649     }
01650     wxString result;
01651     result.Printf(_("%d points fine-tuned, %d points not updated due to low correlation\n\nHint: The errors of the fine-tuned points have been set to the correlation coefficient\nProblematic points can be spotted (just after fine-tune, before optimizing)\nby an error <= %.3f.\nThe error of points without a well defined peak (typically in regions with uniform color)\nwill be set to 0\n\nUse the Control Point list (F3) to see all points of the current project\n"),
01652                   nGood, nBad, corrThresh);
01653     wxMessageBox(result, _("Fine-tune result"), wxOK);
01654     // set newly optimized points
01655     PanoCommand::GlobalCmdHist::getInstance().addCommand(
01656         new PanoCommand::UpdateCPsCmd(pano, cps, false)
01657         );
01658 }
01659 
01660 void MainFrame::OnRemoveCPinMasks(wxCommandEvent & e)
01661 {
01662     if(pano.getCtrlPoints().size()<2)
01663         return;
01664     HuginBase::UIntSet cps=getCPinMasks(pano);
01665     if(cps.size()>0)
01666     {
01667         PanoCommand::GlobalCmdHist::getInstance().addCommand(
01668                     new PanoCommand::RemoveCtrlPointsCmd(pano,cps)
01669                     );
01670         wxMessageBox(wxString::Format(_("Removed %lu control points"), static_cast<unsigned long>(cps.size())),
01671                    _("Removing control points in masks"),wxOK|wxICON_INFORMATION);
01672     };
01673 }
01674 
01675 #ifdef HUGIN_HSI
01676 void MainFrame::OnPythonScript(wxCommandEvent & e)
01677 {
01678     wxString fname;
01679     wxFileDialog dlg(wxGetActiveWindow(),
01680             _("Select python script"),
01681             wxConfigBase::Get()->Read(wxT("/lensPath"),wxT("")), wxT(""),
01682             _("Python script (*.py)|*.py|All files (*.*)|*.*"),
01683             wxFD_OPEN, wxDefaultPosition);
01684     dlg.SetDirectory(wxConfigBase::Get()->Read(wxT("/pythonScriptPath"),wxT("")));
01685 
01686     if (dlg.ShowModal() == wxID_OK)
01687     {
01688         wxString filename = dlg.GetPath();
01689         wxConfig::Get()->Write(wxT("/pythonScriptPath"), dlg.GetDirectory());
01690         std::string scriptfile((const char *)filename.mb_str(HUGIN_CONV_FILENAME));
01691         PanoCommand::GlobalCmdHist::getInstance().addCommand(
01692             new PanoCommand::PythonScriptPanoCmd(pano,scriptfile)
01693             );
01694     }
01695 }
01696 
01697 void MainFrame::OnPlugin(wxCommandEvent & e)
01698 {
01699     wxFileName file=m_plugins[e.GetId()];
01700     if(file.FileExists())
01701     {
01702         std::string scriptfile((const char *)file.GetFullPath().mb_str(HUGIN_CONV_FILENAME));
01703         PanoCommand::GlobalCmdHist::getInstance().addCommand(
01704                                  new PanoCommand::PythonScriptPanoCmd(pano,scriptfile)
01705                                  );
01706     }
01707     else
01708     {
01709         wxMessageBox(wxString::Format(wxT("Python-Script %s not found.\nStopping processing."),file.GetFullPath().c_str()),_("Warning"),wxOK|wxICON_INFORMATION);
01710     };
01711 }
01712 
01713 #endif
01714 
01715 void MainFrame::OnUndo(wxCommandEvent & e)
01716 {
01717     DEBUG_TRACE("OnUndo");
01718     if (PanoCommand::GlobalCmdHist::getInstance().canUndo())
01719     {
01720         PanoCommand::GlobalCmdHist::getInstance().undo();
01721     }
01722     else
01723     {
01724         wxBell();
01725     };
01726 }
01727 
01728 void MainFrame::OnRedo(wxCommandEvent & e)
01729 {
01730     DEBUG_TRACE("OnRedo");
01731     if (PanoCommand::GlobalCmdHist::getInstance().canRedo())
01732     {
01733         PanoCommand::GlobalCmdHist::getInstance().redo();
01734     };
01735 }
01736 
01737 void MainFrame::ShowCtrlPoint(unsigned int cpNr)
01738 {
01739     DEBUG_DEBUG("Showing control point " << cpNr);
01740     m_notebook->SetSelection(2);
01741     cpe->ShowControlPoint(cpNr);
01742 }
01743 
01744 void MainFrame::ShowCtrlPointEditor(unsigned int img1, unsigned int img2)
01745 {
01746     if(!IsShown())
01747     {
01748         Show();
01749         Raise();
01750     };
01751     m_notebook->SetSelection(2);
01752     cpe->setLeftImage(img1);
01753     cpe->setRightImage(img2);
01754 }
01755 
01756 void MainFrame::ShowMaskEditor(size_t imgNr)
01757 {
01758     if(!IsShown())
01759     {
01760         Show();
01761         Raise();
01762     };
01763     m_notebook->SetSelection(1);
01764     mask_panel->setImage(imgNr, true);
01765 };
01766 
01767 void MainFrame::ShowStitcherTab()
01768 {
01770     if(m_show_opt_panel && m_show_opt_photo_panel)
01771     {
01772         m_notebook->SetSelection(5);
01773     }
01774     else
01775     {
01776         if(m_show_opt_panel || m_show_opt_photo_panel)
01777         {
01778             m_notebook->SetSelection(4);
01779         }
01780         else
01781         {
01782             m_notebook->SetSelection(3);
01783         };
01784     };
01785 }
01786 
01788 void MainFrame::updateProgressDisplay()
01789 {
01790     wxString msg;
01791     if (!m_message.empty())
01792     {
01793         msg = wxGetTranslation(wxString(m_message.c_str(), wxConvLocal));
01794         if (!m_filename.empty())
01795         {
01796             msg.Append(wxT(" "));
01797             msg.Append(wxString(ProgressDisplay::m_filename.c_str(), HUGIN_CONV_FILENAME));
01798         };
01799     };
01800     GetStatusBar()->SetStatusText(msg, 0);
01801 
01802 #ifdef __WXMSW__
01803     UpdateWindow(NULL);
01804 #endif
01805 }
01806 
01807 void MainFrame::enableTools(bool option)
01808 {
01809     wxToolBar* theToolBar = GetToolBar();
01810     theToolBar->EnableTool(XRCID("action_optimize"), option);
01811     theToolBar->EnableTool(XRCID("ID_SHOW_PREVIEW_FRAME"), option);
01812     //theToolBar->EnableTool(XRCID("ID_SHOW_GL_PREVIEW_FRAME"), option);
01813     wxMenuBar* theMenuBar = GetMenuBar();
01814     theMenuBar->Enable(XRCID("action_optimize"), option);
01815     theMenuBar->Enable(XRCID("action_finetune_all_cp"), option);
01816     theMenuBar->Enable(XRCID("action_remove_cp_in_masks"), option);
01817     theMenuBar->Enable(XRCID("ID_SHOW_PREVIEW_FRAME"), option);
01818     theMenuBar->Enable(XRCID("action_stitch"), option);
01819     theMenuBar->Enable(XRCID("action_stitch_userdefined"), option);
01820     m_menu_file_advanced->Enable(XRCID("action_import_papywizard"), option);
01821     //theMenuBar->Enable(XRCID("ID_SHOW_GL_PREVIEW_FRAME"), option);
01822 }
01823 
01824 
01825 void MainFrame::OnSize(wxSizeEvent &e)
01826 {
01827 #ifdef DEBUG
01828     wxSize sz = this->GetSize();
01829     wxSize csz = this->GetClientSize();
01830     wxSize vsz = this->GetVirtualSize();
01831     DEBUG_TRACE(" size:" << sz.x << "," << sz.y <<
01832                 " client: "<< csz.x << "," << csz.y <<
01833                 " virtual: "<< vsz.x << "," << vsz.y);
01834 #endif
01835 
01836     Layout();
01837     e.Skip();
01838 }
01839 
01840 CPDetectorSetting& MainFrame::GetDefaultSetting()
01841 {
01842     return images_panel->GetDefaultSetting();
01843 };
01844 
01845 void MainFrame::RunCPGenerator(CPDetectorSetting &setting, const HuginBase::UIntSet& img)
01846 {
01847     images_panel->RunCPGenerator(setting, img);
01848 };
01849 
01850 void MainFrame::RunCPGenerator(const HuginBase::UIntSet& img)
01851 {
01852     images_panel->RunCPGenerator(img);
01853 };
01854 
01855 const wxString MainFrame::GetSelectedCPGenerator()
01856 {
01857     return images_panel->GetSelectedCPGenerator();
01858 };
01859 
01860 const wxString & MainFrame::GetXRCPath()
01861 {
01862      return huginApp::Get()->GetXRCPath();
01863 };
01864 
01865 const wxString & MainFrame::GetDataPath()
01866 {
01867     return wxGetApp().GetDataPath();
01868 };
01869 
01871 MainFrame * MainFrame::Get()
01872 {
01873     if (m_this) {
01874         return m_this;
01875     } else {
01876         DEBUG_FATAL("MainFrame not yet created");
01877         DEBUG_ASSERT(m_this);
01878         return 0;
01879     }
01880 }
01881 
01882 wxString MainFrame::getProjectName()
01883 {
01884     return m_filename;
01885 }
01886 
01887 void MainFrame::OnMRUFiles(wxCommandEvent &e)
01888 {
01889     size_t index = e.GetId() - wxID_FILE1;
01890     wxString f(m_mruFiles.GetHistoryFile(index));
01891     if (!f.empty())
01892     {
01893         wxFileName fn(f);
01894         if(fn.FileExists())
01895             LoadProjectFile(f);
01896         else
01897         {
01898             m_mruFiles.RemoveFileFromHistory(index);
01899             wxMessageBox(wxString::Format(_("File \"%s\" not found.\nMaybe file was renamed, moved or deleted."),f.c_str()),
01900                 _("Error!"),wxOK | wxICON_INFORMATION );
01901         };
01902     };
01903 }
01904 
01905 void MainFrame::OnFullScreen(wxCommandEvent & e)
01906 {
01907     ShowFullScreen(!IsFullScreen(), wxFULLSCREEN_NOBORDER | wxFULLSCREEN_NOCAPTION);
01908 #ifdef __WXGTK__
01909     //workaround a wxGTK bug that also the toolbar is hidden, but not requested to hide
01910     GetToolBar()->Show(true);
01911 #endif
01912 };
01913 
01914 struct celeste::svm_model* MainFrame::GetSVMModel()
01915 {
01916     if(svmModel==NULL)
01917     {
01918         // determine file name of SVM model file
01919         // get XRC path from application
01920         wxString wxstrModelFileName = huginApp::Get()->GetDataPath() + wxT(HUGIN_CELESTE_MODEL);
01921         // convert wxString to string
01922         std::string strModelFileName(wxstrModelFileName.mb_str(HUGIN_CONV_FILENAME));
01923 
01924         // SVM model file
01925         if (! wxFile::Exists(wxstrModelFileName) ) {
01926             wxMessageBox(wxString::Format(_("Celeste model expected in %s not found, Hugin needs to be properly installed."),wxstrModelFileName.c_str()), _("Fatal Error"));
01927             return NULL;
01928         }
01929         if(!celeste::loadSVMmodel(svmModel,strModelFileName))
01930         {
01931             wxMessageBox(wxString::Format(_("Could not load Celeste model file %s"),wxstrModelFileName.c_str()),_("Error"));
01932             svmModel=NULL;
01933         };
01934     }
01935     return svmModel;
01936 };
01937 
01938 GLPreviewFrame * MainFrame::getGLPreview()
01939 {
01940     return gl_preview_frame;
01941 }
01942 
01943 void MainFrame::SetGuiLevel(GuiLevel newLevel)
01944 {
01945     if(gl_preview_frame==NULL && newLevel==GUI_SIMPLE)
01946     {
01947         SetGuiLevel(GUI_ADVANCED);
01948         return;
01949     };
01950     if(m_guiLevel==GUI_EXPERT && newLevel!=GUI_EXPERT && pano.getOptimizerSwitch()==0)
01951     {
01952         bool needsUpdateOptimizerVar=false;
01953         HuginBase::OptimizeVector optVec = pano.getOptimizeVector();
01954         for(size_t i=0; i<optVec.size(); i++)
01955         {
01956             bool hasTrX=optVec[i].erase("TrX")>0;
01957             bool hasTrY=optVec[i].erase("TrY")>0;
01958             bool hasTrZ=optVec[i].erase("TrZ")>0;
01959             bool hasTpy=optVec[i].erase("Tpy")>0;
01960             bool hasTpp=optVec[i].erase("Tpp")>0;
01961             bool hasg=optVec[i].erase("g")>0;
01962             bool hast=optVec[i].erase("t")>0;
01963             needsUpdateOptimizerVar=needsUpdateOptimizerVar || hasTrX || hasTrY || hasTrZ || hasTpy || hasTpp || hasg || hast;
01964         };
01965         if(needsUpdateOptimizerVar)
01966         {
01967             PanoCommand::GlobalCmdHist::getInstance().addCommand(
01968                 new PanoCommand::UpdateOptimizeVectorCmd(pano, optVec)
01969             );
01970         };
01971     };
01972     if(newLevel==GUI_SIMPLE && pano.getPhotometricOptimizerSwitch()==0)
01973     {
01974         bool needsUpdateOptimizerVar=false;
01975         HuginBase::OptimizeVector optVec = pano.getOptimizeVector();
01976         for(size_t i=0; i<optVec.size(); i++)
01977         {
01978             bool hasVx=optVec[i].erase("Vx")>0;
01979             bool hasVy=optVec[i].erase("Vy")>0;
01980             needsUpdateOptimizerVar=needsUpdateOptimizerVar || hasVx || hasVy;
01981         };
01982         if(needsUpdateOptimizerVar)
01983         {
01984             PanoCommand::GlobalCmdHist::getInstance().addCommand(
01985                 new PanoCommand::UpdateOptimizeVectorCmd(pano, optVec)
01986             );
01987         };
01988     };
01989     m_guiLevel=newLevel;
01990     images_panel->SetGuiLevel(m_guiLevel);
01991     opt_panel->SetGuiLevel(m_guiLevel);
01992     opt_photo_panel->SetGuiLevel(m_guiLevel);
01993     pano_panel->SetGuiLevel(m_guiLevel);
01994     if(gl_preview_frame)
01995     {
01996         gl_preview_frame->SetGuiLevel(m_guiLevel);
01997     };
01998     switch(m_guiLevel)
01999     {
02000         case GUI_SIMPLE:
02001             GetMenuBar()->FindItem(XRCID("action_gui_simple"))->Check();
02002             break;
02003         case GUI_ADVANCED:
02004             GetMenuBar()->FindItem(XRCID("action_gui_advanced"))->Check();
02005             break;
02006         case GUI_EXPERT:
02007             GetMenuBar()->FindItem(XRCID("action_gui_expert"))->Check();
02008             break;
02009     };
02010     if(m_guiLevel==GUI_SIMPLE)
02011     {
02012         if(!gl_preview_frame->IsShown())
02013         {
02014             wxCommandEvent dummy;
02015             OnToggleGLPreviewFrame(dummy);
02016         };
02017         wxGetApp().SetTopWindow(gl_preview_frame);
02018         GetMenuBar()->Remove(0);
02019         GetMenuBar()->Insert(0, m_menu_file_simple, _("&File"));
02020         if(m_filename.IsEmpty())
02021         {
02022             gl_preview_frame->SetTitle(_("Hugin - Panorama Stitcher"));
02023             SetTitle(_("Panorama editor"));
02024         }
02025         else
02026         {
02027             wxFileName scriptName = m_filename;
02028             gl_preview_frame->SetTitle(scriptName.GetName() + wxT(".") + scriptName.GetExt() + wxT(" - ") + _("Hugin - Panorama Stitcher"));
02029             SetTitle(scriptName.GetName() + wxT(".") + scriptName.GetExt() + wxT(" - ") + _("Panorama editor"));
02030         };
02031         Hide();
02032     }
02033     else
02034     {
02035         wxGetApp().SetTopWindow(this);
02036         GetMenuBar()->Remove(0);
02037         GetMenuBar()->Insert(0, m_menu_file_advanced, _("&File"));
02038         if(m_filename.IsEmpty())
02039         {
02040             SetTitle(_("Hugin - Panorama Stitcher"));
02041         }
02042         else
02043         {
02044             wxFileName scriptName = m_filename;
02045             SetTitle(scriptName.GetName() + wxT(".") + scriptName.GetExt() + wxT(" - ") + _("Hugin - Panorama Stitcher"));
02046         };
02047         if(!IsShown())
02048         {
02049             Show();
02050         };
02051     };
02052 };
02053 
02054 void MainFrame::OnSetGuiSimple(wxCommandEvent & e)
02055 {
02056     GuiLevel reqGuiLevel=GetMinimumGuiLevel(pano);
02057     if(reqGuiLevel<=GUI_SIMPLE)
02058     {
02059         SetGuiLevel(GUI_SIMPLE);
02060     }
02061     else
02062     {
02063         if(reqGuiLevel==GUI_ADVANCED)
02064         {
02065             wxMessageBox(_("Can't switch to simple interface. The project is using stacks and/or vignetting center shift.\nThese features are not supported in simple interface."),
02066 #ifdef __WXMSW__
02067                          wxT("Hugin"),
02068 #else
02069                          wxT(""),
02070 #endif
02071                          wxOK | wxICON_INFORMATION);
02072         }
02073         else
02074         {
02075             wxMessageBox(_("Can't switch to simple interface. The project is using translation or shear parameters.\nThese parameters are not supported in simple interface."),
02076 #ifdef __WXMSW__
02077                          wxT("Hugin"),
02078 #else
02079                          wxT(""),
02080 #endif
02081                          wxOK | wxICON_INFORMATION);
02082         }
02083         SetGuiLevel(m_guiLevel);
02084     };
02085 };
02086 
02087 void MainFrame::OnSetGuiAdvanced(wxCommandEvent & e)
02088 {
02089     GuiLevel reqGuiLevel=GetMinimumGuiLevel(pano);
02090     if(reqGuiLevel<=GUI_ADVANCED)
02091     {
02092         SetGuiLevel(GUI_ADVANCED);
02093     }
02094     else
02095     {
02096         wxMessageBox(_("Can't switch to advanced interface. The project is using translation or shear parameters.\nThese parameters are not supported in advanced interface."),
02097 #ifdef __WXMSW__
02098                      wxT("Hugin"),
02099 #else
02100                      wxT(""),
02101 #endif
02102                      wxOK | wxICON_INFORMATION);
02103         SetGuiLevel(GUI_EXPERT);
02104     };
02105 };
02106 
02107 void MainFrame::OnSetGuiExpert(wxCommandEvent & e)
02108 {
02109     SetGuiLevel(GUI_EXPERT);
02110 };
02111 
02112 void MainFrame::DisableOpenGLTools()
02113 {
02114     GetMenuBar()->Enable(XRCID("ID_SHOW_GL_PREVIEW_FRAME"), false);
02115     GetMenuBar()->Enable(XRCID("action_gui_simple"), false);
02116     GetToolBar()->EnableTool(XRCID("ID_SHOW_GL_PREVIEW_FRAME"), false); 
02117 };
02118 
02119 void MainFrame::RunAssistant(wxWindow* mainWin)
02120 {
02121     if (pano.getNrOfImages() < 2)
02122     {
02123         wxMessageBox(_("At least two images are required.\nPlease add more images."),_("Error"), wxOK, mainWin);
02124         return;
02125     }
02126 
02127     //save project into temp directory
02128     wxString tempDir= wxConfig::Get()->Read(wxT("tempDir"),wxT(""));
02129     if(!tempDir.IsEmpty())
02130     {
02131         if(tempDir.Last()!=wxFileName::GetPathSeparator())
02132         {
02133             tempDir.Append(wxFileName::GetPathSeparator());
02134         }
02135     };
02136     wxFileName scriptFileName(wxFileName::CreateTempFileName(tempDir+wxT("ha")));
02137     std::ofstream script(scriptFileName.GetFullPath().mb_str(HUGIN_CONV_FILENAME));
02138     script.exceptions ( std::ofstream::eofbit | std::ofstream::failbit | std::ofstream::badbit );
02139     HuginBase::UIntSet all;
02140     fill_set(all, 0, pano.getNrOfImages()-1);
02141     pano.printPanoramaScript(script, pano.getOptimizeVector(), pano.getOptions(), all, false);
02142     script.close();
02143 
02144     // get assistant queue
02145     const wxFileName exePath(wxStandardPaths::Get().GetExecutablePath());
02146     HuginQueue::CommandQueue* commands = HuginQueue::GetAssistantCommandQueue(pano, exePath.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR), scriptFileName.GetFullPath());
02147     //execute queue
02148     int ret = MyExecuteCommandQueue(commands, mainWin, _("Running assistant"));
02149 
02150     //read back panofile
02151     PanoCommand::GlobalCmdHist::getInstance().addCommand(new PanoCommand::wxLoadPTProjectCmd(pano,
02152         (const char *)scriptFileName.GetFullPath().mb_str(HUGIN_CONV_FILENAME), 
02153         (const char *)scriptFileName.GetPath(wxPATH_NATIVE | wxPATH_GET_SEPARATOR).mb_str(HUGIN_CONV_FILENAME), 
02154         ret==0, false));
02155 
02156     //delete temporary files
02157     wxRemoveFile(scriptFileName.GetFullPath());
02158     //if return value is non-zero, an error occurred in the assistant
02159     if(ret!=0)
02160     {
02161         //check for unconnected images
02162         HuginGraph::ImageGraph graph(pano);
02163         const HuginGraph::ImageGraph::Components comps = graph.GetComponents();
02164         if(comps.size() > 1)
02165         {
02166             // switch to images panel.
02167             unsigned i1 = *(comps[0].rbegin());
02168             unsigned i2 = *(comps[1].begin());
02169             ShowCtrlPointEditor( i1, i2);
02170             // display message box with 
02171             wxMessageBox(wxString::Format(_("Warning %d unconnected image groups found:"), comps.size()) + Components2Str(comps) + wxT("\n")
02172                 + _("Please create control points between unconnected images using the Control Points tab in the panorama editor.\n\nAfter adding the points, press the \"Align\" button again"),_("Error"), wxOK , mainWin);
02173             return;
02174         };
02175         wxMessageBox(_("The assistant did not complete successfully. Please check the resulting project file."),
02176                      _("Warning"),wxOK | wxICON_INFORMATION, mainWin); 
02177     };
02178 };
02179 
02180 void MainFrame::OnRunAssistant(wxCommandEvent & e)
02181 {
02182     RunAssistant(this);
02183 };
02184 
02185 void MainFrame::OnSendToAssistantQueue(wxCommandEvent &e)
02186 {
02187     wxCommandEvent dummy;
02188     OnSaveProject(dummy);
02189     wxString projectFile = getProjectName();
02190     if(wxFileName::FileExists(projectFile))
02191     {
02192 #if defined __WXMAC__ && defined MAC_SELF_CONTAINED_BUNDLE
02193         // Original patch for OSX by Charlie Reiman dd. 18 June 2011
02194         // Slightly modified by HvdW. Errors in here are mine, not Charlie's. 
02195         FSRef appRef;
02196         FSRef actuallyLaunched;
02197         OSStatus err;
02198         FSRef documentArray[1]; // Don't really need an array if we only have 1 item
02199         LSLaunchFSRefSpec launchSpec;
02200         Boolean  isDir;
02201 
02202         err = LSFindApplicationForInfo(kLSUnknownCreator,
02203                                        CFSTR("net.sourceforge.hugin.PTBatcherGUI"),
02204                                        NULL,
02205                                        &appRef,
02206                                        NULL);
02207         if (err != noErr)
02208         {
02209             // error, can't find PTBatcherGUI
02210             wxMessageBox(wxString::Format(_("External program %s not found in the bundle, reverting to system path"), wxT("open")), _("Error"));
02211             // Possibly a silly attempt otherwise the previous would have worked as well, but just try it.
02212             wxExecute(_T("open -b net.sourceforge.hugin.PTBatcherGUI ")+hugin_utils::wxQuoteFilename(projectFile));
02213             return;
02214         }
02215 
02216         wxCharBuffer projectFilebuffer=projectFile.ToUTF8();
02217         // Point to document
02218         err = FSPathMakeRef((unsigned char*) projectFilebuffer.data(), &documentArray[0], &isDir);
02219         if (err != noErr || isDir)
02220         {
02221             // Something went wrong.
02222             wxMessageBox(wxString::Format(_("Project file not found"), wxT("open")), _("Error"));
02223             return;
02224         }
02225         launchSpec.appRef = &appRef;
02226         launchSpec.numDocs = sizeof(documentArray)/sizeof(documentArray[0]);
02227         launchSpec.itemRefs = documentArray;
02228         launchSpec.passThruParams = NULL;
02229         launchSpec.launchFlags = kLSLaunchDontAddToRecents + kLSLaunchDontSwitch;
02230         launchSpec.asyncRefCon = NULL;
02231 
02232         err = LSOpenFromRefSpec(&launchSpec, &actuallyLaunched);
02233         if (err != noErr && err != kLSLaunchInProgressErr)
02234         {  
02235             // Should be ok if it's in progress... I think. 
02236             // Launch failed.
02237             wxMessageBox(wxString::Format(_("Can't launch PTBatcherGui"), wxT("open")), _("Error"));
02238             return;
02239         }
02240 
02241         // Should verify that actuallyLaunched and appRef are the same.
02242         if (FSCompareFSRefs(&appRef, &actuallyLaunched) != noErr)
02243         {
02244             // error, lauched the wrong thing.
02245             wxMessageBox(wxString::Format(_("Launched incorrect programme"), wxT("open")), _("Error"));
02246             return;
02247         }
02248 #else
02249         const wxFileName exePath(wxStandardPaths::Get().GetExecutablePath());
02250         wxExecute(exePath.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR) + wxT("PTBatcherGUI -a ")+hugin_utils::wxQuoteFilename(projectFile));
02251 #endif
02252     }
02253 };
02254 
02255 wxString MainFrame::GetCurrentOptimizerString()
02256 {
02257     return images_panel->GetCurrentOptimizerString();
02258 };
02259 
02260 MainFrame * MainFrame::m_this = 0;

Generated on 27 May 2016 for Hugintrunk by  doxygen 1.4.7