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  else
227  {
228  m_frame->SetStatusInformation(_("PTBatcherGUI started"));
229  };
230  m_server = new BatchIPCServer();
231  if (!m_server->Create(servername))
232  {
233  delete m_server;
234  m_server = NULL;
235  };
236  }
237  else
238  {
239  conn=client.MakeConnection(wxEmptyString, servername, IPC_START);
240  if(!conn)
241  {
242  return false;
243  }
244  };
245 
246  size_t count = 0;
247  if (parser.Found(wxT("a")))
248  {
249  //added assistant files
250  wxString userDefined;
251  parser.Found(wxT("u"), &userDefined);
252  while (parser.GetParamCount() > count)
253  {
254  wxString param = parser.GetParam(count);
255  count++;
256  wxFileName name(param);
257  name.MakeAbsolute();
258  if (name.FileExists())
259  {
260  //only add existing pto files
261  if (name.GetExt().CmpNoCase(wxT("pto")) == 0)
262  {
263  if (IsFirstInstance)
264  {
265  m_frame->AddToList(name.GetFullPath(), Project::DETECTING, userDefined);
266  }
267  else
268  {
269  conn->Request(wxT("D ") + name.GetFullPath());
270  if (!userDefined.IsEmpty())
271  {
272  conn->Request(wxT("U ") + userDefined);
273  };
274  };
275  };
276  };
277  };
278  }
279  else
280  {
281  bool projectSpecified = false;
282  wxString userDefined;
283  parser.Found(wxT("u"), &userDefined);
284  //we collect all parameters - all project files <and their output prefixes>
285  while (parser.GetParamCount() > count)
286  {
287  wxString param = parser.GetParam(count);
288  count++;
289  if (!projectSpecified) //next parameter must be new script file
290  {
291  wxFileName name(param);
292  name.MakeAbsolute();
293  if (IsFirstInstance)
294  {
295  m_frame->AddToList(name.GetFullPath(), Project::STITCHING, userDefined);
296  }
297  else
298  {
299  conn->Request(wxT("A ") + name.GetFullPath());
300  if (!userDefined.IsEmpty())
301  {
302  conn->Request(wxT("U ") + userDefined);
303  };
304  }
305  projectSpecified = true;
306  }
307  else //parameter could be previous project's output prefix
308  {
309  wxFileName fn(param);
310  fn.MakeAbsolute();
311  if (!fn.HasExt()) //if there is no extension we have a prefix
312  {
313  if (IsFirstInstance)
314  {
315  m_frame->ChangePrefix(-1, fn.GetFullPath());
316  }
317  else
318  {
319  conn->Request(wxT("P ") + fn.GetFullPath());
320  };
321  projectSpecified = false;
322  }
323  else
324  {
325  wxString ext = fn.GetExt();
326  //we may still have a prefix, but with added image extension
327  if (ext.CmpNoCase(wxT("jpg")) == 0 || ext.CmpNoCase(wxT("jpeg")) == 0 ||
328  ext.CmpNoCase(wxT("tif")) == 0 || ext.CmpNoCase(wxT("tiff")) == 0 ||
329  ext.CmpNoCase(wxT("png")) == 0 || ext.CmpNoCase(wxT("exr")) == 0 ||
330  ext.CmpNoCase(wxT("pnm")) == 0 || ext.CmpNoCase(wxT("hdr")) == 0)
331  {
332  //extension will be removed before stitch, so there is no need to do it now
333  if (IsFirstInstance)
334  {
335  m_frame->ChangePrefix(-1, fn.GetFullPath());
336  }
337  else
338  {
339  conn->Request(wxT("P ") + fn.GetFullPath());
340  };
341  projectSpecified = false;
342  }
343  else //if parameter has a different extension we presume it is a new script file
344  {
345  //we add the new project
346  if (IsFirstInstance)
347  {
348  m_frame->AddToList(fn.GetFullPath(), Project::STITCHING, userDefined);
349  }
350  else
351  {
352  conn->Request(wxT("A ") + fn.GetFullPath());
353  if (!userDefined.IsEmpty())
354  {
355  conn->Request(wxT("U ") + userDefined);
356  };
357  }
358  projectSpecified = true;
359  }
360  } //else of if(!fn.HasExt())
361  }
362  }
363  };
364 
365  if(IsFirstInstance)
366  {
367  wxConfigBase* config=wxConfigBase::Get();
368  if (parser.Found(wxT("s")))
369  {
370  config->DeleteEntry(wxT("/BatchFrame/ShutdownCheck"));
371 #if !defined __WXMAC__ && !defined __WXOSX_COCOA__
372  // wxMac has not wxShutdown
373  config->Write(wxT("/BatchFrame/AtEnd"), static_cast<long>(Batch::SHUTDOWN));
374 #endif
375  }
376  if (parser.Found(wxT("o")))
377  {
378  config->Write(wxT("/BatchFrame/OverwriteCheck"), 1l);
379  }
380  if (parser.Found(wxT("v")))
381  {
382  config->Write(wxT("/BatchFrame/VerboseCheck"), 1l);
383  }
384  config->Flush();
385  }
386  else
387  {
388  if (parser.Found(wxT("s")))
389  {
390 #if !defined __WXMAC__ && !defined __WXOSX_COCOA__
391  // wxMac has not wxShutdown
392  conn->Request(wxT("SetShutdownCheck"));
393 #endif
394  }
395  if (parser.Found(wxT("o")))
396  {
397  conn->Request(wxT("SetOverwriteCheck"));
398  }
399  if (parser.Found(wxT("v")))
400  {
401  conn->Request(wxT("SetVerboseCheck"));
402  }
403  conn->Request(wxT("BringWindowToTop"));
404  if(parser.Found(wxT("b")))
405  {
406  conn->Request(wxT("RunBatch"));
407  }
408  conn->Disconnect();
409  delete conn;
410  delete m_checker;
411  return false;
412  };
415  //deactivate verbose output if started minimized
417  {
418  m_frame->SetInternalVerbose(false);
419  };
420  if (parser.Found(wxT("b")) )
421  {
422  m_frame->RunBatch();
423  }
424 #ifdef __WXMAC__
425  // if there are command line parameters they are handled all by the code above
426  // but wxMac calls also MacOpenFiles after OnInit with the command line
427  // parameters again, so the files get added twice. To prevent this we
428  // reset the internal file list for MacOpenFiles here
429  // but we need to process the files when PTBatcherGUI is called from finder
430  // with an open files AppleEvent, in this case the argv is empty (except argc[0])
431  // and we don't want to skip the MacOpenFile function
432  if (argc > 1)
433  {
434  wxArrayString emptyFiles;
435  OSXStoreOpenFiles(emptyFiles);
436  };
437 #endif
438  return true;
439 }
440 
442 {
444  delete m_checker;
445  delete m_server;
446  delete wxHelpProvider::Set(NULL);
447  return 0;
448 }
449 
450 #if wxUSE_ON_FATAL_EXCEPTION
451 void PTBatcherGUI::OnFatalException()
452 {
453  GenerateReport(wxDebugReport::Context_Exception);
454 };
455 #endif
456 
457 #ifdef __WXMAC__
458 // wx calls this method when the app gets "Open files" AppleEvent
459 void PTBatcherGUI::MacOpenFiles(const wxArrayString &fileNames)
460 {
461  if(m_frame)
462  {
463  for (int i = 0; i < fileNames.GetCount(); ++i)
464  {
465  wxFileName fn(fileNames[i]);
466  m_frame->AddToList(fn.GetFullPath());
467  };
468  };
469 }
470 #endif
471 
472 const void* BatchIPCConnection::OnRequest(const wxString& topic, const wxString& item, size_t* size, wxIPCFormat format)
473 {
474  *size=wxNO_LEN;
475  BatchFrame* MyBatchFrame=wxGetApp().GetFrame();
476  if(item.Left(1)==wxT("A"))
477  {
478  MyBatchFrame->AddToList(item.Mid(2));
479  return wxEmptyString;
480  };
481  if(item.Left(1)==wxT("D"))
482  {
483  MyBatchFrame->AddToList(item.Mid(2), Project::DETECTING);
484  return wxEmptyString;
485  };
486  if(item.Left(1)==wxT("P"))
487  {
488  MyBatchFrame->ChangePrefix(-1,item.Mid(2));
489  return wxEmptyString;
490  };
491  if (item.Left(1) == wxT("U"))
492  {
493  MyBatchFrame->ChangeUserDefined(-1, item.Mid(2));
494  return wxEmptyString;
495  };
496  wxCommandEvent event;
497  event.SetInt(1);
498 #if !defined __WXMAC__ && !defined __WXOSX_COCOA__
499  // wxMac has not wxShutdown
500  if(item==wxT("SetShutdownCheck"))
501  if (MyBatchFrame->GetEndTask()!=Batch::SHUTDOWN)
502  {
503  wxCommandEvent choiceEvent;
504  choiceEvent.SetInt(Batch::SHUTDOWN);
505  MyBatchFrame->OnChoiceEnd(choiceEvent);
506  MyBatchFrame->SetCheckboxes();
507  };
508 #endif
509  if(item==wxT("SetOverwriteCheck"))
510  if(!MyBatchFrame->GetCheckOverwrite())
511  {
512  MyBatchFrame->OnCheckOverwrite(event);
513  MyBatchFrame->SetCheckboxes();
514  };
515  if(item==wxT("SetVerboseCheck"))
516  if(!MyBatchFrame->GetCheckVerbose())
517  {
518  MyBatchFrame->OnCheckVerbose(event);
519  MyBatchFrame->SetCheckboxes();
520  };
521  if(item==wxT("BringWindowToTop"))
522  {
523  MyBatchFrame->RequestUserAttention();
524  }
525  if(item==wxT("RunBatch"))
526  {
527  wxCommandEvent myEvent(wxEVT_COMMAND_TOOL_CLICKED ,XRCID("tool_start"));
528  MyBatchFrame->GetEventHandler()->AddPendingEvent(myEvent);
529  };
530  return wxEmptyString;
531 };
532 
533 wxConnectionBase* BatchIPCServer::OnAcceptConnection (const wxString& topic)
534 {
535  if(topic==IPC_START)
536  {
537  return new BatchIPCConnection;
538  }
539  return NULL;
540 };
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:149
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 SetStatusInformation(wxString status)
sets status message, also updates tooltip of taskbar icon
void OnCheckOverwrite(wxCommandEvent &event)
wxHelpController & GetHelpController()
return help controller for open help
Definition: BatchFrame.h:159
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