Hugintrunk  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
RunStitchPanel.cpp
Go to the documentation of this file.
1 // -*- c-basic-offset: 4 -*-
2 
25 #include <hugin_config.h>
26 #include "panoinc_WX.h"
27 #include "panoinc.h"
28 
29 #include <wx/wfstream.h>
30 #include <wx/stdpaths.h>
31 
32 #include <fstream>
33 #include <sstream>
34 #include <vigra/error.hxx>
35 #include "base_wx/huginConfig.h"
37 #include "base_wx/Executor.h"
40 
41 #include "base_wx/platform.h"
42 #include "base_wx/wxPlatform.h"
43 
44 #include "RunStitchPanel.h"
45 
46 #include "hugin/config_defaults.h"
47 
48 // ==========================================
49 // Implementation of stitch window
50 
51 // event ID's for RunStitchPanel
52 enum
53 {
54  ID_Quit = 1,
56 };
57 
58 
59 BEGIN_EVENT_TABLE(RunStitchPanel, wxPanel)
60  EVT_END_PROCESS(-1, RunStitchPanel::OnProcessTerminate)
62 
63 RunStitchPanel::RunStitchPanel(wxWindow * parent)
64  : wxPanel(parent)
65 {
66  m_paused=false;
67  m_overwrite=false;
68  /*
69  wxMenu *menuFile = new wxMenu;
70 
71  menuFile->AppendSeparator();
72  menuFile->Append( ID_Quit, _("E&xit") );
73 
74  wxMenu *menuHelp = new wxMenu;
75  menuHelp->Append( ID_About, _("&About...") );
76 
77  wxMenuBar *menuBar = new wxMenuBar;
78  menuBar->Append( menuFile, _("&File") );
79  menuBar->Append( menuHelp, _("&Help") );
80  SetMenuBar( menuBar );
81  */
82 
83  wxBoxSizer * topsizer = new wxBoxSizer( wxVERTICAL );
84  m_execPanel = new MyExecPanel(this);
85 
86 #ifdef __WXMSW__
87  // wxFrame does have a strange background color on Windows, copy color from a child widget
88  this->SetBackgroundColour(m_execPanel->GetBackgroundColour());
89 #endif
90  topsizer->Add(m_execPanel, 1, wxEXPAND, 0);
91  SetSizer( topsizer );
92 // topsizer->SetSizeHints( this ); // set size hints to honour minimum size
93 }
94 
95 bool RunStitchPanel::StitchProject(const wxString& scriptFile, const wxString& outname, const wxString& userDefinedOutput)
96 {
97  DEBUG_TRACE("");
98  wxFileName fname(scriptFile);
99  if ( !fname.FileExists() ) {
100  wxLogError( _("Could not open project file:") + scriptFile);
101  return false;
102  }
103 
104  wxString pathToPTO;
105  wxFileName::SplitPath(scriptFile, &pathToPTO, NULL, NULL);
106  pathToPTO.Append(wxFileName::GetPathSeparator());
107 
108  std::ifstream prjfile((const char *)scriptFile.mb_str(HUGIN_CONV_FILENAME));
109  if (prjfile.bad()) {
110  wxLogError( wxString::Format(_("could not open script: %s"), scriptFile.c_str()) );
111  return false;
112  }
113  HuginBase::Panorama pano;
115  int ptoVersion = 0;
116  if (newPano.loadPTScript(prjfile, ptoVersion, (const char *)pathToPTO.mb_str(HUGIN_CONV_FILENAME))) {
117  pano.setMemento(newPano);
118  if (pano.getActiveImages().empty())
119  {
120  wxLogError(wxString::Format(_("Project %s does not contain any active images."), scriptFile.c_str()));
121  return false;
122  }
124  if (ptoVersion < 2) {
125  // no options stored in file, use default arguments in config
126 
127  wxConfig* config = new wxConfig(wxT("hugin")); //needed for PTBatcher console application
128  wxConfigBase::Set(config); //
129  opts.enblendOptions = wxConfigBase::Get()->Read(wxT("/Enblend/Args"), wxT(HUGIN_ENBLEND_ARGS)).mb_str(wxConvLocal);
130  opts.enfuseOptions = wxConfigBase::Get()->Read(wxT("/Enfuse/Args"), wxT(HUGIN_ENFUSE_ARGS)).mb_str(wxConvLocal);
131 
132  }
133  opts.remapUsingGPU = wxConfigBase::Get()->Read(wxT("/Nona/UseGPU"), HUGIN_NONA_USEGPU) == 1;
134  pano.setOptions(opts);
135  } else {
136  wxLogError( wxString::Format(_("error while parsing panotools script: %s"), scriptFile.c_str()) );
137  return false;
138  }
139  // get options and correct for correct makefile
141  if (!userDefinedOutput.IsEmpty())
142  {
143  wxFileInputStream input(userDefinedOutput);
144  if (!input.IsOk())
145  {
146  wxLogError(wxString::Format(_("Can't open user defined output sequence \"%s\"."), userDefinedOutput.c_str()));
147  return false;
148  }
149  wxFileConfig settings(input);
150  // disable cropped output if user defined setting is requesting
151  long supportsCroppedOutput;
152  settings.Read(wxT("/General/SupportsCroppedTIFF"), &supportsCroppedOutput, 1l);
153  if (supportsCroppedOutput != 1)
154  {
155  opts.tiff_saveROI = false;
156  };
157  };
159  if (opts.enblendOptions.length() == 0) {
160  // no options stored in file, use default arguments in config file
161  opts.enblendOptions = wxConfigBase::Get()->Read(wxT("/Enblend/Args"), wxT(HUGIN_ENBLEND_ARGS)).mb_str(wxConvLocal);
162  }
163  pano.setOptions(opts);
164  DEBUG_DEBUG("output file specified is " << (const char *)outname.mb_str(wxConvLocal));
165 
166  wxString basename;
167  wxString outpath;
168  wxFileName outputPrefix(outname);
169  outputPrefix.MakeAbsolute();
170  outpath = outputPrefix.GetPath();
171  basename = outputPrefix.GetFullName();
172  //get temp dir from preferences
173  wxString tempDir= wxConfigBase::Get()->Read(wxT("tempDir"),wxT(""));
174  if(!tempDir.IsEmpty())
175  if(tempDir.Last()!=wxFileName::GetPathSeparator())
176  tempDir.Append(wxFileName::GetPathSeparator());
177 
178  try {
179  // copy pto file to temporary file
180  m_currentPTOfn = wxFileName::CreateTempFileName(tempDir+wxT("huginpto_"));
181  if(m_currentPTOfn.empty()) {
182  wxLogError(_("Could not create temporary file"));
183  }
184  DEBUG_DEBUG("tmpPTOfn file: " << (const char *)m_currentPTOfn.mb_str(wxConvLocal));
185  // copy is not enough, need to adjust image path names...
186  const std::string script(m_currentPTOfn.mb_str(HUGIN_CONV_FILENAME));
187  pano.WritePTOFile(script);
188 
189  // cd to output directory, if one is given.
190  m_oldCwd = wxFileName::GetCwd();
191  wxFileName::SetCwd(outpath);
192  const wxFileName exePath(wxStandardPaths::Get().GetExecutablePath());
193  wxArrayString outputFiles;
194  wxString statusText;
195  m_tempFiles.clear();
196  HuginQueue::CommandQueue* commands;
197  std::stringstream errors;
198  if (userDefinedOutput.IsEmpty())
199  {
200  commands = HuginQueue::GetStitchingCommandQueue(pano, exePath.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR), m_currentPTOfn, basename, statusText, outputFiles, m_tempFiles, errors);
201  }
202  else
203  {
204  commands= HuginQueue::GetStitchingCommandQueueUserOutput(pano, exePath.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR), m_currentPTOfn, basename, userDefinedOutput, statusText, outputFiles, m_tempFiles, errors);
205  };
206  if (commands->empty())
207  {
208  wxMessageBox(_("Queue is empty. This should never happen.") + "\n\n" + wxString(errors.str()), _("Error during stitching"), wxICON_ERROR | wxOK);
209  return false;
210  };
211  // check output directories.
212  wxString overwrittenFiles;
213  if (!m_overwrite)
214  {
215  for (size_t i = 0; i < outputFiles.size(); i++)
216  {
217  wxString fn(outputFiles[i]);
218  if (wxFile::Exists(fn))
219  {
220  overwrittenFiles.Append(fn + wxT(" "));
221  };
222  };
223 
224  if (!overwrittenFiles.IsEmpty())
225  {
226  int overwriteret = wxMessageBox(_("Overwrite existing images?\n\n") + overwrittenFiles, _("Overwrite existing images"), wxYES_NO | wxICON_QUESTION);
227  // TODO: change button label ok to overwrite
228  if (overwriteret != wxYES) {
229  DEBUG_DEBUG("Abort, do not overwrite images!");
230  return false;
231  }
232  DEBUG_DEBUG("Overwrite existing images!");
233  };
234  };
235  if (!statusText.empty())
236  {
237  m_execPanel->AddString(statusText);
238  };
239  if (m_execPanel->ExecQueue(commands) == -1)
240  {
241  wxMessageBox(wxString::Format(_("Error while stitching project\n%s"), scriptFile.c_str()),
242  _("Error during stitching"), wxICON_ERROR | wxOK );
243  };
244  } catch (std::exception & e)
245  {
246  std::cerr << "caught exception: " << e.what() << std::endl;
247  wxMessageBox(wxString(e.what(), wxConvLocal),
248  _("Error during stitching"), wxICON_ERROR | wxOK );
249  }
250  return true;
251 }
252 
253 bool RunStitchPanel::DetectProject(const wxString& scriptFile, const wxString& userDefinedAssistant)
254 {
255  m_currentPTOfn=wxEmptyString;
256  wxFileName fname(scriptFile);
257  if ( !fname.FileExists() ) {
258  wxLogError( _("Could not open project file:") + scriptFile);
259  return false;
260  }
261  // check user defined assistant file
262  if (!userDefinedAssistant.IsEmpty())
263  {
264  wxFileInputStream input(userDefinedAssistant);
265  if (!input.IsOk())
266  {
267  wxLogError(wxString::Format(_("Can't open user defined output sequence \"%s\"."), userDefinedAssistant.c_str()));
268  return false;
269  };
270  };
271 
272  // get path to project file
273  wxString pathToPTO;
274  wxFileName::SplitPath(scriptFile, &pathToPTO, NULL, NULL);
275  pathToPTO.Append(wxFileName::GetPathSeparator());
276 
277  //read project file
278  std::ifstream prjfile((const char *)scriptFile.mb_str(HUGIN_CONV_FILENAME));
279  if (prjfile.bad())
280  {
281  wxLogError( wxString::Format(_("could not open script: %s"), scriptFile.c_str()));
282  return false;
283  }
284  HuginBase::Panorama pano;
286  int ptoVersion = 0;
287  if (!newPano.loadPTScript(prjfile, ptoVersion, (const char *)pathToPTO.mb_str(HUGIN_CONV_FILENAME)))
288  {
289  wxLogError(wxString::Format(_("error while parsing panotools script: %s"), scriptFile.c_str()));
290  return false;
291  }
292  pano.setMemento(newPano);
293 
294  //read settings
295  wxString tempDir= wxConfigBase::Get()->Read(wxT("tempDir"),wxT(""));
296  if (!tempDir.IsEmpty())
297  {
298  if (tempDir.Last() != wxFileName::GetPathSeparator())
299  {
300  tempDir.Append(wxFileName::GetPathSeparator());
301  };
302  };
303 
304  try {
305  // prepare running assistant
306  fname.Normalize(wxPATH_NORM_ABSOLUTE | wxPATH_NORM_DOTS | wxPATH_NORM_TILDE | wxPATH_NORM_SHORTCUT);
307  const wxFileName exePath(wxStandardPaths::Get().GetExecutablePath());
308  HuginQueue::CommandQueue* commands;
309  if (userDefinedAssistant.IsEmpty())
310  {
311  commands = HuginQueue::GetAssistantCommandQueue(pano, exePath.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR), fname.GetFullPath());
312  }
313  else
314  {
315  std::stringstream errors;
316  commands = HuginQueue::GetAssistantCommandQueueUserDefined(pano, exePath.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR), fname.GetFullPath(), userDefinedAssistant, m_tempFiles, errors);
317  };
318  if (commands->empty())
319  {
320  wxMessageBox(_("Queue is empty. This should never happen."), _("Error during running assistant"), wxICON_ERROR | wxOK);
321  return false;
322  };
323  if (m_execPanel->ExecQueue(commands) == -1)
324  {
325  wxMessageBox(wxString::Format(_("Error while running assistant\n%s"), scriptFile.c_str()),
326  _("Error during running assistant"), wxICON_ERROR | wxOK );
327  }
328  }
329  catch (std::exception & e)
330  {
331  std::cerr << "caught exception: " << e.what() << std::endl;
332  wxMessageBox(wxString(e.what(), wxConvLocal),
333  _("Error during running assistant"), wxICON_ERROR | wxOK );
334  }
335  return true;
336 }
337 
338 void RunStitchPanel::OnProcessTerminate(wxProcessEvent & event)
339 {
340  DEBUG_TRACE("");
341 #ifndef DEBUG
342  if(!m_currentPTOfn.IsEmpty())
343  {
344  wxRemoveFile(m_currentPTOfn);
345  };
346 #endif
347  // delete all temp files
348  if (!m_tempFiles.empty())
349  {
350  for (size_t i = 0; i < m_tempFiles.size(); ++i)
351  {
352  if (wxFileExists(m_tempFiles[i]))
353  {
354  wxRemoveFile(m_tempFiles[i]);
355  };
356  };
357  };
358  // restore old working directory, if changed
359  if (!m_oldCwd.IsEmpty())
360  {
361  wxFileName::SetCwd(m_oldCwd);
362  };
363  // notify parent of exit
364  if (this->GetParent())
365  {
366  event.SetEventObject( this );
367  DEBUG_TRACE("Sending wxProcess event");
368  this->GetParent()->GetEventHandler()->ProcessEvent( event );
369  }
370 }
371 
373 {
374  DEBUG_TRACE("");
376 }
377 
379 {
380  return m_paused;
381 }
382 
384 {
385  m_overwrite = over;
386 }
387 
389 {
390  m_paused=true;
392 }
393 
395 {
397  m_paused=false;
398 }
399 
401 {
402  return m_execPanel->GetPid();
403 }
404 
405 bool RunStitchPanel::SaveLog(const wxString &filename)
406 {
407  return m_execPanel->SaveLog(filename);
408 };
implementation of huginApp Class
void setMemento(const PanoramaMemento &memento)
set the internal state
Definition: Panorama.cpp:1507
bool StitchProject(const wxString &scriptFile, const wxString &outname, const wxString &userDefinedOutput=wxEmptyString)
void OnProcessTerminate(wxProcessEvent &event)
interface of CommandQueue creating for stitching engine
#define HUGIN_CONV_FILENAME
Definition: platform.h:40
#define DEBUG_TRACE(msg)
Definition: utils.h:67
int ExecQueue(HuginQueue::CommandQueue *queue)
END_EVENT_TABLE()
include file for the hugin project
wxArrayString m_tempFiles
basic classes and function for queuing commands in wxWidgets
CommandQueue * GetAssistantCommandQueue(const HuginBase::Panorama &pano, const wxString &ExePath, const wxString &project)
generates the command queue for running the assistant
Model for a panorama.
Definition: Panorama.h:152
bool SaveLog(const wxString &filename)
save the content of the window into a given log file
bool loadPTScript(std::istream &i, int &ptoVersion, const std::string &prefix="")
load a Hugin file
wxString m_currentPTOfn
void AddString(const wxString &s)
display the string in the panel
#define HUGIN_NONA_USEGPU
MyExecPanel * m_execPanel
UIntSet getActiveImages() const
get active images
Definition: Panorama.cpp:1585
include file for the hugin project
const PanoramaOptions & getOptions() const
returns the options for this panorama
Definition: Panorama.h:481
void SetOverwrite(bool over=true)
bool DetectProject(const wxString &scriptFile, const wxString &userDefinedAssistant=wxEmptyString)
Memento class for a Panorama object.
Definition: Panorama.h:49
#define HUGIN_ENFUSE_ARGS
#define DEBUG_DEBUG(msg)
Definition: utils.h:68
functions for interaction with the hugin configuration file
platform/compiler specific stuff.
bool WritePTOFile(const std::string &filename, const std::string &prefix="")
write data to given pto file
Definition: Panorama.cpp:2059
void setOptions(const PanoramaOptions &opt)
set new output settings This is not used directly for optimizing/stiching, but it can be feed into ru...
Definition: Panorama.cpp:1531
CommandQueue * GetAssistantCommandQueueUserDefined(const HuginBase::Panorama &pano, const wxString &ExePath, const wxString &project, const wxString &assistantSetting, wxArrayString &tempFilesDelete, std::ostream &errStream)
generates the command queue for running the assistant
void PauseProcess(bool pause=true)
function to pause running process, argument pause defaults to true - to resume, set it to false ...
Panorama image options.
CommandQueue * GetStitchingCommandQueueUserOutput(const HuginBase::Panorama &pano, const wxString &ExePath, const wxString &project, const wxString &prefix, const wxString &outputSettings, wxString &statusText, wxArrayString &outputFiles, wxArrayString &tempFilesDelete, std::ostream &errStream)
generates the command queue for stitching a pano, the commands are parsed from the given executor out...
#define HUGIN_ENBLEND_ARGS
CommandQueue * GetStitchingCommandQueue(const HuginBase::Panorama &pano, const wxString &ExePath, const wxString &project, const wxString &prefix, wxString &statusText, wxArrayString &outputFiles, wxArrayString &tempFilesDelete, std::ostream &errStream)
generates the command queue for stitching a pano it will also generate the necessary exiftool argfile...
std::vector< NormalCommand * > CommandQueue
Definition: Executor.h:61
wxString m_oldCwd
create a CommandQueue for running the assistant using CLI tools
bool SaveLog(const wxString &filename)
save the content of the window into a given log file