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