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  return false;
127  }
128  }
129 #elif defined UNIX_SELF_CONTAINED_BUNDLE
130  // initialize paths
131  {
132  wxFileName exePath(wxStandardPaths::Get().GetExecutablePath());
133  exePath.RemoveLastDir();
134  const wxString huginRoot(exePath.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR));
135  xrcPrefix = huginRoot + "share/hugin/xrc/";
136  }
137 #else
138  // add the locale directory specified during configure
139  xrcPrefix = INSTALL_XRC_DIR;
140 #endif
141  wxIcon myIcon(xrcPrefix + "data/hugin.png", wxBITMAP_TYPE_PNG);
142  SetIcon(myIcon);
143 #endif
144 
145  SetSizer( topsizer );
146 // topsizer->SetSizeHints( this ); // set size hints to honour minimum size
147  m_deleteOnExit=false;
148  // bind event handler
149  Bind(wxEVT_MENU, &RunStitchFrame::OnQuit, this, ID_Quit);
150  Bind(wxEVT_MENU, &RunStitchFrame::OnAbout, this, ID_About);
151  Bind(wxEVT_BUTTON, &RunStitchFrame::OnCancel, this, wxID_CANCEL);
152  Bind(wxEVT_END_PROCESS, &RunStitchFrame::OnProcessTerminate, this);
153  Bind(EVT_QUEUE_PROGRESS, &RunStitchFrame::OnProgress, this);
154 
155 }
156 
157 void RunStitchFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
158 {
159  hugin_utils::HuginMessageBox(wxString::Format(_("HuginStitchProject. Application to stitch hugin project files.\n Version: %s"), hugin_utils::GetHuginVersion()),
160  _("Hugin_stitch_project"), wxOK | wxICON_INFORMATION, this);
161 }
162 void RunStitchFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
163 {
164  DEBUG_TRACE("");
165  if (m_isStitching) {
167  m_isStitching = false;
168  }
169  Close();
170 }
171 
172 void RunStitchFrame::OnCancel(wxCommandEvent& WXUNUSED(event))
173 {
174  DEBUG_TRACE("");
175  if (m_isStitching) {
177  m_isStitching = false;
178  } else {
179  Close();
180  }
181 }
182 
183 void RunStitchFrame::OnProcessTerminate(wxProcessEvent & event)
184 {
185  if (! m_isStitching) {
186  // canceled stitch
187  // TODO: Cleanup files?
188  Close();
189  } else {
190  m_isStitching = false;
191  if (event.GetExitCode() != 0)
192  {
193  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?"),
194  _("Hugin_stitch_project"), wxICON_ERROR | wxYES_NO, this) == wxYES)
195  {
196  wxString defaultdir = wxConfigBase::Get()->Read("/actualPath",wxEmptyString);
197  wxFileDialog dlg(this,
198  _("Specify log file"),
199  defaultdir, wxEmptyString,
200  _("Log files (*.log)|*.log|All files (*)|*"),
201  wxFD_SAVE | wxFD_OVERWRITE_PROMPT, wxDefaultPosition);
202  dlg.SetDirectory(wxConfigBase::Get()->Read("/actualPath",wxEmptyString));
203  if (dlg.ShowModal() == wxID_OK)
204  {
205  wxConfig::Get()->Write("/actualPath", dlg.GetDirectory()); // remember for later
206  m_stitchPanel->SaveLog(dlg.GetPath());
207  };
208  }
209  } else {
210  if(m_deleteOnExit)
211  {
212  wxRemoveFile(m_scriptFile);
213  };
214  Close();
215  }
216  }
217 }
218 
219 void RunStitchFrame::OnProgress(wxCommandEvent& event)
220 {
221  if (event.GetInt() >= 0)
222  {
223  m_progress->SetValue(event.GetInt());
224  };
225 };
226 
227 bool RunStitchFrame::StitchProject(const wxString& scriptFile, const wxString& outname, const wxString& userDefinedOutput, bool doDeleteOnExit)
228 {
229  if (! m_stitchPanel->StitchProject(scriptFile, outname, userDefinedOutput)) {
230  return false;
231  }
232  m_isStitching = true;
233  m_scriptFile=scriptFile;
234  m_deleteOnExit=doDeleteOnExit;
235  return true;
236 }
237 
238 void RunStitchFrame::SetOverwrite(bool doOverwrite)
239 {
240  m_stitchPanel->SetOverwrite(doOverwrite);
241 };
242 
243 // **********************************************************************
244 
245 
250 class stitchApp : public wxApp
251 {
252 public:
253 
256  stitchApp();
257 
260  virtual ~stitchApp();
261 
264  virtual bool OnInit();
265 
267  virtual int OnExit();
268 
269 #ifdef __WXMAC__
270 
271  void MacOpenFile(const wxString &fileName);
272 #endif
273 
274 private:
275  wxLocale m_locale;
276 #ifdef __WXMAC__
277  wxString m_macFileNameToOpenOnStart;
278 #endif
279 };
280 
282 {
283  // suppress tiff warnings
284  TIFFSetWarningHandler(0);
285 
286  DEBUG_TRACE("ctor");
287 }
288 
290 {
291  DEBUG_TRACE("dtor");
292  DEBUG_TRACE("dtor end");
293 }
294 
296 {
297  // Required to access the preferences of hugin
298  SetAppName("hugin");
299 #if defined __WXMSW__ && wxCHECK_VERSION(3,3,0)
300  // automatically switch between light and dark mode
301  SetAppearance(Appearance::System);
302 #endif
303 #if defined __WXGTK__
304  CheckConfigFilename();
305 #endif
306 
307  // need to explicitly initialize locale for C++ library/runtime
308  setlocale(LC_ALL, "");
309  // initialize i18n
310 #if defined __WXMSW__
311  int localeID = wxConfigBase::Get()->Read("language", (long) wxLANGUAGE_DEFAULT);
312  m_locale.Init(localeID);
313 #else
314  m_locale.Init(wxLANGUAGE_DEFAULT);
315 #endif
316 
317  // setup the environment for the different operating systems
318 #if defined __WXMSW__
319  wxFileName exePath(wxStandardPaths::Get().GetExecutablePath());
320  exePath.RemoveLastDir();
321  // locale setup
322  m_locale.AddCatalogLookupPathPrefix(exePath.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR) + "share\\locale");
323 
324 #elif defined UNIX_SELF_CONTAINED_BUNDLE
325  // initialize paths
326  {
327  wxFileName exePath(wxStandardPaths::Get().GetExecutablePath());
328  exePath.RemoveLastDir();
329  const wxString huginRoot=exePath.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR);
330  // add the locale directory specified during configure
331  m_locale.AddCatalogLookupPathPrefix(huginRoot + "share/locale");
332  }
333 #else
334  // add the locale directory specified during configure
335  m_locale.AddCatalogLookupPathPrefix(INSTALL_LOCALE_DIR);
336 #endif
337 
338  // set the name of locale recource to look for
339  m_locale.AddCatalog("hugin");
340 
341  // parse arguments
342  static const wxCmdLineEntryDesc cmdLineDesc[] =
343  {
344  //On wxWidgets 2.9, wide characters don't work here.
345  //On previous versions, the wxT macro is required for unicode builds.
346  { wxCMD_LINE_SWITCH, "h", "help", "show this help message",
347  wxCMD_LINE_VAL_NONE, wxCMD_LINE_OPTION_HELP },
348  { wxCMD_LINE_OPTION, "o", "output", "output prefix" },
349  { wxCMD_LINE_SWITCH, "d", "delete", "delete pto file after stitching" },
350  { wxCMD_LINE_SWITCH, "w", "overwrite", "overwrite existing files" },
351  { wxCMD_LINE_OPTION, "u", "user-defined-output", "use user defined output" },
352  { wxCMD_LINE_PARAM, NULL, NULL, "<project>",
353  wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL },
354  { wxCMD_LINE_NONE }
355  };
356 
357  wxCmdLineParser parser(cmdLineDesc, argc, argv);
358 
359  switch ( parser.Parse() ) {
360  case -1: // -h or --help was given, and help displayed so exit
361  return false;
362  break;
363  case 0: // all is well
364  break;
365  default:
366  wxLogError(_("Syntax error in parameters detected, aborting."));
367  return false;
368  break;
369  }
370 
371  wxString scriptFile;
372 #ifdef __WXMAC__
373  m_macFileNameToOpenOnStart = wxEmptyString;
374  wxYield();
375  scriptFile = m_macFileNameToOpenOnStart;
376 
377  // bring myself front (for being called from command line)
378  {
379  ProcessSerialNumber selfPSN;
380  OSErr err = GetCurrentProcess(&selfPSN);
381  if (err == noErr)
382  {
383  SetFrontProcess(&selfPSN);
384  }
385  }
386 #endif
387 
388  wxString userDefinedOutput;
389  parser.Found("u", &userDefinedOutput);
390  if (!userDefinedOutput.IsEmpty())
391  {
392  if (!wxFileName::FileExists(userDefinedOutput))
393  {
394  hugin_utils::HuginMessageBox(wxString::Format(_("Could not find the specified user output file \"%s\"."), userDefinedOutput),
395  _("Hugin_stitch_project"), wxOK | wxICON_EXCLAMATION, wxGetActiveWindow());
396  return false;
397  };
398  };
399  if( parser.GetParamCount() == 0 && wxIsEmpty(scriptFile))
400  {
401  wxString defaultdir = wxConfigBase::Get()->Read("/actualPath",wxEmptyString);
402  wxFileDialog dlg(0,
403  _("Specify project source project file"),
404  defaultdir, wxEmptyString,
405  _("Project files (*.pto)|*.pto|All files (*)|*"),
406  wxFD_OPEN, wxDefaultPosition);
407 
408  dlg.SetDirectory(wxConfigBase::Get()->Read("/actualPath",wxEmptyString));
409  if (dlg.ShowModal() == wxID_OK) {
410  wxConfig::Get()->Write("/actualPath", dlg.GetDirectory()); // remember for later
411  scriptFile = dlg.GetPath();
412  } else { // bail
413  return false;
414  }
415  } else if(wxIsEmpty(scriptFile)) {
416  scriptFile = parser.GetParam(0);
417  std::cout << "********************* script file: " << (const char *)scriptFile.mb_str(wxConvLocal) << std::endl;
418  if (! wxIsAbsolutePath(scriptFile)) {
419  scriptFile = wxGetCwd() + wxFileName::GetPathSeparator() + scriptFile;
420  }
421  }
422 
423  std::cout << "input file is " << (const char *)scriptFile.mb_str(wxConvLocal) << std::endl;
424 
425  wxString outname;
426 
427  if ( !parser.Found("o", &outname) ) {
428  // ask for output.
429  wxFileDialog dlg(0,_("Specify output prefix"),
430  wxConfigBase::Get()->Read("/actualPath",wxEmptyString),
431  wxEmptyString, wxEmptyString,
432  wxFD_SAVE, wxDefaultPosition);
433  dlg.SetDirectory(wxConfigBase::Get()->Read("/actualPath",wxEmptyString));
434  if (dlg.ShowModal() == wxID_OK) {
435  while(containsInvalidCharacters(dlg.GetPath()))
436  {
437  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()),
438  _("Hugin_stitch_project"), wxOK | wxICON_EXCLAMATION, wxGetActiveWindow());
439  if(dlg.ShowModal()!=wxID_OK)
440  return false;
441  };
442  wxFileName prefix(dlg.GetPath());
443  while (!prefix.IsDirWritable())
444  {
445  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()),
446  _("Hugin_stitch_project"), wxOK | wxICON_INFORMATION, wxGetActiveWindow());
447  if (dlg.ShowModal() != wxID_OK)
448  {
449  return false;
450  };
451  prefix = dlg.GetPath();
452  };
453 
454  wxConfig::Get()->Write("/actualPath", dlg.GetDirectory()); // remember for later
455  outname = dlg.GetPath();
456  } else { // bail
457 // wxLogError( _("No project files specified"));
458  return false;
459  }
460  }
461 
462  // check output filename
463  wxFileName outfn(outname);
464  wxString ext = outfn.GetExt();
465  // remove extension if it indicates an image file
466  if (ext.CmpNoCase("jpg") == 0 || ext.CmpNoCase("jpeg") == 0||
467  ext.CmpNoCase("tif") == 0|| ext.CmpNoCase("tiff") == 0 ||
468  ext.CmpNoCase("png") == 0 || ext.CmpNoCase("exr") == 0 ||
469  ext.CmpNoCase("pnm") == 0 || ext.CmpNoCase("hdr"))
470  {
471  outfn.ClearExt();
472  outname = outfn.GetFullPath();
473  }
474 
475  RunStitchFrame *frame = new RunStitchFrame(NULL, "Hugin Stitcher", wxDefaultPosition, wxSize(640,600) );
476  frame->Show( true );
477  SetTopWindow( frame );
478 
479  wxFileName basename(scriptFile);
480  frame->SetTitle(wxString::Format(_("%s - Stitching"), basename.GetName().c_str()));
481  frame->SetOverwrite(parser.Found("w"));
482  bool n = frame->StitchProject(scriptFile, outname, userDefinedOutput, parser.Found("d"));
483  return n;
484 }
485 
486 
488 {
489  DEBUG_TRACE("");
490  return 0;
491 }
492 
493 
494 #ifdef __WXMAC__
495 // wx calls this method when the app gets "Open file" AppleEvent
496 void stitchApp::MacOpenFile(const wxString &fileName)
497 {
498  m_macFileNameToOpenOnStart = fileName;
499 }
500 #endif
501 
502 // make wxwindows use this class as the main application
503 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:510
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:495
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)