MainFrame.cpp

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

Generated on Fri Apr 25 01:25:33 2014 for Hugintrunk by  doxygen 1.3.9.1