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

Generated on 22 May 2018 for Hugintrunk by  doxygen 1.4.7