MainFrame.cpp

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

Generated on 24 Nov 2017 for Hugintrunk by  doxygen 1.4.7