Hugintrunk  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
hugin_stitch_project.cpp
Go to the documentation of this file.
1 // -*- c-basic-offset: 4 -*-
2 
27 #include <hugin_config.h>
28 #include "panoinc_WX.h"
29 #include "panoinc.h"
30 
31 #include <wx/wfstream.h>
32 #if defined __WXMSW__ || defined UNIX_SELF_CONTAINED_BUNDLE
33 #include <wx/stdpaths.h>
34 #endif
35 
36 #include <fstream>
37 #include <sstream>
38 #include "base_wx/RunStitchPanel.h"
39 #include "base_wx/huginConfig.h"
41 #include "base_wx/platform.h"
42 #include "base_wx/wxPlatform.h"
43 #include "base_wx/wxutils.h"
44 
45 #include <tiffio.h>
46 
47 // somewhere SetDesc gets defined.. this breaks wx/cmdline.h on OSX
48 #ifdef SetDesc
49 #undef SetDesc
50 #endif
51 
52 #include <wx/cmdline.h>
53 
54 class RunStitchFrame: public wxFrame
55 {
56 public:
57  RunStitchFrame(wxWindow * parent, const wxString& title, const wxPoint& pos, const wxSize& size);
58 
59  bool StitchProject(const wxString& scriptFile, const wxString& outname, const wxString& userDefinedOutput, bool doDeleteOnExit);
60 
61  void OnQuit(wxCommandEvent& event);
62  void OnAbout(wxCommandEvent& event);
63  void OnProgress(wxCommandEvent& event);
65  void SetOverwrite(bool doOverwrite);
66 
67 private:
68 
69  bool m_isStitching;
70  wxString m_scriptFile;
72  wxGauge* m_progress;
73 
74  void OnProcessTerminate(wxProcessEvent & event);
75  void OnCancel(wxCommandEvent & event);
76 
78 };
79 
80 // event ID's for RunStitchPanel
81 enum
82 {
83  ID_Quit = 1,
85 };
86 
87 RunStitchFrame::RunStitchFrame(wxWindow * parent, const wxString& title, const wxPoint& pos, const wxSize& size)
88  : wxFrame(parent, -1, title, pos, size), m_isStitching(false)
89 {
90  wxBoxSizer * topsizer = new wxBoxSizer( wxVERTICAL );
91  m_stitchPanel = new RunStitchPanel(this);
92 
93  topsizer->Add(m_stitchPanel, 1, wxEXPAND | wxALL, 2);
94 
95  wxBoxSizer* bottomsizer = new wxBoxSizer(wxHORIZONTAL);
96  m_progress = new wxGauge(this, wxID_ANY, 100, wxDefaultPosition, wxDefaultSize, wxGA_HORIZONTAL | wxGA_PROGRESS);
97  bottomsizer->Add(m_progress, 1, wxEXPAND | wxALL, 10);
98  bottomsizer->Add( new wxButton(this, wxID_CANCEL, _("Cancel")),
99  0, wxALL, 10);
100  topsizer->Add(bottomsizer, 0, wxEXPAND);
101 
102 #ifdef __WXMSW__
103  // wxFrame does have a strange background color on Windows..
104  this->SetBackgroundColour(m_stitchPanel->GetBackgroundColour());
105 #endif
106 
107  // setup the environment for the different operating systems
108  wxInitAllImageHandlers();
109 #if defined __WXMSW__
110  wxFileName exePath(wxStandardPaths::Get().GetExecutablePath());
111  exePath.RemoveLastDir();
112  wxIconBundle myIcons(exePath.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR) + "share\\hugin\\xrc\\data\\hugin.ico", wxBITMAP_TYPE_ICO);
113  SetIcons(myIcons);
114 #else
115  wxString xrcPrefix;
116 #if defined __WXMAC__ && defined MAC_SELF_CONTAINED_BUNDLE
117  {
118  wxString exec_path = MacGetPathToBundledResourceFile(CFSTR("xrc"));
119  if (!exec_path.IsEmpty())
120  {
121  xrcPrefix = exec_path + "/";
122  }
123  else
124  {
125  hugin_utils::HuginMessageBox(_("xrc directory not found in bundle"), _("Hugin_stitch_project"), wxOK | wxICON_ERROR, wxGetActiveWindow());
126  }
127  }
128 #elif defined UNIX_SELF_CONTAINED_BUNDLE
129  // initialize paths
130  {
131  wxFileName exePath(wxStandardPaths::Get().GetExecutablePath());
132  exePath.RemoveLastDir();
133  const wxString huginRoot(exePath.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR));
134  xrcPrefix = huginRoot + "share/hugin/xrc/";
135  }
136 #else
137  // add the locale directory specified during configure
138  xrcPrefix = INSTALL_XRC_DIR;
139 #endif
140  if (!xrcPrefix.IsEmpty())
141  {
142  wxIcon myIcon(xrcPrefix + "data/hugin.png", wxBITMAP_TYPE_PNG);
143  SetIcon(myIcon);
144  }
145 #endif
146 
147  SetSizer( topsizer );
148 // topsizer->SetSizeHints( this ); // set size hints to honour minimum size
149  m_deleteOnExit=false;
150  // bind event handler
151  Bind(wxEVT_MENU, &RunStitchFrame::OnQuit, this, ID_Quit);
152  Bind(wxEVT_MENU, &RunStitchFrame::OnAbout, this, ID_About);
153  Bind(wxEVT_BUTTON, &RunStitchFrame::OnCancel, this, wxID_CANCEL);
154  Bind(wxEVT_END_PROCESS, &RunStitchFrame::OnProcessTerminate, this);
155  Bind(EVT_QUEUE_PROGRESS, &RunStitchFrame::OnProgress, this);
156 
157 }
158 
159 void RunStitchFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
160 {
161  hugin_utils::HuginMessageBox(wxString::Format(_("HuginStitchProject. Application to stitch hugin project files.\n Version: %s"), hugin_utils::GetHuginVersion()),
162  _("Hugin_stitch_project"), wxOK | wxICON_INFORMATION, this);
163 }
164 void RunStitchFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
165 {
166  DEBUG_TRACE("");
167  if (m_isStitching) {
169  m_isStitching = false;
170  }
171  Close();
172 }
173 
174 void RunStitchFrame::OnCancel(wxCommandEvent& WXUNUSED(event))
175 {
176  DEBUG_TRACE("");
177  if (m_isStitching) {
179  m_isStitching = false;
180  } else {
181  Close();
182  }
183 }
184 
185 void RunStitchFrame::OnProcessTerminate(wxProcessEvent & event)
186 {
187  if (! m_isStitching) {
188  // canceled stitch
189  // TODO: Cleanup files?
190  Close();
191  } else {
192  m_isStitching = false;
193  if (event.GetExitCode() != 0)
194  {
195  if (hugin_utils::HuginMessageBox(_("Error during stitching\nPlease report the complete text to the bug tracker on https://bugs.launchpad.net/hugin.\n\nDo you want to save the log file?"),
196  _("Hugin_stitch_project"), wxICON_ERROR | wxYES_NO, this) == wxYES)
197  {
198  wxString defaultdir = wxConfigBase::Get()->Read("/actualPath",wxEmptyString);
199  wxFileDialog dlg(this,
200  _("Specify log file"),
201  defaultdir, wxEmptyString,
202  _("Log files (*.log)|*.log|All files (*)|*"),
203  wxFD_SAVE | wxFD_OVERWRITE_PROMPT, wxDefaultPosition);
204  dlg.SetDirectory(wxConfigBase::Get()->Read("/actualPath",wxEmptyString));
205  if (dlg.ShowModal() == wxID_OK)
206  {
207  wxConfig::Get()->Write("/actualPath", dlg.GetDirectory()); // remember for later
208  m_stitchPanel->SaveLog(dlg.GetPath());
209  };
210  }
211  } else {
212  if(m_deleteOnExit)
213  {
214  wxRemoveFile(m_scriptFile);
215  };
216  Close();
217  }
218  }
219 }
220 
221 void RunStitchFrame::OnProgress(wxCommandEvent& event)
222 {
223  if (event.GetInt() >= 0)
224  {
225  m_progress->SetValue(event.GetInt());
226  };
227 };
228 
229 bool RunStitchFrame::StitchProject(const wxString& scriptFile, const wxString& outname, const wxString& userDefinedOutput, bool doDeleteOnExit)
230 {
231  if (! m_stitchPanel->StitchProject(scriptFile, outname, userDefinedOutput)) {
232  return false;
233  }
234  m_isStitching = true;
235  m_scriptFile=scriptFile;
236  m_deleteOnExit=doDeleteOnExit;
237  return true;
238 }
239 
240 void RunStitchFrame::SetOverwrite(bool doOverwrite)
241 {
242  m_stitchPanel->SetOverwrite(doOverwrite);
243 };
244 
245 // **********************************************************************
246 
247 
252 class stitchApp : public wxApp
253 {
254 public:
255 
258  stitchApp();
259 
262  virtual ~stitchApp();
263 
266  virtual bool OnInit();
267 
269  virtual int OnExit();
270 
271 #ifdef __WXMAC__
272 
273  void MacOpenFile(const wxString &fileName);
274 #endif
275 
276 private:
277  wxLocale m_locale;
278 #ifdef __WXMAC__
279  wxString m_macFileNameToOpenOnStart;
280 #endif
281 };
282 
284 {
285  // suppress tiff warnings
286  TIFFSetWarningHandler(0);
287 
288  DEBUG_TRACE("ctor");
289 }
290 
292 {
293  DEBUG_TRACE("dtor");
294  DEBUG_TRACE("dtor end");
295 }
296 
298 {
299  // Required to access the preferences of hugin
300  SetAppName("hugin");
301 #if defined __WXMSW__ && wxCHECK_VERSION(3,3,0)
302  // automatically switch between light and dark mode
303  SetAppearance(Appearance::System);
304 #endif
305 #if defined __WXGTK__
306  CheckConfigFilename();
307 #endif
308 
309  // need to explicitly initialize locale for C++ library/runtime
310  setlocale(LC_ALL, "");
311  // initialize i18n
312 #if defined __WXMSW__
313  int localeID = wxConfigBase::Get()->Read("language", (long) wxLANGUAGE_DEFAULT);
314  m_locale.Init(localeID);
315 #else
316  m_locale.Init(wxLANGUAGE_DEFAULT);
317 #endif
318 
319  // setup the environment for the different operating systems
320 #if defined __WXMSW__
321  wxFileName exePath(wxStandardPaths::Get().GetExecutablePath());
322  exePath.RemoveLastDir();
323  // locale setup
324  m_locale.AddCatalogLookupPathPrefix(exePath.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR) + "share\\locale");
325 
326 #elif defined UNIX_SELF_CONTAINED_BUNDLE
327  // initialize paths
328  {
329  wxFileName exePath(wxStandardPaths::Get().GetExecutablePath());
330  exePath.RemoveLastDir();
331  const wxString huginRoot=exePath.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR);
332  // add the locale directory specified during configure
333  m_locale.AddCatalogLookupPathPrefix(huginRoot + "share/locale");
334  }
335 #else
336  // add the locale directory specified during configure
337  m_locale.AddCatalogLookupPathPrefix(INSTALL_LOCALE_DIR);
338 #endif
339 
340  // set the name of locale recource to look for
341  m_locale.AddCatalog("hugin");
342 
343  // parse arguments
344  static const wxCmdLineEntryDesc cmdLineDesc[] =
345  {
346  //On wxWidgets 2.9, wide characters don't work here.
347  //On previous versions, the wxT macro is required for unicode builds.
348  { wxCMD_LINE_SWITCH, "h", "help", "show this help message",
349  wxCMD_LINE_VAL_NONE, wxCMD_LINE_OPTION_HELP },
350  { wxCMD_LINE_OPTION, "o", "output", "output prefix" },
351  { wxCMD_LINE_SWITCH, "d", "delete", "delete pto file after stitching" },
352  { wxCMD_LINE_SWITCH, "w", "overwrite", "overwrite existing files" },
353  { wxCMD_LINE_OPTION, "u", "user-defined-output", "use user defined output" },
354  { wxCMD_LINE_PARAM, NULL, NULL, "<project>",
355  wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL },
356  { wxCMD_LINE_NONE }
357  };
358 
359  wxCmdLineParser parser(cmdLineDesc, argc, argv);
360 
361  switch ( parser.Parse() ) {
362  case -1: // -h or --help was given, and help displayed so exit
363  return false;
364  break;
365  case 0: // all is well
366  break;
367  default:
368  wxLogError(_("Syntax error in parameters detected, aborting."));
369  return false;
370  break;
371  }
372 
373  wxString scriptFile;
374 #ifdef __WXMAC__
375  m_macFileNameToOpenOnStart = wxEmptyString;
376  wxYield();
377  scriptFile = m_macFileNameToOpenOnStart;
378 
379  // bring myself front (for being called from command line)
380  {
381  ProcessSerialNumber selfPSN;
382  OSErr err = GetCurrentProcess(&selfPSN);
383  if (err == noErr)
384  {
385  SetFrontProcess(&selfPSN);
386  }
387  }
388 #endif
389 
390  wxString userDefinedOutput;
391  parser.Found("u", &userDefinedOutput);
392  if (!userDefinedOutput.IsEmpty())
393  {
394  if (!wxFileName::FileExists(userDefinedOutput))
395  {
396  hugin_utils::HuginMessageBox(wxString::Format(_("Could not find the specified user output file \"%s\"."), userDefinedOutput),
397  _("Hugin_stitch_project"), wxOK | wxICON_EXCLAMATION, wxGetActiveWindow());
398  return false;
399  };
400  };
401  if( parser.GetParamCount() == 0 && wxIsEmpty(scriptFile))
402  {
403  wxString defaultdir = wxConfigBase::Get()->Read("/actualPath",wxEmptyString);
404  wxFileDialog dlg(0,
405  _("Specify project source project file"),
406  defaultdir, wxEmptyString,
407  _("Project files (*.pto)|*.pto|All files (*)|*"),
408  wxFD_OPEN, wxDefaultPosition);
409 
410  dlg.SetDirectory(wxConfigBase::Get()->Read("/actualPath",wxEmptyString));
411  if (dlg.ShowModal() == wxID_OK) {
412  wxConfig::Get()->Write("/actualPath", dlg.GetDirectory()); // remember for later
413  scriptFile = dlg.GetPath();
414  } else { // bail
415  return false;
416  }
417  } else if(wxIsEmpty(scriptFile)) {
418  scriptFile = parser.GetParam(0);
419  std::cout << "********************* script file: " << (const char *)scriptFile.mb_str(wxConvLocal) << std::endl;
420  if (! wxIsAbsolutePath(scriptFile)) {
421  scriptFile = wxGetCwd() + wxFileName::GetPathSeparator() + scriptFile;
422  }
423  }
424 
425  std::cout << "input file is " << (const char *)scriptFile.mb_str(wxConvLocal) << std::endl;
426 
427  wxString outname;
428 
429  if ( !parser.Found("o", &outname) ) {
430  // ask for output.
431  wxFileDialog dlg(0,_("Specify output prefix"),
432  wxConfigBase::Get()->Read("/actualPath",wxEmptyString),
433  wxEmptyString, wxEmptyString,
434  wxFD_SAVE, wxDefaultPosition);
435  dlg.SetDirectory(wxConfigBase::Get()->Read("/actualPath",wxEmptyString));
436  if (dlg.ShowModal() == wxID_OK) {
437  while(containsInvalidCharacters(dlg.GetPath()))
438  {
439  hugin_utils::HuginMessageBox(wxString::Format(_("The given filename contains one of the following invalid characters: %s\nHugin can not work with this filename. Please enter a valid filename."), getInvalidCharacters()),
440  _("Hugin_stitch_project"), wxOK | wxICON_EXCLAMATION, wxGetActiveWindow());
441  if(dlg.ShowModal()!=wxID_OK)
442  return false;
443  };
444  wxFileName prefix(dlg.GetPath());
445  while (!prefix.IsDirWritable())
446  {
447  hugin_utils::HuginMessageBox(wxString::Format(_("You have no permissions to write in folder \"%s\".\nPlease select another folder for the final output."), prefix.GetPath().c_str()),
448  _("Hugin_stitch_project"), wxOK | wxICON_INFORMATION, wxGetActiveWindow());
449  if (dlg.ShowModal() != wxID_OK)
450  {
451  return false;
452  };
453  prefix = dlg.GetPath();
454  };
455 
456  wxConfig::Get()->Write("/actualPath", dlg.GetDirectory()); // remember for later
457  outname = dlg.GetPath();
458  } else { // bail
459 // wxLogError( _("No project files specified"));
460  return false;
461  }
462  }
463 
464  // check output filename
465  wxFileName outfn(outname);
466  wxString ext = outfn.GetExt();
467  // remove extension if it indicates an image file
468  if (ext.CmpNoCase("jpg") == 0 || ext.CmpNoCase("jpeg") == 0||
469  ext.CmpNoCase("tif") == 0|| ext.CmpNoCase("tiff") == 0 ||
470  ext.CmpNoCase("png") == 0 || ext.CmpNoCase("exr") == 0 ||
471  ext.CmpNoCase("pnm") == 0 || ext.CmpNoCase("hdr"))
472  {
473  outfn.ClearExt();
474  outname = outfn.GetFullPath();
475  }
476 
477  RunStitchFrame *frame = new RunStitchFrame(NULL, "Hugin Stitcher", wxDefaultPosition, wxSize(640,600) );
478  frame->Show( true );
479  SetTopWindow( frame );
480 
481  wxFileName basename(scriptFile);
482  frame->SetTitle(wxString::Format(_("%s - Stitching"), basename.GetName().c_str()));
483  frame->SetOverwrite(parser.Found("w"));
484  bool n = frame->StitchProject(scriptFile, outname, userDefinedOutput, parser.Found("d"));
485  return n;
486 }
487 
488 
490 {
491  DEBUG_TRACE("");
492  return 0;
493 }
494 
495 
496 #ifdef __WXMAC__
497 // wx calls this method when the app gets "Open file" AppleEvent
498 void stitchApp::MacOpenFile(const wxString &fileName)
499 {
500  m_macFileNameToOpenOnStart = fileName;
501 }
502 #endif
503 
504 // make wxwindows use this class as the main application
505 IMPLEMENT_APP(stitchApp)
RunStitchFrame(wxWindow *parent, const wxString &title, const wxPoint &pos, const wxSize &size)
implementation of huginApp Class
bool FileExists(const std::string &filename)
checks if file exists
Definition: utils.cpp:362
void OnCancel(wxCommandEvent &event)
Cancels project execution - kills process.
void OnProcessTerminate(wxProcessEvent &event)
RunStitchPanel * m_stitchPanel
bool StitchProject(const wxString &scriptFile, const wxString &outname, const wxString &userDefinedOutput=wxEmptyString)
#define DEBUG_TRACE(msg)
Definition: utils.h:67
include file for the hugin project
virtual ~stitchApp()
dtor.
bool StitchProject(wxString scriptFile, wxString outname, wxString userDefinedOutput=wxEmptyString)
Starts stitching of project file.
bool SaveLog(const wxString &filename)
save the content of the window into a given log file
void OnAbout(wxCommandEvent &event)
void OnQuit(wxCommandEvent &event)
The application class for hugin_stitch_project.
include file for the hugin project
void SetOverwrite(bool over=true)
bool containsInvalidCharacters(const wxString stringToTest)
returns true, if the given strings contains invalid characters
Definition: platform.cpp:511
std::string GetHuginVersion()
return a string with version numbers
Definition: utils.cpp:907
functions for interaction with the hugin configuration file
platform/compiler specific stuff.
const wxString getInvalidCharacters()
returns all invalid characters for the filename (mainly characters, which does not work with gnu make...
Definition: platform.cpp:496
virtual bool OnInit()
pseudo constructor.
virtual int OnExit()
just for testing purposes
void SetOverwrite(bool doOverwrite)
sets, if existing output file should be automatic overwritten
int HuginMessageBox(const wxString &message, const wxString &caption, int style, wxWindow *parent)
Definition: wxutils.cpp:176
void OnProgress(wxCommandEvent &event)