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