Hugintrunk  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PTBatcherGUI.cpp
Go to the documentation of this file.
1 // -*- c-basic-offset: 4 -*-
2 
27 #include "PTBatcherGUI.h"
28 #include <wx/cshelp.h>
29 #if defined __WXMSW__ || defined UNIX_SELF_CONTAINED_BUNDLE
30 #include <wx/stdpaths.h>
31 #endif
32 #include "lensdb/LensDB.h"
33 
34 // make wxwindows use this class as the main application
35 #if defined USE_GDKBACKEND_X11
36 // wxWidgets does not support wxTaskBarIcon::IsAvailable on Wayland
37 // so until it is fixed upstream enforce using x11 backendj
38 // see ticket http://trac.wxwidgets.org/ticket/17779
39 #warning Using Hugin with hard coded GDK_BACKEND=x11
40 wxIMPLEMENT_WX_THEME_SUPPORT
41 wxIMPLEMENT_APP_NO_MAIN(PTBatcherGUI);
42 #include <stdlib.h>
43 int main(int argc, char **argv)
44 {
45  wxDISABLE_DEBUG_SUPPORT();
46  char backend[]="GDK_BACKEND=x11";
47  putenv(backend);
48  return wxEntry(argc, argv);
49 };
50 #else
52 #endif
53 
54 BEGIN_EVENT_TABLE(PTBatcherGUI, wxApp)
55  EVT_LIST_ITEM_ACTIVATED(XRCID("project_listbox"),PTBatcherGUI::OnItemActivated)
57 
58 bool PTBatcherGUI::OnInit()
59 {
60 #if wxUSE_ON_FATAL_EXCEPTION
61  wxHandleFatalExceptions();
62 #endif
63  // Required to access the preferences of hugin
64  SetAppName(wxT("hugin"));
65 #if defined __WXGTK__ && wxCHECK_VERSION(3,1,1)
66  CheckConfigFilename();
67 #endif
68 
69  // need to explicitly initialize locale for C++ library/runtime
70  setlocale(LC_ALL, "");
71 #if defined __WXMSW__
72  int localeID = wxConfigBase::Get()->Read(wxT("language"), (long) wxLANGUAGE_DEFAULT);
73  m_locale.Init(localeID);
74 #else
75  m_locale.Init(wxLANGUAGE_DEFAULT);
76 #endif
77  // initialize help provider
78  wxHelpControllerHelpProvider* provider = new wxHelpControllerHelpProvider;
79  wxHelpProvider::Set(provider);
80 
81  // setup the environment for the different operating systems
82 #if defined __WXMSW__
83  wxFileName exePath(wxStandardPaths::Get().GetExecutablePath());
84  exePath.RemoveLastDir();
85  const wxString huginRoot(exePath.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR));
86  m_xrcPrefix = huginRoot + wxT("share\\hugin\\xrc\\");
87 
88  // locale setup
89  m_locale.AddCatalogLookupPathPrefix(huginRoot + wxT("share\\locale"));
90 #elif defined __WXMAC__ && defined MAC_SELF_CONTAINED_BUNDLE
91  {
92  wxString exec_path = MacGetPathToBundledResourceFile(CFSTR("xrc"));
93  if(exec_path != wxT(""))
94  {
95  m_xrcPrefix = exec_path + wxT("/");
96  }
97  else
98  {
99  wxMessageBox(_("xrc directory not found in bundle"), _("Fatal Error"));
100  return false;
101  }
102 
103  }
104 
105 #elif defined UNIX_SELF_CONTAINED_BUNDLE
106  // initialize paths
107  {
108  wxFileName exePath(wxStandardPaths::Get().GetExecutablePath());
109  exePath.RemoveLastDir();
110  const wxString huginRoot(exePath.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR));
111  m_xrcPrefix = huginRoot + wxT("share/hugin/xrc/");
112 
113  // locale setup
114  m_locale.AddCatalogLookupPathPrefix(huginRoot + wxT("share/locale"));
115  }
116 #else
117  // add the locale directory specified during configure
118  m_xrcPrefix = wxT(INSTALL_XRC_DIR);
119  m_locale.AddCatalogLookupPathPrefix(wxT(INSTALL_LOCALE_DIR));
120 #endif
121 
122  // set the name of locale recource to look for
123  m_locale.AddCatalog(wxT("hugin"));
124 
125  const wxString name = wxString::Format(_T("PTBatcherGUI-%s"), wxGetUserId().c_str());
126  m_checker = new wxSingleInstanceChecker(name+wxT(".lock"),wxFileName::GetTempDir());
127  bool IsFirstInstance=(!m_checker->IsAnotherRunning());
128 
129  if(IsFirstInstance)
130  {
131  if ( ! wxFile::Exists(m_xrcPrefix + wxT("/batch_frame.xrc")) )
132  {
133  wxMessageBox(_("xrc directory not found, hugin needs to be properly installed\nTried Path:") + m_xrcPrefix , _("Fatal Error"));
134  return false;
135  }
136  // initialize image handlers
137  wxInitAllImageHandlers();
138 
139  // Initialize all the XRC handlers.
140  wxXmlResource::Get()->InitAllHandlers();
141  wxXmlResource::Get()->AddHandler(new ProjectListBoxXmlHandler());
142  // load XRC files
143  wxXmlResource::Get()->Load(m_xrcPrefix + wxT("batch_frame.xrc"));
144  wxXmlResource::Get()->Load(m_xrcPrefix + wxT("batch_toolbar.xrc"));
145  wxXmlResource::Get()->Load(m_xrcPrefix + wxT("batch_menu.xrc"));
146  wxXmlResource::Get()->Load(m_xrcPrefix + wxT("lensdb_dialogs.xrc"));
147  wxXmlResource::Get()->Load(m_xrcPrefix + wxT("dlg_warning.xrc"));
148  };
149 
150  // parse arguments
151  static const wxCmdLineEntryDesc cmdLineDesc[] =
152  {
153  {
154  wxCMD_LINE_SWITCH, "h", "help", "show this help message",
155  wxCMD_LINE_VAL_NONE, wxCMD_LINE_OPTION_HELP
156  },
157  { wxCMD_LINE_SWITCH, "b", "batch", "run batch immediately" },
158  { wxCMD_LINE_SWITCH, "o", "overwrite", "overwrite previous files without asking" },
159  { wxCMD_LINE_SWITCH, "s", "shutdown", "shutdown computer after batch is complete" },
160  { wxCMD_LINE_SWITCH, "v", "verbose", "show verbose output when processing projects" },
161  { wxCMD_LINE_SWITCH, "a", "assistant", "run the assistant on the given projects" },
162  { wxCMD_LINE_OPTION, "u", "user-defined", "use the given user defined sequence" },
163  {
164  wxCMD_LINE_PARAM, NULL, NULL, "stitch_project.pto [output prefix]|assistant_project.pto",
165  wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL + wxCMD_LINE_PARAM_MULTIPLE
166  },
167  { wxCMD_LINE_NONE }
168  };
169  wxCmdLineParser parser(cmdLineDesc, argc, argv);
170 
171  switch ( parser.Parse() )
172  {
173  case -1: // -h or --help was given, and help displayed so exit
174  return false;
175  break;
176  case 0: // all is well
177  break;
178  default:
179  wxLogError(_("Syntax error in parameters detected, aborting."));
180  return false;
181  break;
182  }
183 
184  wxClient client;
185  wxConnectionBase* conn;
186  wxString servername;
187 #ifdef _WIN32
188  servername=name;
189 #else
190  servername=wxFileName::GetTempDir()+wxFileName::GetPathSeparator()+name+wxT(".ipc");
191 #endif
192  if(IsFirstInstance)
193  {
194  m_frame = new BatchFrame(&m_locale,m_xrcPrefix);
195  m_frame->RestoreSize();
196  // init help system
197  provider->SetHelpController(&m_frame->GetHelpController());
198 #ifdef __WXMSW__
199  m_frame->GetHelpController().Initialize(m_xrcPrefix + wxT("data/hugin_help_en_EN.chm"));
200 #else
201 #if wxUSE_WXHTML_HELP
202  // using wxHtmlHelpController
203 #if defined __WXMAC__ && defined MAC_SELF_CONTAINED_BUNDLE
204  // On Mac, xrc/data/help_LOCALE should be in the bundle as LOCALE.lproj/help
205  // which we can rely on the operating sytem to pick the right locale's.
206  wxString strFile = MacGetPathToBundledResourceFile(CFSTR("help"));
207  if (!strFile.IsEmpty())
208  {
209  m_frame->GetHelpController().AddBook(wxFileName(strFile + wxT("/hugin_help_en_EN.hhp")));
210  }
211  else
212  {
213  wxLogError(wxString::Format(wxT("Could not find help directory in the bundle"), strFile.c_str()));
214  return false;
215  }
216 #else
217  m_frame->GetHelpController().AddBook(wxFileName(m_xrcPrefix + wxT("data/help_en_EN/hugin_help_en_EN.hhp")));
218 #endif
219 #else
220  // using wxExtHelpController
221  m_frame->GetHelpController().Initialize(Initialize(m_xrcPrefix + wxT("data/help_en_EN")));
222 #endif
223 #endif
224 
225  SetTopWindow(m_frame);
226  if(!(m_frame->IsStartedMinimized()))
227  {
228  m_frame->Show(true);
229  }
230  else
231  {
232  m_frame->SetStatusInformation(_("PTBatcherGUI started"));
233  };
234  m_server = new BatchIPCServer();
235  if (!m_server->Create(servername))
236  {
237  delete m_server;
238  m_server = NULL;
239  };
240  }
241  else
242  {
243  conn=client.MakeConnection(wxEmptyString, servername, IPC_START);
244  if(!conn)
245  {
246  return false;
247  }
248  };
249 
250  size_t count = 0;
251  if (parser.Found(wxT("a")))
252  {
253  //added assistant files
254  wxString userDefined;
255  parser.Found(wxT("u"), &userDefined);
256  while (parser.GetParamCount() > count)
257  {
258  wxString param = parser.GetParam(count);
259  count++;
260  wxFileName name(param);
261  name.MakeAbsolute();
262  if (name.FileExists())
263  {
264  //only add existing pto files
265  if (name.GetExt().CmpNoCase(wxT("pto")) == 0)
266  {
267  if (IsFirstInstance)
268  {
269  m_frame->AddToList(name.GetFullPath(), Project::DETECTING, userDefined);
270  }
271  else
272  {
273  conn->Request(wxT("D ") + name.GetFullPath());
274  if (!userDefined.IsEmpty())
275  {
276  conn->Request(wxT("U ") + userDefined);
277  };
278  };
279  };
280  };
281  };
282  }
283  else
284  {
285  bool projectSpecified = false;
286  wxString userDefined;
287  parser.Found(wxT("u"), &userDefined);
288  //we collect all parameters - all project files <and their output prefixes>
289  while (parser.GetParamCount() > count)
290  {
291  wxString param = parser.GetParam(count);
292  count++;
293  if (!projectSpecified) //next parameter must be new script file
294  {
295  wxFileName name(param);
296  name.MakeAbsolute();
297  if (IsFirstInstance)
298  {
299  m_frame->AddToList(name.GetFullPath(), Project::STITCHING, userDefined);
300  }
301  else
302  {
303  conn->Request(wxT("A ") + name.GetFullPath());
304  if (!userDefined.IsEmpty())
305  {
306  conn->Request(wxT("U ") + userDefined);
307  };
308  }
309  projectSpecified = true;
310  }
311  else //parameter could be previous project's output prefix
312  {
313  wxFileName fn(param);
314  fn.MakeAbsolute();
315  if (!fn.HasExt()) //if there is no extension we have a prefix
316  {
317  if (IsFirstInstance)
318  {
319  m_frame->ChangePrefix(-1, fn.GetFullPath());
320  }
321  else
322  {
323  conn->Request(wxT("P ") + fn.GetFullPath());
324  };
325  projectSpecified = false;
326  }
327  else
328  {
329  wxString ext = fn.GetExt();
330  //we may still have a prefix, but with added image extension
331  if (ext.CmpNoCase(wxT("jpg")) == 0 || ext.CmpNoCase(wxT("jpeg")) == 0 ||
332  ext.CmpNoCase(wxT("tif")) == 0 || ext.CmpNoCase(wxT("tiff")) == 0 ||
333  ext.CmpNoCase(wxT("png")) == 0 || ext.CmpNoCase(wxT("exr")) == 0 ||
334  ext.CmpNoCase(wxT("pnm")) == 0 || ext.CmpNoCase(wxT("hdr")) == 0)
335  {
336  //extension will be removed before stitch, so there is no need to do it now
337  if (IsFirstInstance)
338  {
339  m_frame->ChangePrefix(-1, fn.GetFullPath());
340  }
341  else
342  {
343  conn->Request(wxT("P ") + fn.GetFullPath());
344  };
345  projectSpecified = false;
346  }
347  else //if parameter has a different extension we presume it is a new script file
348  {
349  //we add the new project
350  if (IsFirstInstance)
351  {
352  m_frame->AddToList(fn.GetFullPath(), Project::STITCHING, userDefined);
353  }
354  else
355  {
356  conn->Request(wxT("A ") + fn.GetFullPath());
357  if (!userDefined.IsEmpty())
358  {
359  conn->Request(wxT("U ") + userDefined);
360  };
361  }
362  projectSpecified = true;
363  }
364  } //else of if(!fn.HasExt())
365  }
366  }
367  };
368 
369  if(IsFirstInstance)
370  {
371  wxConfigBase* config=wxConfigBase::Get();
372  if (parser.Found(wxT("s")))
373  {
374  config->DeleteEntry(wxT("/BatchFrame/ShutdownCheck"));
375 #if !defined __WXMAC__ && !defined __WXOSX_COCOA__
376  // wxMac has not wxShutdown
377  config->Write(wxT("/BatchFrame/AtEnd"), static_cast<long>(Batch::SHUTDOWN));
378 #endif
379  }
380  if (parser.Found(wxT("o")))
381  {
382  config->Write(wxT("/BatchFrame/OverwriteCheck"), 1l);
383  }
384  if (parser.Found(wxT("v")))
385  {
386  config->Write(wxT("/BatchFrame/VerboseCheck"), 1l);
387  }
388  config->Flush();
389  }
390  else
391  {
392  if (parser.Found(wxT("s")))
393  {
394 #if !defined __WXMAC__ && !defined __WXOSX_COCOA__
395  // wxMac has not wxShutdown
396  conn->Request(wxT("SetShutdownCheck"));
397 #endif
398  }
399  if (parser.Found(wxT("o")))
400  {
401  conn->Request(wxT("SetOverwriteCheck"));
402  }
403  if (parser.Found(wxT("v")))
404  {
405  conn->Request(wxT("SetVerboseCheck"));
406  }
407  conn->Request(wxT("BringWindowToTop"));
408  if(parser.Found(wxT("b")))
409  {
410  conn->Request(wxT("RunBatch"));
411  }
412  conn->Disconnect();
413  delete conn;
414  delete m_checker;
415  return false;
416  };
417  m_frame->SetCheckboxes();
418  m_frame->PropagateDefaults();
419  //deactivate verbose output if started minimized
420  if(m_frame->IsStartedMinimized())
421  {
422  m_frame->SetInternalVerbose(false);
423  };
424  if (parser.Found(wxT("b")) )
425  {
426  m_frame->RunBatch();
427  }
428 #ifdef __WXMAC__
429  // if there are command line parameters they are handled all by the code above
430  // but wxMac calls also MacOpenFiles after OnInit with the command line
431  // parameters again, so the files get added twice. To prevent this we
432  // reset the internal file list for MacOpenFiles here
433  // but we need to process the files when PTBatcherGUI is called from finder
434  // with an open files AppleEvent, in this case the argv is empty (except argc[0])
435  // and we don't want to skip the MacOpenFile function
436  if (argc > 1)
437  {
438  wxArrayString emptyFiles;
439  OSXStoreOpenFiles(emptyFiles);
440  };
441 #endif
442  return true;
443 }
444 
446 {
448  delete m_checker;
449  delete m_server;
450  delete wxHelpProvider::Set(NULL);
451  return 0;
452 }
453 
454 #if wxUSE_ON_FATAL_EXCEPTION
455 void PTBatcherGUI::OnFatalException()
456 {
457  GenerateReport(wxDebugReport::Context_Exception);
458 };
459 #endif
460 
461 void PTBatcherGUI::OnItemActivated(wxListEvent& event)
462 {
463  wxCommandEvent dummy;
465 }
466 
467 #ifdef __WXMAC__
468 // wx calls this method when the app gets "Open files" AppleEvent
469 void PTBatcherGUI::MacOpenFiles(const wxArrayString &fileNames)
470 {
471  if(m_frame)
472  {
473  for (int i = 0; i < fileNames.GetCount(); ++i)
474  {
475  wxFileName fn(fileNames[i]);
476  m_frame->AddToList(fn.GetFullPath());
477  };
478  };
479 }
480 #endif
481 
482 const void* BatchIPCConnection::OnRequest(const wxString& topic, const wxString& item, size_t* size, wxIPCFormat format)
483 {
484  *size=wxNO_LEN;
485  BatchFrame* MyBatchFrame=wxGetApp().GetFrame();
486  if(item.Left(1)==wxT("A"))
487  {
488  MyBatchFrame->AddToList(item.Mid(2));
489  return wxEmptyString;
490  };
491  if(item.Left(1)==wxT("D"))
492  {
493  MyBatchFrame->AddToList(item.Mid(2), Project::DETECTING);
494  return wxEmptyString;
495  };
496  if(item.Left(1)==wxT("P"))
497  {
498  MyBatchFrame->ChangePrefix(-1,item.Mid(2));
499  return wxEmptyString;
500  };
501  if (item.Left(1) == wxT("U"))
502  {
503  MyBatchFrame->ChangeUserDefined(-1, item.Mid(2));
504  return wxEmptyString;
505  };
506  wxCommandEvent event;
507  event.SetInt(1);
508 #if !defined __WXMAC__ && !defined __WXOSX_COCOA__
509  // wxMac has not wxShutdown
510  if(item==wxT("SetShutdownCheck"))
511  if (MyBatchFrame->GetEndTask()!=Batch::SHUTDOWN)
512  {
513  wxCommandEvent choiceEvent;
514  choiceEvent.SetInt(Batch::SHUTDOWN);
515  MyBatchFrame->OnChoiceEnd(choiceEvent);
516  MyBatchFrame->SetCheckboxes();
517  };
518 #endif
519  if(item==wxT("SetOverwriteCheck"))
520  if(!MyBatchFrame->GetCheckOverwrite())
521  {
522  MyBatchFrame->OnCheckOverwrite(event);
523  MyBatchFrame->SetCheckboxes();
524  };
525  if(item==wxT("SetVerboseCheck"))
526  if(!MyBatchFrame->GetCheckVerbose())
527  {
528  MyBatchFrame->OnCheckVerbose(event);
529  MyBatchFrame->SetCheckboxes();
530  };
531  if(item==wxT("BringWindowToTop"))
532  {
533  MyBatchFrame->RequestUserAttention();
534  }
535  if(item==wxT("RunBatch"))
536  {
537  wxCommandEvent myEvent(wxEVT_COMMAND_TOOL_CLICKED ,XRCID("tool_start"));
538  MyBatchFrame->GetEventHandler()->AddPendingEvent(myEvent);
539  };
540  return wxEmptyString;
541 };
542 
543 wxConnectionBase* BatchIPCServer::OnAcceptConnection (const wxString& topic)
544 {
545  if(topic==IPC_START)
546  {
547  return new BatchIPCConnection;
548  }
549  return NULL;
550 };
void ChangePrefix(int index, wxString newPrefix)
Definition: BatchFrame.cpp:597
wxIMPLEMENT_APP(huginApp)
const wxString IPC_START(wxT("BatchStart"))
topic name for BatchIPCConnection and BatchIPCServer
BatchFrame * m_frame
Definition: PTBatcherGUI.h:101
Batch::EndTask GetEndTask()
return which task should be executed at end
virtual const void * OnRequest(const wxString &topic, const wxString &item, size_t *size=NULL, wxIPCFormat format=wxIPC_TEXT)
request handler for transfer
void AddToList(wxString aFile, Project::Target target=Project::STITCHING, wxString userDefined=wxEmptyString)
Definition: BatchFrame.cpp:489
bool GetCheckOverwrite()
return if overwrite checkbox is checked
END_EVENT_TABLE()
static void Clean()
cleanup the static LensDB instance, must be called at the end of the program
Definition: LensDB.cpp:2010
virtual wxConnectionBase * OnAcceptConnection(const wxString &topic)
accept connection handler (establish the connection)
Batch processor for Hugin with GUI.
class to access Hugins camera and lens database
server which implements the communication between different PTBatcherGUI instances (see BatchIPCConne...
Definition: PTBatcherGUI.h:62
The application class for hugin_stitch_project.
Definition: PTBatcherGUI.h:76
void ChangeUserDefined(int index, wxString newUserDefined)
Definition: BatchFrame.cpp:612
void OnCheckVerbose(wxCommandEvent &event)
void OnCheckOverwrite(wxCommandEvent &event)
void OnButtonOpenWithHugin(wxCommandEvent &event)
Definition: BatchFrame.cpp:751
virtual int OnExit()
void OnChoiceEnd(wxCommandEvent &event)
wxSingleInstanceChecker * m_checker
Definition: PTBatcherGUI.h:112
void SetCheckboxes()
void OnItemActivated(wxListEvent &event)
class for communication between different PTBatcherGUI instances
Definition: PTBatcherGUI.h:54
BatchIPCServer * m_server
Definition: PTBatcherGUI.h:113
bool GetCheckVerbose()
return if verbose checkbox is checked
int main(int argc, char *argv[])
Definition: Main.cpp:167