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