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 
44 #include <tiffio.h>
45 
46 // somewhere SetDesc gets defined.. this breaks wx/cmdline.h on OSX
47 #ifdef SetDesc
48 #undef SetDesc
49 #endif
50 
51 #include <wx/cmdline.h>
52 
53 class RunStitchFrame: public wxFrame
54 {
55 public:
56  RunStitchFrame(wxWindow * parent, const wxString& title, const wxPoint& pos, const wxSize& size);
57 
58  bool StitchProject(const wxString& scriptFile, const wxString& outname, const wxString& userDefinedOutput, bool doDeleteOnExit);
59 
60  void OnQuit(wxCommandEvent& event);
61  void OnAbout(wxCommandEvent& event);
62  void OnProgress(wxCommandEvent& event);
64  void SetOverwrite(bool doOverwrite);
65 
66 private:
67 
68  bool m_isStitching;
69  wxString m_scriptFile;
71  wxGauge* m_progress;
72 
73  void OnProcessTerminate(wxProcessEvent & event);
74  void OnCancel(wxCommandEvent & event);
75 
77 
78  DECLARE_EVENT_TABLE()
79 };
80 
81 // event ID's for RunStitchPanel
82 enum
83 {
84  ID_Quit = 1,
86 };
87 
88 BEGIN_EVENT_TABLE(RunStitchFrame, wxFrame)
89  EVT_MENU(ID_Quit, RunStitchFrame::OnQuit)
90  EVT_MENU(ID_About, RunStitchFrame::OnAbout)
91  EVT_BUTTON(wxID_CANCEL, RunStitchFrame::OnCancel)
92  EVT_END_PROCESS(-1, RunStitchFrame::OnProcessTerminate)
93  EVT_COMMAND(wxID_ANY, EVT_QUEUE_PROGRESS, RunStitchFrame::OnProgress)
95 
96 RunStitchFrame::RunStitchFrame(wxWindow * parent, const wxString& title, const wxPoint& pos, const wxSize& size)
97  : wxFrame(parent, -1, title, pos, size), m_isStitching(false)
98 {
99  wxBoxSizer * topsizer = new wxBoxSizer( wxVERTICAL );
100  m_stitchPanel = new RunStitchPanel(this);
101 
102  topsizer->Add(m_stitchPanel, 1, wxEXPAND | wxALL, 2);
103 
104  wxBoxSizer* bottomsizer = new wxBoxSizer(wxHORIZONTAL);
105  m_progress = new wxGauge(this, wxID_ANY, 100, wxDefaultPosition, wxDefaultSize, wxGA_HORIZONTAL | wxGA_PROGRESS);
106  bottomsizer->Add(m_progress, 1, wxEXPAND | wxALL, 10);
107  bottomsizer->Add( new wxButton(this, wxID_CANCEL, _("Cancel")),
108  0, wxALL, 10);
109  topsizer->Add(bottomsizer, 0, wxEXPAND);
110 
111 #ifdef __WXMSW__
112  // wxFrame does have a strange background color on Windows..
113  this->SetBackgroundColour(m_stitchPanel->GetBackgroundColour());
114 #endif
115 
116  SetSizer( topsizer );
117 // topsizer->SetSizeHints( this ); // set size hints to honour minimum size
118  m_deleteOnExit=false;
119 }
120 
121 void RunStitchFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
122 {
123  wxMessageBox(wxString::Format(_("HuginStitchProject. Application to stitch hugin project files.\n Version: %s"), hugin_utils::GetHuginVersion().c_str()),
124  wxT("About hugin_stitch_project"),
125  wxOK | wxICON_INFORMATION );
126 }
127 void RunStitchFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
128 {
129  DEBUG_TRACE("");
130  if (m_isStitching) {
132  m_isStitching = false;
133  }
134  Close();
135 }
136 
137 void RunStitchFrame::OnCancel(wxCommandEvent& WXUNUSED(event))
138 {
139  DEBUG_TRACE("");
140  if (m_isStitching) {
142  m_isStitching = false;
143  } else {
144  Close();
145  }
146 }
147 
148 void RunStitchFrame::OnProcessTerminate(wxProcessEvent & event)
149 {
150  if (! m_isStitching) {
151  // canceled stitch
152  // TODO: Cleanup files?
153  Close();
154  } else {
155  m_isStitching = false;
156  if (event.GetExitCode() != 0)
157  {
158  if(wxMessageBox(_("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?"),
159  _("Error during stitching"), wxICON_ERROR | wxYES_NO )==wxYES)
160  {
161  wxString defaultdir = wxConfigBase::Get()->Read(wxT("/actualPath"),wxT(""));
162  wxFileDialog dlg(this,
163  _("Specify log file"),
164  defaultdir, wxT(""),
165  _("Log files (*.log)|*.log|All files (*)|*"),
166  wxFD_SAVE | wxFD_OVERWRITE_PROMPT, wxDefaultPosition);
167  dlg.SetDirectory(wxConfigBase::Get()->Read(wxT("/actualPath"),wxT("")));
168  if (dlg.ShowModal() == wxID_OK)
169  {
170  wxConfig::Get()->Write(wxT("/actualPath"), dlg.GetDirectory()); // remember for later
171  m_stitchPanel->SaveLog(dlg.GetPath());
172  };
173  }
174  } else {
175  if(m_deleteOnExit)
176  {
177  wxRemoveFile(m_scriptFile);
178  };
179  Close();
180  }
181  }
182 }
183 
184 void RunStitchFrame::OnProgress(wxCommandEvent& event)
185 {
186  if (event.GetInt() >= 0)
187  {
188  m_progress->SetValue(event.GetInt());
189  };
190 };
191 
192 bool RunStitchFrame::StitchProject(const wxString& scriptFile, const wxString& outname, const wxString& userDefinedOutput, bool doDeleteOnExit)
193 {
194  if (! m_stitchPanel->StitchProject(scriptFile, outname, userDefinedOutput)) {
195  return false;
196  }
197  m_isStitching = true;
198  m_scriptFile=scriptFile;
199  m_deleteOnExit=doDeleteOnExit;
200  return true;
201 }
202 
203 void RunStitchFrame::SetOverwrite(bool doOverwrite)
204 {
205  m_stitchPanel->SetOverwrite(doOverwrite);
206 };
207 
208 // **********************************************************************
209 
210 
215 class stitchApp : public wxApp
216 {
217 public:
218 
221  stitchApp();
222 
225  virtual ~stitchApp();
226 
229  virtual bool OnInit();
230 
232  virtual int OnExit();
233 
234 #ifdef __WXMAC__
235 
236  void MacOpenFile(const wxString &fileName);
237 #endif
238 
239 private:
240  wxLocale m_locale;
241 #ifdef __WXMAC__
242  wxString m_macFileNameToOpenOnStart;
243 #endif
244 };
245 
247 {
248  // suppress tiff warnings
249  TIFFSetWarningHandler(0);
250 
251  DEBUG_TRACE("ctor");
252 }
253 
255 {
256  DEBUG_TRACE("dtor");
257  DEBUG_TRACE("dtor end");
258 }
259 
261 {
262  // Required to access the preferences of hugin
263  SetAppName(wxT("hugin"));
264 #if defined __WXGTK__
265  CheckConfigFilename();
266 #endif
267 
268  // need to explicitly initialize locale for C++ library/runtime
269  setlocale(LC_ALL, "");
270  // initialize i18n
271 #if defined __WXMSW__
272  int localeID = wxConfigBase::Get()->Read(wxT("language"), (long) wxLANGUAGE_DEFAULT);
273  m_locale.Init(localeID);
274 #else
275  m_locale.Init(wxLANGUAGE_DEFAULT);
276 #endif
277 
278  // setup the environment for the different operating systems
279 #if defined __WXMSW__
280  wxFileName exePath(wxStandardPaths::Get().GetExecutablePath());
281  exePath.RemoveLastDir();
282  // locale setup
283  m_locale.AddCatalogLookupPathPrefix(exePath.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR) + wxT("share\\locale"));
284 
285 #elif defined UNIX_SELF_CONTAINED_BUNDLE
286  // initialize paths
287  {
288  wxFileName exePath(wxStandardPaths::Get().GetExecutablePath());
289  exePath.RemoveLastDir();
290  const wxString huginRoot=exePath.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR);
291  // add the locale directory specified during configure
292  m_locale.AddCatalogLookupPathPrefix(huginRoot + wxT("share/locale"));
293  }
294 #else
295  // add the locale directory specified during configure
296  m_locale.AddCatalogLookupPathPrefix(wxT(INSTALL_LOCALE_DIR));
297 #endif
298 
299  // set the name of locale recource to look for
300  m_locale.AddCatalog(wxT("hugin"));
301 
302  // parse arguments
303  static const wxCmdLineEntryDesc cmdLineDesc[] =
304  {
305  //On wxWidgets 2.9, wide characters don't work here.
306  //On previous versions, the wxT macro is required for unicode builds.
307  { wxCMD_LINE_SWITCH, "h", "help", "show this help message",
308  wxCMD_LINE_VAL_NONE, wxCMD_LINE_OPTION_HELP },
309  { wxCMD_LINE_OPTION, "o", "output", "output prefix" },
310  { wxCMD_LINE_SWITCH, "d", "delete", "delete pto file after stitching" },
311  { wxCMD_LINE_SWITCH, "w", "overwrite", "overwrite existing files" },
312  { wxCMD_LINE_OPTION, "u", "user-defined-output", "use user defined output" },
313  { wxCMD_LINE_PARAM, NULL, NULL, "<project>",
314  wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL },
315  { wxCMD_LINE_NONE }
316  };
317 
318  wxCmdLineParser parser(cmdLineDesc, argc, argv);
319 
320  switch ( parser.Parse() ) {
321  case -1: // -h or --help was given, and help displayed so exit
322  return false;
323  break;
324  case 0: // all is well
325  break;
326  default:
327  wxLogError(_("Syntax error in parameters detected, aborting."));
328  return false;
329  break;
330  }
331 
332  wxString scriptFile;
333 #ifdef __WXMAC__
334  m_macFileNameToOpenOnStart = wxT("");
335  wxYield();
336  scriptFile = m_macFileNameToOpenOnStart;
337 
338  // bring myself front (for being called from command line)
339  {
340  ProcessSerialNumber selfPSN;
341  OSErr err = GetCurrentProcess(&selfPSN);
342  if (err == noErr)
343  {
344  SetFrontProcess(&selfPSN);
345  }
346  }
347 #endif
348 
349  wxString userDefinedOutput;
350  parser.Found(wxT("u"), &userDefinedOutput);
351  if (!userDefinedOutput.IsEmpty())
352  {
353  if (!wxFileName::FileExists(userDefinedOutput))
354  {
355  wxMessageBox(wxString::Format(_("Could not find the specified user output file \"%s\"."), userDefinedOutput.c_str()),
356  _("Error"), wxOK | wxICON_EXCLAMATION);
357  return false;
358  };
359  };
360  if( parser.GetParamCount() == 0 && wxIsEmpty(scriptFile))
361  {
362  wxString defaultdir = wxConfigBase::Get()->Read(wxT("/actualPath"),wxT(""));
363  wxFileDialog dlg(0,
364  _("Specify project source project file"),
365  defaultdir, wxT(""),
366  _("Project files (*.pto)|*.pto|All files (*)|*"),
367  wxFD_OPEN, wxDefaultPosition);
368 
369  dlg.SetDirectory(wxConfigBase::Get()->Read(wxT("/actualPath"),wxT("")));
370  if (dlg.ShowModal() == wxID_OK) {
371  wxConfig::Get()->Write(wxT("/actualPath"), dlg.GetDirectory()); // remember for later
372  scriptFile = dlg.GetPath();
373  } else { // bail
374  return false;
375  }
376  } else if(wxIsEmpty(scriptFile)) {
377  scriptFile = parser.GetParam(0);
378  std::cout << "********************* script file: " << (const char *)scriptFile.mb_str(wxConvLocal) << std::endl;
379  if (! wxIsAbsolutePath(scriptFile)) {
380  scriptFile = wxGetCwd() + wxFileName::GetPathSeparator() + scriptFile;
381  }
382  }
383 
384  std::cout << "input file is " << (const char *)scriptFile.mb_str(wxConvLocal) << std::endl;
385 
386  wxString outname;
387 
388  if ( !parser.Found(wxT("o"), &outname) ) {
389  // ask for output.
390  wxFileDialog dlg(0,_("Specify output prefix"),
391  wxConfigBase::Get()->Read(wxT("/actualPath"),wxT("")),
392  wxT(""), wxT(""),
393  wxFD_SAVE, wxDefaultPosition);
394  dlg.SetDirectory(wxConfigBase::Get()->Read(wxT("/actualPath"),wxT("")));
395  if (dlg.ShowModal() == wxID_OK) {
396  while(containsInvalidCharacters(dlg.GetPath()))
397  {
398  wxMessageBox(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().c_str()),
399  _("Error"),wxOK | wxICON_EXCLAMATION);
400  if(dlg.ShowModal()!=wxID_OK)
401  return false;
402  };
403  wxFileName prefix(dlg.GetPath());
404  while (!prefix.IsDirWritable())
405  {
406  wxMessageBox(wxString::Format(_("You have no permissions to write in folder \"%s\".\nPlease select another folder for the final output."), prefix.GetPath().c_str()),
407 #ifdef __WXMSW__
408  wxT("Hugin_stitch_project"),
409 #else
410  wxT(""),
411 #endif
412  wxOK | wxICON_INFORMATION);
413  if (dlg.ShowModal() != wxID_OK)
414  {
415  return false;
416  };
417  prefix = dlg.GetPath();
418  };
419 
420  wxConfig::Get()->Write(wxT("/actualPath"), dlg.GetDirectory()); // remember for later
421  outname = dlg.GetPath();
422  } else { // bail
423 // wxLogError( _("No project files specified"));
424  return false;
425  }
426  }
427 
428  // check output filename
429  wxFileName outfn(outname);
430  wxString ext = outfn.GetExt();
431  // remove extension if it indicates an image file
432  if (ext.CmpNoCase(wxT("jpg")) == 0 || ext.CmpNoCase(wxT("jpeg")) == 0||
433  ext.CmpNoCase(wxT("tif")) == 0|| ext.CmpNoCase(wxT("tiff")) == 0 ||
434  ext.CmpNoCase(wxT("png")) == 0 || ext.CmpNoCase(wxT("exr")) == 0 ||
435  ext.CmpNoCase(wxT("pnm")) == 0 || ext.CmpNoCase(wxT("hdr")))
436  {
437  outfn.ClearExt();
438  outname = outfn.GetFullPath();
439  }
440 
441  RunStitchFrame *frame = new RunStitchFrame(NULL, wxT("Hugin Stitcher"), wxDefaultPosition, wxSize(640,600) );
442  frame->Show( true );
443  SetTopWindow( frame );
444 
445  wxFileName basename(scriptFile);
446  frame->SetTitle(wxString::Format(_("%s - Stitching"), basename.GetName().c_str()));
447  frame->SetOverwrite(parser.Found(wxT("w")));
448  bool n = frame->StitchProject(scriptFile, outname, userDefinedOutput, parser.Found(wxT("d")));
449  return n;
450 }
451 
452 
454 {
455  DEBUG_TRACE("");
456  return 0;
457 }
458 
459 
460 #ifdef __WXMAC__
461 // wx calls this method when the app gets "Open file" AppleEvent
462 void stitchApp::MacOpenFile(const wxString &fileName)
463 {
464  m_macFileNameToOpenOnStart = fileName;
465 }
466 #endif
467 
468 // make wxwindows use this class as the main application
469 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
END_EVENT_TABLE()
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:502
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:487
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
void OnProgress(wxCommandEvent &event)