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 
00061 #include "base_wx/MyProgressDialog.h"
00062 #include "base_wx/RunStitchPanel.h"
00063 #include "base_wx/wxImageCache.h"
00064 #include "base_wx/PTWXDlg.h"
00065 #include "base_wx/MyExternalCmdExecDialog.h"
00066 #include "base_wx/AssistantExecutor.h"
00067 #include "algorithms/optimizer/ImageGraph.h"
00068 
00069 #include "base_wx/huginConfig.h"
00070 #include "hugin/AboutDialog.h"
00071 
00072 #if HUGIN_HSI
00073 #include "PluginItems.h"
00074 #endif
00075 
00076 #ifdef __MINGW32__
00077 // fixes for mingw compilation...
00078 #undef FindWindow
00079 #endif
00080 
00085 class HuginSplashScreen : public wxFrame
00086 {
00087 public:
00088     HuginSplashScreen() {};
00089     HuginSplashScreen(wxWindow* parent, wxBitmap bitmap) : 
00090         wxFrame(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxFRAME_TOOL_WINDOW | wxFRAME_NO_TASKBAR | wxSTAY_ON_TOP)
00091     {
00092         SetExtraStyle(GetExtraStyle() | wxWS_EX_TRANSIENT);
00093         wxSizer* topSizer=new wxBoxSizer(wxVERTICAL);
00094         wxStaticBitmap* staticBitmap=new wxStaticBitmap(this,wxID_ANY,bitmap);
00095         topSizer->Add(staticBitmap,1,wxEXPAND);
00096         SetSizerAndFit(topSizer);
00097         SetClientSize(bitmap.GetWidth(), bitmap.GetHeight());
00098         CenterOnScreen();
00099         Show(true);
00100         SetFocus();
00101 #if defined(__WXMSW__) || defined(__WXMAC__)
00102         Update();
00103 #elif defined(__WXGTK20__)
00104         //do nothing
00105 #else
00106         wxYieldIfNeeded();
00107 #endif
00108     };
00109     DECLARE_DYNAMIC_CLASS(HuginSplashScreen)
00110     DECLARE_EVENT_TABLE()
00111 };
00112 
00113 IMPLEMENT_DYNAMIC_CLASS(HuginSplashScreen, wxFrame)
00114 BEGIN_EVENT_TABLE(HuginSplashScreen, wxFrame)
00115 END_EVENT_TABLE()
00116 
00118 bool PanoDropTarget::OnDropFiles(wxCoord x, wxCoord y, const wxArrayString& filenames)
00119 {
00120     DEBUG_TRACE("OnDropFiles");
00121     MainFrame * mf = MainFrame::Get();
00122     if (!mf) return false;
00123 
00124     if (!m_imageOnly && filenames.GetCount() == 1) {
00125         wxFileName file(filenames[0]);
00126         if (file.GetExt().CmpNoCase(wxT("pto")) == 0 ||
00127             file.GetExt().CmpNoCase(wxT("ptp")) == 0 ||
00128             file.GetExt().CmpNoCase(wxT("pts")) == 0 )
00129         {
00130             // load project
00131             if (mf->CloseProject(true)) {
00132                 mf->LoadProjectFile(file.GetFullPath());
00133                 // remove old images from cache
00134                 ImageCache::getInstance().flush();
00135             }
00136             return true;
00137         }
00138     }
00139 
00140     // try to add as images
00141     std::vector<std::string> filesv;
00142     wxArrayString invalidFiles;
00143     for (unsigned int i=0; i< filenames.GetCount(); i++) {
00144         wxFileName file(filenames[i]);
00145 
00146         if (file.GetExt().CmpNoCase(wxT("jpg")) == 0 ||
00147             file.GetExt().CmpNoCase(wxT("jpeg")) == 0 ||
00148             file.GetExt().CmpNoCase(wxT("tif")) == 0 ||
00149             file.GetExt().CmpNoCase(wxT("tiff")) == 0 ||
00150             file.GetExt().CmpNoCase(wxT("png")) == 0 ||
00151             file.GetExt().CmpNoCase(wxT("bmp")) == 0 ||
00152             file.GetExt().CmpNoCase(wxT("gif")) == 0 ||
00153             file.GetExt().CmpNoCase(wxT("pnm")) == 0 ||
00154             file.GetExt().CmpNoCase(wxT("sun")) == 0 ||
00155             file.GetExt().CmpNoCase(wxT("hdr")) == 0 ||
00156             file.GetExt().CmpNoCase(wxT("viff")) == 0 )
00157         {
00158             if(containsInvalidCharacters(filenames[i]))
00159             {
00160                 invalidFiles.Add(file.GetFullPath());
00161             }
00162             else
00163             {
00164                 filesv.push_back((const char *)filenames[i].mb_str(HUGIN_CONV_FILENAME));
00165             };
00166         }
00167     }
00168     // we got some images to add.
00169     if (filesv.size() > 0)
00170     {
00171         // use a Command to ensure proper undo and updating of GUI parts
00172         wxBusyCursor();
00173         if(pano.getNrOfCtrlPoints()>0)
00174         {
00175             PanoCommand::GlobalCmdHist::getInstance().addCommand(new PanoCommand::wxAddImagesCmd(pano, filesv));
00176         }
00177         else
00178         {
00179             std::vector<PanoCommand::PanoCommand*> cmds;
00180             cmds.push_back(new PanoCommand::wxAddImagesCmd(pano, filesv));
00181             cmds.push_back(new PanoCommand::DistributeImagesCmd(pano));
00182             cmds.push_back(new PanoCommand::CenterPanoCmd(pano));
00183             PanoCommand::GlobalCmdHist::getInstance().addCommand(new PanoCommand::CombinedPanoCommand(pano, cmds));
00184         };
00185 
00186     }
00187     if(invalidFiles.size()>0)
00188     {
00189         ShowFilenameWarning(mf, invalidFiles);
00190     }
00191 
00192     return true;
00193 }
00194 
00195 
00196 
00197 // event table. this frame will recieve mostly global commands.
00198 BEGIN_EVENT_TABLE(MainFrame, wxFrame)
00199     EVT_MENU(XRCID("action_new_project"),  MainFrame::OnNewProject)
00200     EVT_MENU(XRCID("action_load_project"),  MainFrame::OnLoadProject)
00201     EVT_MENU(XRCID("action_save_project"),  MainFrame::OnSaveProject)
00202     EVT_MENU(XRCID("action_save_as_project"),  MainFrame::OnSaveProjectAs)
00203     EVT_MENU(XRCID("action_save_as_ptstitcher"),  MainFrame::OnSavePTStitcherAs)
00204     EVT_MENU(XRCID("action_open_batch_processor"),  MainFrame::OnOpenPTBatcher)
00205     EVT_MENU(XRCID("action_import_project"), MainFrame::OnMergeProject)
00206     EVT_MENU(XRCID("action_apply_template"),  MainFrame::OnApplyTemplate)
00207     EVT_MENU(XRCID("action_exit_hugin"),  MainFrame::OnUserQuit)
00208     EVT_MENU_RANGE(wxID_FILE1, wxID_FILE9, MainFrame::OnMRUFiles)
00209     EVT_MENU(XRCID("action_show_about"),  MainFrame::OnAbout)
00210     EVT_MENU(XRCID("action_show_help"),  MainFrame::OnHelp)
00211     EVT_MENU(XRCID("action_show_tip"),  MainFrame::OnTipOfDay)
00212     EVT_MENU(XRCID("action_show_shortcuts"),  MainFrame::OnKeyboardHelp)
00213     EVT_MENU(XRCID("action_show_faq"),  MainFrame::OnFAQ)
00214     EVT_MENU(XRCID("action_show_donate"),  MainFrame::OnShowDonate)
00215     EVT_MENU(XRCID("action_show_prefs"), MainFrame::OnShowPrefs)
00216     EVT_MENU(XRCID("action_assistant"), MainFrame::OnRunAssistant)
00217     EVT_MENU(XRCID("action_batch_assistant"), MainFrame::OnSendToAssistantQueue)
00218     EVT_MENU(XRCID("action_gui_simple"), MainFrame::OnSetGuiSimple)
00219     EVT_MENU(XRCID("action_gui_advanced"), MainFrame::OnSetGuiAdvanced)
00220     EVT_MENU(XRCID("action_gui_expert"), MainFrame::OnSetGuiExpert)
00221 #ifdef HUGIN_HSI
00222     EVT_MENU(XRCID("action_python_script"), MainFrame::OnPythonScript)
00223 #endif
00224     EVT_MENU(XRCID("ID_EDITUNDO"), MainFrame::OnUndo)
00225     EVT_MENU(XRCID("ID_EDITREDO"), MainFrame::OnRedo)
00226     EVT_MENU(XRCID("ID_SHOW_FULL_SCREEN"), MainFrame::OnFullScreen)
00227     EVT_MENU(XRCID("ID_SHOW_PREVIEW_FRAME"), MainFrame::OnTogglePreviewFrame)
00228     EVT_MENU(XRCID("ID_SHOW_GL_PREVIEW_FRAME"), MainFrame::OnToggleGLPreviewFrame)
00229     EVT_BUTTON(XRCID("ID_SHOW_PREVIEW_FRAME"),MainFrame::OnTogglePreviewFrame)
00230     EVT_BUTTON(XRCID("ID_SHOW_GL_PREVIEW_FRAME"), MainFrame::OnToggleGLPreviewFrame)
00231 
00232     EVT_MENU(XRCID("action_optimize"),  MainFrame::OnOptimize)
00233     EVT_BUTTON(XRCID("action_optimize"),  MainFrame::OnOptimize)
00234     EVT_MENU(XRCID("action_finetune_all_cp"), MainFrame::OnFineTuneAll)
00235 //    EVT_BUTTON(XRCID("action_finetune_all_cp"), MainFrame::OnFineTuneAll)
00236     EVT_MENU(XRCID("action_remove_cp_in_masks"), MainFrame::OnRemoveCPinMasks)
00237 
00238     EVT_MENU(XRCID("ID_CP_TABLE"), MainFrame::OnShowCPFrame)
00239     EVT_BUTTON(XRCID("ID_CP_TABLE"),MainFrame::OnShowCPFrame)
00240 
00241     EVT_MENU(XRCID("ID_SHOW_PANEL_IMAGES"), MainFrame::OnShowPanel)
00242     EVT_MENU(XRCID("ID_SHOW_PANEL_MASK"), MainFrame::OnShowPanel)
00243     EVT_MENU(XRCID("ID_SHOW_PANEL_CP_EDITOR"), MainFrame::OnShowPanel)
00244     EVT_MENU(XRCID("ID_SHOW_PANEL_OPTIMIZER"), MainFrame::OnShowPanel)
00245     EVT_MENU(XRCID("ID_SHOW_PANEL_OPTIMIZER_PHOTOMETRIC"), MainFrame::OnShowPanel)
00246     EVT_MENU(XRCID("ID_SHOW_PANEL_PANORAMA"), MainFrame::OnShowPanel)
00247     EVT_MENU(XRCID("action_stitch"), MainFrame::OnDoStitch)
00248     EVT_MENU(XRCID("action_stitch_userdefined"), MainFrame::OnUserDefinedStitch)
00249     EVT_MENU(XRCID("action_add_images"),  MainFrame::OnAddImages)
00250     EVT_BUTTON(XRCID("action_add_images"),  MainFrame::OnAddImages)
00251     EVT_MENU(XRCID("action_add_time_images"),  MainFrame::OnAddTimeImages)
00252     EVT_BUTTON(XRCID("action_add_time_images"),  MainFrame::OnAddTimeImages)
00253     EVT_CLOSE(  MainFrame::OnExit)
00254     EVT_SIZE(MainFrame::OnSize)
00255 END_EVENT_TABLE()
00256 
00257 // change this variable definition
00258 //wxTextCtrl *itemProjTextMemo;
00259 // image preview
00260 //wxBitmap *p_img = (wxBitmap *) NULL;
00261 //WX_DEFINE_ARRAY()
00262 
00263 MainFrame::MainFrame(wxWindow* parent, HuginBase::Panorama & pano)
00264     : cp_frame(0), pano(pano)
00265 {
00266     preview_frame = 0;
00267     svmModel=NULL;
00268 
00269     bool disableOpenGL=false;
00270 #if wxCHECK_VERSION(2,9,4)
00271     if(wxGetKeyState(WXK_COMMAND))
00272 #else
00273     if(wxGetKeyState(WXK_CONTROL))
00274 #endif
00275     {
00276         wxDialog dlg;
00277         wxXmlResource::Get()->LoadDialog(&dlg, NULL, wxT("disable_opengl_dlg"));
00278         long noOpenGL=wxConfigBase::Get()->Read(wxT("DisableOpenGL"), 0l);
00279         if(noOpenGL==1)
00280         {
00281             XRCCTRL(dlg, "disable_dont_ask_checkbox", wxCheckBox)->SetValue(true);
00282         };
00283         if(dlg.ShowModal()==wxID_OK)
00284         {
00285             if(XRCCTRL(dlg, "disable_dont_ask_checkbox", wxCheckBox)->IsChecked())
00286             {
00287                 wxConfigBase::Get()->Write(wxT("DisableOpenGL"), 1l);
00288             }
00289             else
00290             {
00291                 wxConfigBase::Get()->Write(wxT("DisableOpenGL"), 0l);
00292             };
00293             disableOpenGL=true;
00294         }
00295         else
00296         {
00297             wxConfigBase::Get()->Write(wxT("DisableOpenGL"), 0l);
00298         };
00299     }
00300     else
00301     {
00302         long noOpenGL=wxConfigBase::Get()->Read(wxT("DisableOpenGL"), 0l);
00303         disableOpenGL=(noOpenGL==1);
00304     };
00305 
00306     wxBitmap bitmap;
00307     HuginSplashScreen* splash = 0;
00308     wxYield();
00309 
00310     if (bitmap.LoadFile(huginApp::Get()->GetXRCPath() + wxT("data/splash.png"), wxBITMAP_TYPE_PNG))
00311     {
00312         // embed package version into string.
00313         {
00314             wxMemoryDC dc;
00315             dc.SelectObject(bitmap);
00316 #ifdef __WXMAC__
00317             wxFont font(9, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
00318 #else
00319             wxFont font(8, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
00320 #endif
00321             dc.SetFont(font);
00322             dc.SetTextForeground(*wxBLACK);
00323             dc.SetTextBackground(*wxWHITE);
00324             int tw, th;
00325             wxString version;
00326             version.Printf(_("Version %s"), wxString(hugin_utils::GetHuginVersion().c_str(), wxConvLocal).c_str());
00327             dc.GetTextExtent(version, &tw, &th);
00328             // place text on bitmap.
00329             dc.DrawText(version, bitmap.GetWidth() - tw - 3, bitmap.GetHeight() - th - 3);
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 
00362 #ifdef HUGIN_HSI
00363     wxMenuBar* menubar=GetMenuBar();
00364     // the plugin menu will be generated dynamically
00365     wxMenu *pluginMenu=new wxMenu();
00366     // search for all .py files in plugins directory
00367     wxDir dir(GetDataPath()+wxT("plugins"));
00368     if (dir.IsOpened())
00369     {
00370         wxString filename;
00371         bool cont = dir.GetFirst(&filename, wxT("*.py"), wxDIR_FILES | wxDIR_HIDDEN);
00372         PluginItems items;
00373         while (cont)
00374         {
00375             wxFileName file(dir.GetName(), filename);
00376             file.MakeAbsolute();
00377             PluginItem item(file);
00378             if (item.IsAPIValid())
00379             {
00380                 items.push_back(item);
00381             };
00382             cont = dir.GetNext(&filename);
00383         };
00384         items.sort(comparePluginItem);
00385 
00386         int pluginID = wxID_HIGHEST + 2000;
00387         for (PluginItems::const_iterator it = items.begin(); it != items.end(); ++it)
00388         {
00389             PluginItem item = *it;
00390             int categoryID = pluginMenu->FindItem(item.GetCategory());
00391             wxMenu* categoryMenu;
00392             if (categoryID == wxNOT_FOUND)
00393             {
00394                 categoryMenu = new wxMenu();
00395                 pluginMenu->AppendSubMenu(categoryMenu, item.GetCategory());
00396             }
00397             else
00398             {
00399                 categoryMenu = pluginMenu->FindItem(categoryID)->GetSubMenu();
00400             };
00401             categoryMenu->Append(pluginID, item.GetName(), item.GetDescription());
00402             m_plugins[pluginID] = item.GetFilename();
00403             Connect(pluginID, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::OnPlugin));
00404             pluginID++;
00405         };
00406         // show the new menu
00407         if (pluginMenu->GetMenuItemCount() > 0)
00408         {
00409             menubar->Insert(menubar->GetMenuCount() - 2, pluginMenu, _("&Actions"));
00410         };
00411     };
00412 #else
00413     GetMenuBar()->Enable(XRCID("action_python_script"), false);
00414 #endif
00415 
00416     // create tool bar
00417     SetToolBar(wxXmlResource::Get()->LoadToolBar(this, wxT("main_toolbar")));
00418 
00419     // Disable tools by default
00420     enableTools(false);
00421 
00422     // put an "unknown" object in an xrc file and
00423     // take as wxObject (second argument) the return value of wxXmlResource::Get
00424     // finish the images_panel
00425     DEBUG_TRACE("");
00426 
00427     // image_panel
00428     images_panel = XRCCTRL(*this, "images_panel_unknown", ImagesPanel);
00429     assert(images_panel);
00430     images_panel->Init(&pano);
00431     DEBUG_TRACE("");
00432 
00433     m_notebook = XRCCTRL((*this), "controls_notebook", wxNotebook);
00434 //    m_notebook = ((wxNotebook*) ((*this).FindWindow(XRCID("controls_notebook"))));
00435 //    m_notebook = ((wxNotebook*) (FindWindow(XRCID("controls_notebook"))));
00436     DEBUG_ASSERT(m_notebook);
00437 
00438     // the mask panel
00439     mask_panel = XRCCTRL(*this, "mask_panel_unknown", MaskEditorPanel);
00440     assert(mask_panel);
00441     mask_panel->Init(&pano);
00442 
00443     // the pano_panel
00444     DEBUG_TRACE("");
00445     pano_panel = XRCCTRL(*this, "panorama_panel_unknown", PanoPanel);
00446     assert(pano_panel);
00447     pano_panel->Init(&pano);
00448     pano_panel->panoramaChanged (pano); // initialize from pano
00449 
00450     cpe = XRCCTRL(*this, "cp_editor_panel_unknown", CPEditorPanel);
00451     assert(cpe);
00452     cpe->Init(&pano);
00453 
00454     opt_panel = XRCCTRL(*this, "optimizer_panel_unknown", OptimizePanel);
00455     assert(opt_panel);
00456     opt_panel->Init(&pano);
00457     m_show_opt_panel=true;
00458 
00459     opt_photo_panel = XRCCTRL(*this, "optimizer_photometric_panel_unknown", OptimizePhotometricPanel);
00460     assert(opt_photo_panel);
00461     opt_photo_panel->Init(&pano);
00462     m_show_opt_photo_panel=true;
00463 
00464     // generate list of most recently uses files and add it to menu
00465     // needs to be initialized before the fast preview, there we call AddFilesToMenu()
00466     wxConfigBase * config=wxConfigBase::Get();
00467     m_mruFiles.Load(*config);
00468     m_mruFiles.UseMenu(m_menu_file_advanced->FindItem(XRCID("menu_mru"))->GetSubMenu());
00469 
00470     preview_frame = new PreviewFrame(this, pano);
00471     if(disableOpenGL)
00472     {
00473         gl_preview_frame=NULL;
00474         DisableOpenGLTools();
00475         m_mruFiles.AddFilesToMenu();
00476     }
00477     else
00478     {
00479         gl_preview_frame = new GLPreviewFrame(this, pano);
00480     };
00481 
00482     // set the minimize icon
00483 #ifdef __WXMSW__
00484     wxIcon myIcon(GetXRCPath() + wxT("data/hugin.ico"),wxBITMAP_TYPE_ICO);
00485 #else
00486     wxIcon myIcon(GetXRCPath() + wxT("data/hugin.png"),wxBITMAP_TYPE_PNG);
00487 #endif
00488     SetIcon(myIcon);
00489 
00490     // create a new drop handler. wxwindows deletes the automaticall
00491     SetDropTarget(new PanoDropTarget(pano));
00492     DEBUG_TRACE("");
00493 
00494     PanoOperation::GeneratePanoOperationVector();
00495 
00496     // create a status bar
00497     const int fields (2);
00498     CreateStatusBar(fields);
00499     int widths[fields] = {-1, 85};
00500     SetStatusWidths( fields, &widths[0]);
00501     SetStatusText(_("Started"), 0);
00502     wxYield();
00503     DEBUG_TRACE("");
00504 
00505     // observe the panorama
00506     pano.addObserver(this);
00507 
00508     // Set sizing characteristics
00509     //set minumum size
00510 #if defined __WXMAC__ || defined __WXMSW__
00511     // a minimum nice looking size; smaller than this would clutter the layout.
00512     SetSizeHints(900, 675);
00513 #else
00514     // For ASUS eeePc
00515     SetSizeHints(780, 455); //set minumum size
00516 #endif
00517 
00518     // set progress display for image cache.
00519     ImageCache::getInstance().setProgressDisplay(this);
00520 #if defined __WXMSW__
00521     unsigned long long mem = HUGIN_IMGCACHE_UPPERBOUND;
00522     unsigned long mem_low = wxConfigBase::Get()->Read(wxT("/ImageCache/UpperBound"), HUGIN_IMGCACHE_UPPERBOUND);
00523     unsigned long mem_high = wxConfigBase::Get()->Read(wxT("/ImageCache/UpperBoundHigh"), (long) 0);
00524     if (mem_high > 0) {
00525       mem = ((unsigned long long) mem_high << 32) + mem_low;
00526     }
00527     else {
00528       mem = mem_low;
00529     }
00530     ImageCache::getInstance().SetUpperLimit(mem);
00531 #else
00532     ImageCache::getInstance().SetUpperLimit(wxConfigBase::Get()->Read(wxT("/ImageCache/UpperBound"), HUGIN_IMGCACHE_UPPERBOUND));
00533 #endif
00534 
00535     if(splash) {
00536         splash->Close();
00537         delete splash;
00538     }
00539     wxYield();
00540 
00541     // disable automatic Layout() calls, to it by hand
00542     SetAutoLayout(false);
00543 
00544 
00545 #ifdef __WXMSW__
00546     // wxFrame does have a strange background color on Windows, copy color from a child widget
00547     this->SetBackgroundColour(images_panel->GetBackgroundColour());
00548 #endif
00549 
00550 // By using /SUBSYSTEM:CONSOLE /ENTRY:"WinMainCRTStartup" in the linker
00551 // options for the debug build, a console window will be used for stdout
00552 // and stderr. No need to redirect to a file. Better security since we can't
00553 // guarantee that c: exists and writing a file to the root directory is
00554 // never a good idea. release build still uses /SUBSYSTEM:WINDOWS
00555 
00556 #if 0
00557 #ifdef DEBUG
00558 #ifdef __WXMSW__
00559 
00560     freopen("c:\\hugin_stdout.txt", "w", stdout);    // redirect stdout to file
00561     freopen("c:\\hugin_stderr.txt", "w", stderr);    // redirect stderr to file
00562 #endif
00563 #endif
00564 #endif
00565     //reload gui level
00566     long guiLevel=config->Read(wxT("/GuiLevel"),(long)0);
00567     guiLevel = std::max<long>(0, std::min<long>(2, guiLevel));
00568     if(guiLevel==GUI_SIMPLE && disableOpenGL)
00569     {
00570         guiLevel=GUI_ADVANCED;
00571     };
00572     SetGuiLevel((GuiLevel)guiLevel);
00573 
00574     DEBUG_TRACE("");
00575 #ifdef __WXGTK__
00576     // set explicit focus to assistant panel for better processing key presses
00577     images_panel->SetFocus();
00578 #endif
00579 }
00580 
00581 MainFrame::~MainFrame()
00582 {
00583     DEBUG_TRACE("dtor");
00584     if(m_guiLevel==GUI_SIMPLE)
00585     {
00586         delete m_menu_file_advanced;
00587     }
00588     else
00589     {
00590         delete m_menu_file_simple;
00591     };
00592     ImageCache::getInstance().setProgressDisplay(NULL);
00593         delete & ImageCache::getInstance();
00594     delete & PanoCommand::GlobalCmdHist::getInstance();
00595 //    delete cpe;
00596 //    delete images_panel;
00597     DEBUG_DEBUG("removing observer");
00598     pano.removeObserver(this);
00599 
00600     // get the global config object
00601     wxConfigBase* config = wxConfigBase::Get();
00602 
00603     StoreFramePosition(this, wxT("MainFrame"));
00604 
00605     //store most recently used files
00606     m_mruFiles.Save(*config);
00607     //store gui level
00608     config->Write(wxT("/GuiLevel"),(long)m_guiLevel);
00609     config->Flush();
00610     if(svmModel!=NULL)
00611     {
00612         celeste::destroySVMmodel(svmModel);
00613     };
00614     PanoOperation::CleanPanoOperationVector();
00615 
00616     DEBUG_TRACE("dtor end");
00617 }
00618 
00619 void MainFrame::panoramaChanged(HuginBase::Panorama &pano)
00620 {
00621     wxToolBar* theToolBar = GetToolBar();
00622     wxMenuBar* theMenuBar = GetMenuBar();
00623     bool can_undo = PanoCommand::GlobalCmdHist::getInstance().canUndo();
00624     theMenuBar->Enable    (XRCID("ID_EDITUNDO"), can_undo);
00625     theToolBar->EnableTool(XRCID("ID_EDITUNDO"), can_undo);
00626     bool can_redo = PanoCommand::GlobalCmdHist::getInstance().canRedo();
00627     theMenuBar->Enable    (XRCID("ID_EDITREDO"), can_redo);
00628     theToolBar->EnableTool(XRCID("ID_EDITREDO"), can_redo);
00629 
00630     //show or hide optimizer and exposure optimizer tab depending on optimizer master switches
00631     if(pano.getOptimizerSwitch()==0 && !m_show_opt_panel)
00632     {
00633         m_notebook->InsertPage(3, opt_panel, _("Optimizer"));
00634         m_show_opt_panel=true;
00635     };
00636     if(pano.getOptimizerSwitch()!=0 && m_show_opt_panel)
00637     {
00638         m_notebook->RemovePage(3);
00639         m_show_opt_panel=false;
00640     };
00641     if(pano.getPhotometricOptimizerSwitch()==0 && !m_show_opt_photo_panel)
00642     {
00643         if(m_show_opt_panel)
00644         {
00645             m_notebook->InsertPage(4, opt_photo_panel, _("Exposure"));
00646         }
00647         else
00648         {
00649             m_notebook->InsertPage(3, opt_photo_panel, _("Exposure"));
00650         }
00651         m_show_opt_photo_panel=true;
00652     };
00653     if(pano.getPhotometricOptimizerSwitch()!=0 && m_show_opt_photo_panel)
00654     {
00655         if(m_show_opt_panel)
00656         {
00657             m_notebook->RemovePage(4);
00658         }
00659         else
00660         {
00661             m_notebook->RemovePage(3);
00662         };
00663         m_show_opt_photo_panel=false;
00664     };
00665     theMenuBar->Enable(XRCID("ID_SHOW_PANEL_OPTIMIZER"), m_show_opt_panel);
00666     theMenuBar->Enable(XRCID("ID_SHOW_PANEL_OPTIMIZER_PHOTOMETRIC"), m_show_opt_photo_panel);
00667 }
00668 
00669 //void MainFrame::panoramaChanged(HuginBase::Panorama &panorama)
00670 void MainFrame::panoramaImagesChanged(HuginBase::Panorama &panorama, const HuginBase::UIntSet & changed)
00671 {
00672     DEBUG_TRACE("");
00673     assert(&pano == &panorama);
00674     if (pano.getNrOfImages() == 0) {
00675           enableTools(false);
00676         } else {
00677           enableTools(true);
00678         }
00679     GetMenuBar()->Enable(XRCID("action_assistant"), pano.getNrOfImages()>=2);
00680     GetMenuBar()->Enable(XRCID("action_batch_assistant"), pano.getNrOfImages()>=2);
00681 }
00682 
00683 void MainFrame::OnUserQuit(wxCommandEvent & e)
00684 {
00685     Close();
00686 }
00687 
00688 bool MainFrame::CloseProject(bool cancelable)
00689 {
00690     if (pano.isDirty()) {
00691         wxMessageDialog message(wxGetActiveWindow(),
00692                                 _("Save changes to the panorama before closing?"),
00693 #ifdef _WIN32
00694                                 _("Hugin"),
00695 #else
00696                                 wxT(""),
00697 #endif
00698                                 wxICON_EXCLAMATION | wxYES_NO | (cancelable? (wxCANCEL):0));
00699 #if wxCHECK_VERSION(2, 9, 0)
00700     message.SetExtendedMessage(_("If you close without saving, changes since your last save will be discarded"));
00701     #if defined __WXMAC__ || defined __WXMSW__
00702         // Apple human interface guidelines and Windows user experience interaction guidelines
00703         message.SetYesNoLabels(wxID_SAVE, _("Don't Save"));
00704     #else
00705         // Gnome human interface guidelines:
00706         message.SetYesNoLabels(wxID_SAVE, _("Close without saving"));
00707     #endif
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         GetHelpController().DisplayHelpPage(section);
01211     };
01212 #else
01213     if (section.IsEmpty())
01214     {
01215         section = wxT("/Hugin.html");
01216     }
01217 #if defined __WXMAC__ && defined MAC_SELF_CONTAINED_BUNDLE
01218     // On Mac, xrc/data/help_LOCALE should be in the bundle as LOCALE.lproj/help
01219     // which we can rely on the operating sytem to pick the right locale's.
01220     wxString strFile = MacGetPathToBundledResourceFile(CFSTR("help"));
01221     if(strFile!=wxT(""))
01222     {
01223         strFile += section;
01224     } else {
01225         wxLogError(wxString::Format(wxT("Could not find help directory in the bundle"), strFile.c_str()));
01226         return;
01227     }
01228 #else
01229     // find base filename
01230     wxString helpFile = wxT("help_") + huginApp::Get()->GetLocale().GetCanonicalName() + section;
01231     DEBUG_INFO("help file candidate: " << helpFile.mb_str(wxConvLocal));
01232     //if the language is not default, load custom About file (if exists)
01233     wxString strFile = GetXRCPath() + wxT("data/") + helpFile;
01234     if(wxFile::Exists(strFile))
01235     {
01236         DEBUG_TRACE("Using About: " << strFile.mb_str(wxConvLocal));
01237     } else {
01238         strFile = GetXRCPath() + wxT("data/help_en_EN") + section;
01239     }
01240 #endif
01241     if(!wxFile::Exists(strFile))
01242     {
01243         wxLogError(wxString::Format(wxT("Could not open help file: %s"), strFile.c_str()));
01244         return;
01245     }
01246     DEBUG_INFO("help file: " << strFile.mb_str(wxConvLocal));
01247     if(!wxLaunchDefaultBrowser(strFile))
01248     {
01249         wxLogError(_("Can't start system's web browser"));
01250     }
01251 #endif
01252 }
01253 
01254 void MainFrame::OnTipOfDay(wxCommandEvent& WXUNUSED(e))
01255 {
01256     wxString strFile;
01257     bool bShowAtStartup;
01258 // DGSW FIXME - Unreferenced
01259 //      bool bTipsExist = false;
01260     int nValue;
01261 
01262     wxConfigBase * config = wxConfigBase::Get();
01263     nValue = config->Read(wxT("/MainFrame/ShowStartTip"),1l);
01264 
01265     //TODO: tips not localisable
01266     DEBUG_INFO("Tip index: " << nValue);
01267     strFile = GetXRCPath() + wxT("data/tips.txt");  //load default file
01268 
01269     DEBUG_INFO("Reading tips from " << strFile.mb_str(wxConvLocal));
01270     wxTipProvider *tipProvider = new LocalizedFileTipProvider(strFile, nValue);
01271     bShowAtStartup = wxShowTip(wxGetActiveWindow(), tipProvider, (nValue ? true : false));
01272 
01273     //store startup preferences
01274     nValue = (bShowAtStartup ? tipProvider->GetCurrentTip() : 0);
01275     DEBUG_INFO("Writing tip index: " << nValue);
01276     config->Write(wxT("/MainFrame/ShowStartTip"), nValue);
01277     delete tipProvider;
01278 }
01279 
01280 
01281 void MainFrame::OnShowPrefs(wxCommandEvent & e)
01282 {
01283     DEBUG_TRACE("");
01284     PreferencesDialog pref_dlg(wxGetActiveWindow());
01285     pref_dlg.ShowModal();
01286     //update image cache size
01287     wxConfigBase* cfg=wxConfigBase::Get();
01288 #if defined __WXMSW__
01289     unsigned long long mem = HUGIN_IMGCACHE_UPPERBOUND;
01290     unsigned long mem_low = cfg->Read(wxT("/ImageCache/UpperBound"), HUGIN_IMGCACHE_UPPERBOUND);
01291     unsigned long mem_high = cfg->Read(wxT("/ImageCache/UpperBoundHigh"), (long) 0);
01292     if (mem_high > 0)
01293     {
01294       mem = ((unsigned long long) mem_high << 32) + mem_low;
01295     }
01296     else
01297     {
01298       mem = mem_low;
01299     }
01300     ImageCache::getInstance().SetUpperLimit(mem);
01301 #else
01302     ImageCache::getInstance().SetUpperLimit(cfg->Read(wxT("/ImageCache/UpperBound"), HUGIN_IMGCACHE_UPPERBOUND));
01303 #endif
01304     images_panel->ReloadCPDetectorSettings();
01305     if(gl_preview_frame)
01306     {
01307         gl_preview_frame->SetShowProjectionHints(cfg->Read(wxT("/GLPreviewFrame/ShowProjectionHints"),HUGIN_SHOW_PROJECTION_HINTS)!=0);
01308     };
01309 }
01310 
01311 void MainFrame::UpdatePanels( wxCommandEvent& WXUNUSED(event) )
01312 {   // Maybe this can be invoced by the Panorama::Changed() or
01313     // something like this. So no everytime update would be needed.
01314     DEBUG_TRACE("");
01315 }
01316 
01317 void MainFrame::OnTogglePreviewFrame(wxCommandEvent & e)
01318 {
01319     DEBUG_TRACE("");
01320     if (preview_frame->IsIconized()) {
01321         preview_frame->Iconize(false);
01322     }
01323     preview_frame->Show();
01324     preview_frame->Raise();
01325 
01326         // we need to force an update since autoupdate fires
01327         // before the preview frame is shown
01328     wxCommandEvent dummy;
01329         preview_frame->OnUpdate(dummy);
01330 }
01331 
01332 void MainFrame::OnToggleGLPreviewFrame(wxCommandEvent & e)
01333 {
01334     if(gl_preview_frame==NULL)
01335     {
01336         return;
01337     };
01338 #if defined __WXMSW__ || defined __WXMAC__
01339     gl_preview_frame->InitPreviews();
01340 #endif
01341     if (gl_preview_frame->IsIconized()) {
01342         gl_preview_frame->Iconize(false);
01343     }
01344     gl_preview_frame->Show();
01345 #if defined __WXMSW__
01346     // on wxMSW Show() does not send OnShowEvent needed to update the
01347     // visibility state of the fast preview windows
01348     // so explicit calling this event handler
01349     wxShowEvent se;
01350     se.SetShow(true);
01351     gl_preview_frame->OnShowEvent(se);
01352 #elif defined __WXGTK__
01353     gl_preview_frame->LoadOpenGLLayout();
01354 #endif
01355     gl_preview_frame->Raise();
01356 }
01357 
01358 void MainFrame::OnShowCPFrame(wxCommandEvent & e)
01359 {
01360     DEBUG_TRACE("");
01361     if (cp_frame) {
01362         if (cp_frame->IsIconized()) {
01363             cp_frame->Iconize(false);
01364         }
01365         cp_frame->Show();
01366         cp_frame->Raise();
01367     } else {
01368         cp_frame = new CPListFrame(this, pano);
01369         cp_frame->Show();
01370     }
01371 }
01372 
01373 void MainFrame::OnCPListFrameClosed()
01374 {
01375     cp_frame = 0;
01376 }
01377 
01378 void MainFrame::OnOptimize(wxCommandEvent & e)
01379 {
01380     DEBUG_TRACE("");
01381     wxCommandEvent dummy;
01382     opt_panel->OnOptimizeButton(dummy);
01383 }
01384 
01385 void MainFrame::OnPhotometricOptimize(wxCommandEvent & e)
01386 {
01387     wxCommandEvent dummy;
01388     opt_photo_panel->OnOptimizeButton(dummy);
01389 };
01390 
01391 void MainFrame::OnDoStitch(wxCommandEvent & e)
01392 {
01393     DEBUG_TRACE("");
01394     wxCommandEvent cmdEvt(wxEVT_COMMAND_BUTTON_CLICKED,XRCID("pano_button_stitch"));
01395     pano_panel->GetEventHandler()->AddPendingEvent(cmdEvt);
01396 }
01397 
01398 void MainFrame::OnUserDefinedStitch(wxCommandEvent & e)
01399 {
01400     pano_panel->DoUserDefinedStitch();
01401 }
01402 
01403 void MainFrame::OnMergeProject(wxCommandEvent & e)
01404 {
01405     // get the global config object
01406     wxConfigBase* config = wxConfigBase::Get();
01407 
01408     wxString defaultdir = config->Read(wxT("/actualPath"),wxT(""));
01409     wxFileDialog dlg(wxGetActiveWindow(),
01410                      _("Open project file"),
01411                      defaultdir, wxT(""),
01412                      _("Project files (*.pto)|*.pto|All files (*)|*"),
01413                      wxFD_OPEN, wxDefaultPosition);
01414     dlg.SetDirectory(defaultdir);
01415     if (dlg.ShowModal() == wxID_OK)
01416     {
01417         wxString filename = dlg.GetPath();
01418         wxFileName fname(filename);
01419         wxString path = fname.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR);
01420         if (fname.IsOk() && fname.FileExists())
01421         {
01422             wxBusyCursor wait;
01423             HuginBase::PanoramaMemento newPano;
01424             std::ifstream in((const char *)fname.GetFullPath().mb_str(HUGIN_CONV_FILENAME));
01425             int ptoversion=0;
01426             if (newPano.loadPTScript(in, ptoversion, (const char *)path.mb_str(HUGIN_CONV_FILENAME)))
01427             {
01428                 HuginBase::Panorama new_pano;
01429                 new_pano.setMemento(newPano);
01430                 PanoCommand::GlobalCmdHist::getInstance().addCommand(
01431                     new PanoCommand::MergePanoCmd(pano, new_pano)
01432                 );
01433                 m_mruFiles.AddFileToHistory(fname.GetFullPath());
01434                 // force update of preview window
01435                 if ( !(preview_frame->IsIconized() ||(! preview_frame->IsShown()) ) )
01436                 {
01437                     wxCommandEvent dummy;
01438                     preview_frame->OnUpdate(dummy);
01439                 };
01440             }
01441             else
01442             {
01443                 wxMessageBox(wxString::Format(_("Could not read project file %s."),fname.GetFullPath().c_str()),_("Error"),wxOK|wxICON_ERROR);
01444             };
01445         };
01446     }
01447 }
01448 
01449 void MainFrame::OnApplyTemplate(wxCommandEvent & e)
01450 {
01451     // get the global config object
01452     wxConfigBase* config = wxConfigBase::Get();
01453 
01454     wxFileDialog dlg(wxGetActiveWindow(),
01455                      _("Choose template project"),
01456                      config->Read(wxT("/templatePath"),wxT("")), wxT(""),
01457                      _("Project files (*.pto)|*.pto|All files (*)|*"),
01458                      wxFD_OPEN, wxDefaultPosition);
01459     dlg.SetDirectory(wxConfigBase::Get()->Read(wxT("/templatePath"),wxT("")));
01460     if (dlg.ShowModal() == wxID_OK) {
01461         wxString filename = dlg.GetPath();
01462         wxConfig::Get()->Write(wxT("/templatePath"), dlg.GetDirectory());  // remember for later
01463 
01464         std::ifstream file((const char *)filename.mb_str(HUGIN_CONV_FILENAME));
01465 
01466         PanoCommand::GlobalCmdHist::getInstance().addCommand(
01467             new PanoCommand::wxApplyTemplateCmd(pano, file));
01468 
01469     }
01470 }
01471 
01472 void MainFrame::OnOpenPTBatcher(wxCommandEvent & e)
01473 {
01474 #if defined __WXMAC__ && defined MAC_SELF_CONTAINED_BUNDLE
01475         // Original patch for OSX by Charlie Reiman dd. 18 June 2011
01476         // Slightly modified by HvdW. Errors in here are mine, not Charlie's. 
01477         FSRef appRef;
01478         FSRef actuallyLaunched;
01479         OSStatus err;
01480         FSRef documentArray[1]; // Don't really need an array if we only have 1 item
01481         LSLaunchFSRefSpec launchSpec;
01482         Boolean  isDir;
01483         
01484         err = LSFindApplicationForInfo(kLSUnknownCreator,
01485                                                                    CFSTR("net.sourceforge.hugin.PTBatcherGUI"),
01486                                                                    NULL,
01487                                                                    &appRef,
01488                                                                    NULL);
01489         if (err != noErr) {
01490                 // error, can't find PTBatcherGUI
01491                 wxMessageBox(wxString::Format(_("External program %s not found in the bundle, reverting to system path"), wxT("open")), _("Error"));
01492                 // Possibly a silly attempt otherwise the previous would have worked as well, but just try it.
01493                 wxExecute(_T("open -b net.sourceforge.hugin.PTBatcherGUI"));
01494         }
01495         else {
01496                 wxExecute(_T("open -b net.sourceforge.hugin.PTBatcherGUI"));
01497         }       
01498 #else
01499     const wxFileName exePath(wxStandardPaths::Get().GetExecutablePath());
01500         wxExecute(exePath.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR) + _T("PTBatcherGUI"));
01501 #endif
01502 }
01503 
01504 void MainFrame::OnFineTuneAll(wxCommandEvent & e)
01505 {
01506     DEBUG_TRACE("");
01507     // fine-tune all points
01508 
01509     HuginBase::CPVector cps = pano.getCtrlPoints();
01510 
01511     // create a map of all control points.
01512     std::set<unsigned int> unoptimized;
01513     for (unsigned int i=0; i < cps.size(); i++) {
01514         // create all control points.
01515         unoptimized.insert(i);
01516     }
01517 
01518     unsigned int nGood=0;
01519     unsigned int nBad=0;
01520 
01521     wxConfigBase *cfg = wxConfigBase::Get();
01522     double corrThresh=HUGIN_FT_CORR_THRESHOLD;
01523     cfg->Read(wxT("/Finetune/CorrThreshold"), &corrThresh, HUGIN_FT_CORR_THRESHOLD);
01524     double curvThresh = HUGIN_FT_CURV_THRESHOLD;
01525     cfg->Read(wxT("/Finetune/CurvThreshold"),&curvThresh, HUGIN_FT_CURV_THRESHOLD);
01526     // load parameters
01527     const long templWidth = cfg->Read(wxT("/Finetune/TemplateSize"), HUGIN_FT_TEMPLATE_SIZE);
01528     const long sWidth = templWidth + cfg->Read(wxT("/Finetune/LocalSearchWidth"), HUGIN_FT_LOCAL_SEARCH_WIDTH);
01529 
01530     {
01531         ProgressReporterDialog progress(unoptimized.size(), _("Fine-tuning all points"), _("Fine-tuning"), wxGetActiveWindow());
01532 
01533     ImageCache & imgCache = ImageCache::getInstance();
01534 
01535     // do not process the control points in random order,
01536     // but walk from image to image, to reduce image reloading
01537     // in low mem situations.
01538     for (unsigned int imgNr = 0 ; imgNr < pano.getNrOfImages(); imgNr++) {
01539         std::set<unsigned int>::iterator it=unoptimized.begin();
01540 
01541         imgCache.softFlush();
01542 
01543         while (it != unoptimized.end()) {
01544             if (cps[*it].image1Nr == imgNr || cps[*it].image2Nr == imgNr) {
01545                 if (!progress.updateDisplayValue())
01546                 {
01547                     return;
01548                 };
01549                 if (cps[*it].mode == HuginBase::ControlPoint::X_Y) {
01550                     // finetune only normal points
01551                     DEBUG_DEBUG("fine tuning point: " << *it);
01552                     wxImage wxSearchImg;
01553                     ImageCache::ImageCacheRGB8Ptr searchImg = imgCache.getImage(
01554                         pano.getImage(cps[*it].image2Nr).getFilename())->get8BitImage();
01555 
01556                     ImageCache::ImageCacheRGB8Ptr templImg = imgCache.getImage(
01557                         pano.getImage(cps[*it].image1Nr).getFilename())->get8BitImage();
01558 
01559                     vigra_ext::CorrelationResult res;
01560                     vigra::Diff2D roundP1(hugin_utils::roundi(cps[*it].x1), hugin_utils::roundi(cps[*it].y1));
01561                     vigra::Diff2D roundP2(hugin_utils::roundi(cps[*it].x2), hugin_utils::roundi(cps[*it].y2));
01562 
01563                     res = PointFineTuneProjectionAware(pano.getImage(cps[*it].image1Nr), *templImg, roundP1, templWidth,
01564                         pano.getImage(cps[*it].image2Nr), *searchImg, roundP2, sWidth);
01565 
01566                     // invert curvature. we always assume its a maxima, the curvature there is negative
01567                     // however, we allow the user to specify a positive threshold, so we need to
01568                     // invert it
01569                     res.curv.x = - res.curv.x;
01570                     res.curv.y = - res.curv.y;
01571 
01572                     if (res.maxi < corrThresh || res.curv.x < curvThresh || res.curv.y < curvThresh ||
01573                         res.maxpos.x < 0 || res.maxpos.y < 0 || res.corrPos.x < 0 || res.corrPos.y < 0)
01574                     {
01575                         // Bad correlation result.
01576                         nBad++;
01577                         if (res.maxi >= corrThresh) {
01578                             cps[*it].error = 0;
01579                         }
01580                         cps[*it].error = res.maxi;
01581                         DEBUG_DEBUG("low correlation: " << res.maxi << " curv: " << res.curv);
01582                     } else {
01583                         nGood++;
01584                         // only update if a good correlation was found
01585                         cps[*it].x1 = res.corrPos.x;
01586                         cps[*it].y1 = res.corrPos.y;
01587                         cps[*it].x2 = res.maxpos.x;
01588                         cps[*it].y2 = res.maxpos.y;
01589                         cps[*it].error = res.maxi;
01590                     }
01591                 }
01592                 unsigned int rm = *it;
01593                 ++it;
01594                 unoptimized.erase(rm);
01595             } else {
01596                 ++it;
01597             }
01598         }
01599     }
01600     }
01601     wxString result;
01602     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"),
01603                   nGood, nBad, corrThresh);
01604     wxMessageBox(result, _("Fine-tune result"), wxOK);
01605     // set newly optimized points
01606     PanoCommand::GlobalCmdHist::getInstance().addCommand(
01607         new PanoCommand::UpdateCPsCmd(pano, cps, false)
01608         );
01609 }
01610 
01611 void MainFrame::OnRemoveCPinMasks(wxCommandEvent & e)
01612 {
01613     if(pano.getCtrlPoints().size()<2)
01614         return;
01615     HuginBase::UIntSet cps=getCPinMasks(pano);
01616     if(cps.size()>0)
01617     {
01618         PanoCommand::GlobalCmdHist::getInstance().addCommand(
01619                     new PanoCommand::RemoveCtrlPointsCmd(pano,cps)
01620                     );
01621         wxMessageBox(wxString::Format(_("Removed %lu control points"), static_cast<unsigned long>(cps.size())),
01622                    _("Removing control points in masks"),wxOK|wxICON_INFORMATION);
01623     };
01624 }
01625 
01626 #ifdef HUGIN_HSI
01627 void MainFrame::OnPythonScript(wxCommandEvent & e)
01628 {
01629     wxString fname;
01630     wxFileDialog dlg(wxGetActiveWindow(),
01631             _("Select python script"),
01632             wxConfigBase::Get()->Read(wxT("/lensPath"),wxT("")), wxT(""),
01633             _("Python script (*.py)|*.py|All files (*.*)|*.*"),
01634             wxFD_OPEN, wxDefaultPosition);
01635     dlg.SetDirectory(wxConfigBase::Get()->Read(wxT("/pythonScriptPath"),wxT("")));
01636 
01637     if (dlg.ShowModal() == wxID_OK)
01638     {
01639         wxString filename = dlg.GetPath();
01640         wxConfig::Get()->Write(wxT("/pythonScriptPath"), dlg.GetDirectory());
01641         std::string scriptfile((const char *)filename.mb_str(HUGIN_CONV_FILENAME));
01642         PanoCommand::GlobalCmdHist::getInstance().addCommand(
01643             new PanoCommand::PythonScriptPanoCmd(pano,scriptfile)
01644             );
01645     }
01646 }
01647 
01648 void MainFrame::OnPlugin(wxCommandEvent & e)
01649 {
01650     wxFileName file=m_plugins[e.GetId()];
01651     if(file.FileExists())
01652     {
01653         std::string scriptfile((const char *)file.GetFullPath().mb_str(HUGIN_CONV_FILENAME));
01654         PanoCommand::GlobalCmdHist::getInstance().addCommand(
01655                                  new PanoCommand::PythonScriptPanoCmd(pano,scriptfile)
01656                                  );
01657     }
01658     else
01659     {
01660         wxMessageBox(wxString::Format(wxT("Python-Script %s not found.\nStopping processing."),file.GetFullPath().c_str()),_("Warning"),wxOK|wxICON_INFORMATION);
01661     };
01662 }
01663 
01664 #endif
01665 
01666 void MainFrame::OnUndo(wxCommandEvent & e)
01667 {
01668     DEBUG_TRACE("OnUndo");
01669     if (PanoCommand::GlobalCmdHist::getInstance().canUndo())
01670     {
01671         PanoCommand::GlobalCmdHist::getInstance().undo();
01672     }
01673     else
01674     {
01675         wxBell();
01676     };
01677 }
01678 
01679 void MainFrame::OnRedo(wxCommandEvent & e)
01680 {
01681     DEBUG_TRACE("OnRedo");
01682     if (PanoCommand::GlobalCmdHist::getInstance().canRedo())
01683     {
01684         PanoCommand::GlobalCmdHist::getInstance().redo();
01685     };
01686 }
01687 
01688 void MainFrame::ShowCtrlPoint(unsigned int cpNr)
01689 {
01690     DEBUG_DEBUG("Showing control point " << cpNr);
01691     m_notebook->SetSelection(2);
01692     cpe->ShowControlPoint(cpNr);
01693 }
01694 
01695 void MainFrame::ShowCtrlPointEditor(unsigned int img1, unsigned int img2)
01696 {
01697     if(!IsShown())
01698     {
01699         Show();
01700         Raise();
01701     };
01702     m_notebook->SetSelection(2);
01703     cpe->setLeftImage(img1);
01704     cpe->setRightImage(img2);
01705 }
01706 
01707 void MainFrame::ShowMaskEditor(size_t imgNr)
01708 {
01709     if(!IsShown())
01710     {
01711         Show();
01712         Raise();
01713     };
01714     m_notebook->SetSelection(1);
01715     mask_panel->setImage(imgNr, true);
01716 };
01717 
01718 void MainFrame::ShowStitcherTab()
01719 {
01721     if(m_show_opt_panel && m_show_opt_photo_panel)
01722     {
01723         m_notebook->SetSelection(5);
01724     }
01725     else
01726     {
01727         if(m_show_opt_panel || m_show_opt_photo_panel)
01728         {
01729             m_notebook->SetSelection(4);
01730         }
01731         else
01732         {
01733             m_notebook->SetSelection(3);
01734         };
01735     };
01736 }
01737 
01739 void MainFrame::updateProgressDisplay()
01740 {
01741     wxString msg;
01742     if (!m_message.empty())
01743     {
01744         msg = wxGetTranslation(wxString(m_message.c_str(), wxConvLocal));
01745         if (!m_filename.empty())
01746         {
01747             msg.Append(wxT(" "));
01748             msg.Append(wxString(ProgressDisplay::m_filename.c_str(), HUGIN_CONV_FILENAME));
01749         };
01750     };
01751     GetStatusBar()->SetStatusText(msg, 0);
01752 
01753 #ifdef __WXMSW__
01754     UpdateWindow(NULL);
01755 #endif
01756 }
01757 
01758 void MainFrame::enableTools(bool option)
01759 {
01760     wxToolBar* theToolBar = GetToolBar();
01761     theToolBar->EnableTool(XRCID("action_optimize"), option);
01762     theToolBar->EnableTool(XRCID("ID_SHOW_PREVIEW_FRAME"), option);
01763     //theToolBar->EnableTool(XRCID("ID_SHOW_GL_PREVIEW_FRAME"), option);
01764     wxMenuBar* theMenuBar = GetMenuBar();
01765     theMenuBar->Enable(XRCID("action_optimize"), option);
01766     theMenuBar->Enable(XRCID("action_finetune_all_cp"), option);
01767     theMenuBar->Enable(XRCID("action_remove_cp_in_masks"), option);
01768     theMenuBar->Enable(XRCID("ID_SHOW_PREVIEW_FRAME"), option);
01769     theMenuBar->Enable(XRCID("action_stitch"), option);
01770     theMenuBar->Enable(XRCID("action_stitch_userdefined"), option);
01771     //theMenuBar->Enable(XRCID("ID_SHOW_GL_PREVIEW_FRAME"), option);
01772 }
01773 
01774 
01775 void MainFrame::OnSize(wxSizeEvent &e)
01776 {
01777     wxSize sz = this->GetSize();
01778     wxSize csz = this->GetClientSize();
01779     wxSize vsz = this->GetVirtualSize();
01780     DEBUG_TRACE(" size:" << sz.x << "," << sz.y <<
01781                 " client: "<< csz.x << "," << csz.y <<
01782                 " virtual: "<< vsz.x << "," << vsz.y);
01783 
01784     Layout();
01785     e.Skip();
01786 }
01787 
01788 CPDetectorSetting& MainFrame::GetDefaultSetting()
01789 {
01790     return images_panel->GetDefaultSetting();
01791 };
01792 
01793 void MainFrame::RunCPGenerator(CPDetectorSetting &setting, const HuginBase::UIntSet& img)
01794 {
01795     images_panel->RunCPGenerator(setting, img);
01796 };
01797 
01798 void MainFrame::RunCPGenerator(const HuginBase::UIntSet& img)
01799 {
01800     images_panel->RunCPGenerator(img);
01801 };
01802 
01803 const wxString MainFrame::GetSelectedCPGenerator()
01804 {
01805     return images_panel->GetSelectedCPGenerator();
01806 };
01807 
01808 const wxString & MainFrame::GetXRCPath()
01809 {
01810      return huginApp::Get()->GetXRCPath();
01811 };
01812 
01813 const wxString & MainFrame::GetDataPath()
01814 {
01815     return wxGetApp().GetDataPath();
01816 };
01817 
01819 MainFrame * MainFrame::Get()
01820 {
01821     if (m_this) {
01822         return m_this;
01823     } else {
01824         DEBUG_FATAL("MainFrame not yet created");
01825         DEBUG_ASSERT(m_this);
01826         return 0;
01827     }
01828 }
01829 
01830 wxString MainFrame::getProjectName()
01831 {
01832     return m_filename;
01833 }
01834 
01835 void MainFrame::OnMRUFiles(wxCommandEvent &e)
01836 {
01837     size_t index = e.GetId() - wxID_FILE1;
01838     wxString f(m_mruFiles.GetHistoryFile(index));
01839     if (!f.empty())
01840     {
01841         wxFileName fn(f);
01842         if(fn.FileExists())
01843             LoadProjectFile(f);
01844         else
01845         {
01846             m_mruFiles.RemoveFileFromHistory(index);
01847             wxMessageBox(wxString::Format(_("File \"%s\" not found.\nMaybe file was renamed, moved or deleted."),f.c_str()),
01848                 _("Error!"),wxOK | wxICON_INFORMATION );
01849         };
01850     };
01851 }
01852 
01853 void MainFrame::OnFullScreen(wxCommandEvent & e)
01854 {
01855     ShowFullScreen(!IsFullScreen(), wxFULLSCREEN_NOBORDER | wxFULLSCREEN_NOCAPTION);
01856 #ifdef __WXGTK__
01857     //workaround a wxGTK bug that also the toolbar is hidden, but not requested to hide
01858     GetToolBar()->Show(true);
01859 #endif
01860 };
01861 
01862 struct celeste::svm_model* MainFrame::GetSVMModel()
01863 {
01864     if(svmModel==NULL)
01865     {
01866         // determine file name of SVM model file
01867         // get XRC path from application
01868         wxString wxstrModelFileName = huginApp::Get()->GetDataPath() + wxT(HUGIN_CELESTE_MODEL);
01869         // convert wxString to string
01870         std::string strModelFileName(wxstrModelFileName.mb_str(HUGIN_CONV_FILENAME));
01871 
01872         // SVM model file
01873         if (! wxFile::Exists(wxstrModelFileName) ) {
01874             wxMessageBox(wxString::Format(_("Celeste model expected in %s not found, Hugin needs to be properly installed."),wxstrModelFileName.c_str()), _("Fatal Error"));
01875             return NULL;
01876         }
01877         if(!celeste::loadSVMmodel(svmModel,strModelFileName))
01878         {
01879             wxMessageBox(wxString::Format(_("Could not load Celeste model file %s"),wxstrModelFileName.c_str()),_("Error"));
01880             svmModel=NULL;
01881         };
01882     }
01883     return svmModel;
01884 };
01885 
01886 GLPreviewFrame * MainFrame::getGLPreview()
01887 {
01888     return gl_preview_frame;
01889 }
01890 
01891 void MainFrame::SetGuiLevel(GuiLevel newLevel)
01892 {
01893     if(gl_preview_frame==NULL && newLevel==GUI_SIMPLE)
01894     {
01895         SetGuiLevel(GUI_ADVANCED);
01896         return;
01897     };
01898     if(m_guiLevel==GUI_EXPERT && newLevel!=GUI_EXPERT && pano.getOptimizerSwitch()==0)
01899     {
01900         bool needsUpdateOptimizerVar=false;
01901         HuginBase::OptimizeVector optVec = pano.getOptimizeVector();
01902         for(size_t i=0; i<optVec.size(); i++)
01903         {
01904             bool hasTrX=optVec[i].erase("TrX")>0;
01905             bool hasTrY=optVec[i].erase("TrY")>0;
01906             bool hasTrZ=optVec[i].erase("TrZ")>0;
01907             bool hasTpy=optVec[i].erase("Tpy")>0;
01908             bool hasTpp=optVec[i].erase("Tpp")>0;
01909             bool hasg=optVec[i].erase("g")>0;
01910             bool hast=optVec[i].erase("t")>0;
01911             needsUpdateOptimizerVar=needsUpdateOptimizerVar || hasTrX || hasTrY || hasTrZ || hasTpy || hasTpp || hasg || hast;
01912         };
01913         if(needsUpdateOptimizerVar)
01914         {
01915             PanoCommand::GlobalCmdHist::getInstance().addCommand(
01916                 new PanoCommand::UpdateOptimizeVectorCmd(pano, optVec)
01917             );
01918         };
01919     };
01920     if(newLevel==GUI_SIMPLE && pano.getPhotometricOptimizerSwitch()==0)
01921     {
01922         bool needsUpdateOptimizerVar=false;
01923         HuginBase::OptimizeVector optVec = pano.getOptimizeVector();
01924         for(size_t i=0; i<optVec.size(); i++)
01925         {
01926             bool hasVx=optVec[i].erase("Vx")>0;
01927             bool hasVy=optVec[i].erase("Vy")>0;
01928             needsUpdateOptimizerVar=needsUpdateOptimizerVar || hasVx || hasVy;
01929         };
01930         if(needsUpdateOptimizerVar)
01931         {
01932             PanoCommand::GlobalCmdHist::getInstance().addCommand(
01933                 new PanoCommand::UpdateOptimizeVectorCmd(pano, optVec)
01934             );
01935         };
01936     };
01937     m_guiLevel=newLevel;
01938     images_panel->SetGuiLevel(m_guiLevel);
01939     opt_panel->SetGuiLevel(m_guiLevel);
01940     opt_photo_panel->SetGuiLevel(m_guiLevel);
01941     pano_panel->SetGuiLevel(m_guiLevel);
01942     if(gl_preview_frame)
01943     {
01944         gl_preview_frame->SetGuiLevel(m_guiLevel);
01945     };
01946     switch(m_guiLevel)
01947     {
01948         case GUI_SIMPLE:
01949             GetMenuBar()->FindItem(XRCID("action_gui_simple"))->Check();
01950             break;
01951         case GUI_ADVANCED:
01952             GetMenuBar()->FindItem(XRCID("action_gui_advanced"))->Check();
01953             break;
01954         case GUI_EXPERT:
01955             GetMenuBar()->FindItem(XRCID("action_gui_expert"))->Check();
01956             break;
01957     };
01958     if(m_guiLevel==GUI_SIMPLE)
01959     {
01960         if(!gl_preview_frame->IsShown())
01961         {
01962             wxCommandEvent dummy;
01963             OnToggleGLPreviewFrame(dummy);
01964         };
01965         wxGetApp().SetTopWindow(gl_preview_frame);
01966         GetMenuBar()->Remove(0);
01967         GetMenuBar()->Insert(0, m_menu_file_simple, _("&File"));
01968         if(m_filename.IsEmpty())
01969         {
01970             gl_preview_frame->SetTitle(_("Hugin - Panorama Stitcher"));
01971             SetTitle(_("Panorama editor"));
01972         }
01973         else
01974         {
01975             wxFileName scriptName = m_filename;
01976             gl_preview_frame->SetTitle(scriptName.GetName() + wxT(".") + scriptName.GetExt() + wxT(" - ") + _("Hugin - Panorama Stitcher"));
01977             SetTitle(scriptName.GetName() + wxT(".") + scriptName.GetExt() + wxT(" - ") + _("Panorama editor"));
01978         };
01979         Hide();
01980     }
01981     else
01982     {
01983         wxGetApp().SetTopWindow(this);
01984         GetMenuBar()->Remove(0);
01985         GetMenuBar()->Insert(0, m_menu_file_advanced, _("&File"));
01986         if(m_filename.IsEmpty())
01987         {
01988             SetTitle(_("Hugin - Panorama Stitcher"));
01989         }
01990         else
01991         {
01992             wxFileName scriptName = m_filename;
01993             SetTitle(scriptName.GetName() + wxT(".") + scriptName.GetExt() + wxT(" - ") + _("Hugin - Panorama Stitcher"));
01994         };
01995         if(!IsShown())
01996         {
01997             Show();
01998         };
01999     };
02000 };
02001 
02002 void MainFrame::OnSetGuiSimple(wxCommandEvent & e)
02003 {
02004     GuiLevel reqGuiLevel=GetMinimumGuiLevel(pano);
02005     if(reqGuiLevel<=GUI_SIMPLE)
02006     {
02007         SetGuiLevel(GUI_SIMPLE);
02008     }
02009     else
02010     {
02011         if(reqGuiLevel==GUI_ADVANCED)
02012         {
02013             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."),
02014 #ifdef __WXMSW__
02015                          wxT("Hugin"),
02016 #else
02017                          wxT(""),
02018 #endif
02019                          wxOK | wxICON_INFORMATION);
02020         }
02021         else
02022         {
02023             wxMessageBox(_("Can't switch to simple interface. The project is using translation or shear parameters.\nThese parameters are not supported in simple interface."),
02024 #ifdef __WXMSW__
02025                          wxT("Hugin"),
02026 #else
02027                          wxT(""),
02028 #endif
02029                          wxOK | wxICON_INFORMATION);
02030         }
02031         SetGuiLevel(m_guiLevel);
02032     };
02033 };
02034 
02035 void MainFrame::OnSetGuiAdvanced(wxCommandEvent & e)
02036 {
02037     GuiLevel reqGuiLevel=GetMinimumGuiLevel(pano);
02038     if(reqGuiLevel<=GUI_ADVANCED)
02039     {
02040         SetGuiLevel(GUI_ADVANCED);
02041     }
02042     else
02043     {
02044         wxMessageBox(_("Can't switch to advanced interface. The project is using translation or shear parameters.\nThese parameters are not supported in advanced interface."),
02045 #ifdef __WXMSW__
02046                      wxT("Hugin"),
02047 #else
02048                      wxT(""),
02049 #endif
02050                      wxOK | wxICON_INFORMATION);
02051         SetGuiLevel(GUI_EXPERT);
02052     };
02053 };
02054 
02055 void MainFrame::OnSetGuiExpert(wxCommandEvent & e)
02056 {
02057     SetGuiLevel(GUI_EXPERT);
02058 };
02059 
02060 void MainFrame::DisableOpenGLTools()
02061 {
02062     GetMenuBar()->Enable(XRCID("ID_SHOW_GL_PREVIEW_FRAME"), false);
02063     GetMenuBar()->Enable(XRCID("action_gui_simple"), false);
02064     GetToolBar()->EnableTool(XRCID("ID_SHOW_GL_PREVIEW_FRAME"), false); 
02065 };
02066 
02067 void MainFrame::RunAssistant(wxWindow* mainWin)
02068 {
02069     if (pano.getNrOfImages() < 2)
02070     {
02071         wxMessageBox(_("At least two images are required.\nPlease add more images."),_("Error"), wxOK, mainWin);
02072         return;
02073     }
02074 
02075     //save project into temp directory
02076     wxString tempDir= wxConfig::Get()->Read(wxT("tempDir"),wxT(""));
02077     if(!tempDir.IsEmpty())
02078     {
02079         if(tempDir.Last()!=wxFileName::GetPathSeparator())
02080         {
02081             tempDir.Append(wxFileName::GetPathSeparator());
02082         }
02083     };
02084     wxFileName scriptFileName(wxFileName::CreateTempFileName(tempDir+wxT("ha")));
02085     std::ofstream script(scriptFileName.GetFullPath().mb_str(HUGIN_CONV_FILENAME));
02086     script.exceptions ( std::ofstream::eofbit | std::ofstream::failbit | std::ofstream::badbit );
02087     HuginBase::UIntSet all;
02088     fill_set(all, 0, pano.getNrOfImages()-1);
02089     pano.printPanoramaScript(script, pano.getOptimizeVector(), pano.getOptions(), all, false);
02090     script.close();
02091 
02092     // get assistant queue
02093     const wxFileName exePath(wxStandardPaths::Get().GetExecutablePath());
02094     HuginQueue::CommandQueue* commands = HuginQueue::GetAssistantCommandQueue(pano, exePath.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR), scriptFileName.GetFullPath());
02095     //execute queue
02096     int ret = MyExecuteCommandQueue(commands, mainWin, _("Running assistant"));
02097 
02098     //read back panofile
02099     PanoCommand::GlobalCmdHist::getInstance().addCommand(new PanoCommand::wxLoadPTProjectCmd(pano,
02100         (const char *)scriptFileName.GetFullPath().mb_str(HUGIN_CONV_FILENAME), 
02101         (const char *)scriptFileName.GetPath(wxPATH_NATIVE | wxPATH_GET_SEPARATOR).mb_str(HUGIN_CONV_FILENAME), 
02102         ret==0, false));
02103 
02104     //delete temporary files
02105     wxRemoveFile(scriptFileName.GetFullPath());
02106     //if return value is non-zero, an error occurred in the assistant
02107     if(ret!=0)
02108     {
02109         //check for unconnected images
02110         HuginGraph::ImageGraph graph(pano);
02111         const HuginGraph::ImageGraph::Components comps = graph.GetComponents();
02112         if(comps.size() > 1)
02113         {
02114             // switch to images panel.
02115             unsigned i1 = *(comps[0].rbegin());
02116             unsigned i2 = *(comps[1].begin());
02117             ShowCtrlPointEditor( i1, i2);
02118             // display message box with 
02119             wxMessageBox(wxString::Format(_("Warning %d unconnected image groups found:"), comps.size()) + Components2Str(comps) + wxT("\n")
02120                 + _("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);
02121             return;
02122         };
02123         wxMessageBox(_("The assistant did not complete successfully. Please check the resulting project file."),
02124                      _("Warning"),wxOK | wxICON_INFORMATION, mainWin); 
02125     };
02126 };
02127 
02128 void MainFrame::OnRunAssistant(wxCommandEvent & e)
02129 {
02130     RunAssistant(this);
02131 };
02132 
02133 void MainFrame::OnSendToAssistantQueue(wxCommandEvent &e)
02134 {
02135     wxCommandEvent dummy;
02136     OnSaveProject(dummy);
02137     wxString projectFile = getProjectName();
02138     if(wxFileName::FileExists(projectFile))
02139     {
02140 #if defined __WXMAC__ && defined MAC_SELF_CONTAINED_BUNDLE
02141         // Original patch for OSX by Charlie Reiman dd. 18 June 2011
02142         // Slightly modified by HvdW. Errors in here are mine, not Charlie's. 
02143         FSRef appRef;
02144         FSRef actuallyLaunched;
02145         OSStatus err;
02146         FSRef documentArray[1]; // Don't really need an array if we only have 1 item
02147         LSLaunchFSRefSpec launchSpec;
02148         Boolean  isDir;
02149 
02150         err = LSFindApplicationForInfo(kLSUnknownCreator,
02151                                        CFSTR("net.sourceforge.hugin.PTBatcherGUI"),
02152                                        NULL,
02153                                        &appRef,
02154                                        NULL);
02155         if (err != noErr)
02156         {
02157             // error, can't find PTBatcherGUI
02158             wxMessageBox(wxString::Format(_("External program %s not found in the bundle, reverting to system path"), wxT("open")), _("Error"));
02159             // Possibly a silly attempt otherwise the previous would have worked as well, but just try it.
02160             wxExecute(_T("open -b net.sourceforge.hugin.PTBatcherGUI ")+hugin_utils::wxQuoteFilename(projectFile));
02161             return;
02162         }
02163 
02164         wxCharBuffer projectFilebuffer=projectFile.ToUTF8();
02165         // Point to document
02166         err = FSPathMakeRef((unsigned char*) projectFilebuffer.data(), &documentArray[0], &isDir);
02167         if (err != noErr || isDir)
02168         {
02169             // Something went wrong.
02170             wxMessageBox(wxString::Format(_("Project file not found"), wxT("open")), _("Error"));
02171             return;
02172         }
02173         launchSpec.appRef = &appRef;
02174         launchSpec.numDocs = sizeof(documentArray)/sizeof(documentArray[0]);
02175         launchSpec.itemRefs = documentArray;
02176         launchSpec.passThruParams = NULL;
02177         launchSpec.launchFlags = kLSLaunchDontAddToRecents + kLSLaunchDontSwitch;
02178         launchSpec.asyncRefCon = NULL;
02179 
02180         err = LSOpenFromRefSpec(&launchSpec, &actuallyLaunched);
02181         if (err != noErr && err != kLSLaunchInProgressErr)
02182         {  
02183             // Should be ok if it's in progress... I think. 
02184             // Launch failed.
02185             wxMessageBox(wxString::Format(_("Can't launch PTBatcherGui"), wxT("open")), _("Error"));
02186             return;
02187         }
02188 
02189         // Should verify that actuallyLaunched and appRef are the same.
02190         if (FSCompareFSRefs(&appRef, &actuallyLaunched) != noErr)
02191         {
02192             // error, lauched the wrong thing.
02193             wxMessageBox(wxString::Format(_("Launched incorrect programme"), wxT("open")), _("Error"));
02194             return;
02195         }
02196 #else
02197         const wxFileName exePath(wxStandardPaths::Get().GetExecutablePath());
02198         wxExecute(exePath.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR) + wxT("PTBatcherGUI -a ")+hugin_utils::wxQuoteFilename(projectFile));
02199 #endif
02200     }
02201 };
02202 
02203 wxString MainFrame::GetCurrentOptimizerString()
02204 {
02205     return images_panel->GetCurrentOptimizerString();
02206 };
02207 
02208 MainFrame * MainFrame::m_this = 0;

Generated on 10 Feb 2016 for Hugintrunk by  doxygen 1.4.7