MainFrame.cpp

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

Generated on 29 Sep 2016 for Hugintrunk by  doxygen 1.4.7