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 
59  : wxPanel(parent)
60 {
61  m_paused=false;
62  m_overwrite=false;
63  /*
64  wxMenu *menuFile = new wxMenu;
65 
66  menuFile->AppendSeparator();
67  menuFile->Append( ID_Quit, _("E&xit") );
68 
69  wxMenu *menuHelp = new wxMenu;
70  menuHelp->Append( ID_About, _("&About...") );
71 
72  wxMenuBar *menuBar = new wxMenuBar;
73  menuBar->Append( menuFile, _("&File") );
74  menuBar->Append( menuHelp, _("&Help") );
75  SetMenuBar( menuBar );
76  */
77 
78  wxBoxSizer * topsizer = new wxBoxSizer( wxVERTICAL );
79  m_execPanel = new MyExecPanel(this);
80 
81  topsizer->Add(m_execPanel, 1, wxEXPAND, 0);
82  SetSizer( topsizer );
83 // topsizer->SetSizeHints( this ); // set size hints to honour minimum size
84  Bind(wxEVT_END_PROCESS, &RunStitchPanel::OnProcessTerminate, this);
85 }
86 
87 bool RunStitchPanel::StitchProject(const wxString& scriptFile, const wxString& outname, const wxString& userDefinedOutput)
88 {
89  DEBUG_TRACE("");
90  wxFileName fname(scriptFile);
91  if ( !fname.FileExists() ) {
92  wxLogError( _("Could not open project file:") + scriptFile);
93  return false;
94  }
95 
96  wxString pathToPTO;
97  wxFileName::SplitPath(scriptFile, &pathToPTO, NULL, NULL);
98  pathToPTO.Append(wxFileName::GetPathSeparator());
99 
100  std::ifstream prjfile((const char *)scriptFile.mb_str(HUGIN_CONV_FILENAME));
101  if (prjfile.bad()) {
102  wxLogError( wxString::Format(_("could not open script: %s"), scriptFile.c_str()) );
103  return false;
104  }
105  HuginBase::Panorama pano;
107  int ptoVersion = 0;
108  if (newPano.loadPTScript(prjfile, ptoVersion, (const char *)pathToPTO.mb_str(HUGIN_CONV_FILENAME))) {
109  pano.setMemento(newPano);
110  if (pano.getActiveImages().empty())
111  {
112  wxLogError(wxString::Format(_("Project %s does not contain any active images."), scriptFile.c_str()));
113  return false;
114  }
116  if (ptoVersion < 2) {
117  // no options stored in file, use default arguments in config
118 
119  wxConfig* config = new wxConfig(wxT("hugin")); //needed for PTBatcher console application
120  wxConfigBase::Set(config); //
121  opts.enblendOptions = wxConfigBase::Get()->Read(wxT("/Enblend/Args"), wxT(HUGIN_ENBLEND_ARGS)).mb_str(wxConvLocal);
122  opts.enfuseOptions = wxConfigBase::Get()->Read(wxT("/Enfuse/Args"), wxT(HUGIN_ENFUSE_ARGS)).mb_str(wxConvLocal);
123 
124  }
125  opts.remapUsingGPU = wxConfigBase::Get()->Read(wxT("/Nona/UseGPU"), HUGIN_NONA_USEGPU) == 1;
126  pano.setOptions(opts);
127  } else {
128  wxLogError( wxString::Format(_("error while parsing panotools script: %s"), scriptFile.c_str()) );
129  return false;
130  }
131  // get options and correct for correct makefile
133  if (!userDefinedOutput.IsEmpty())
134  {
135  wxFileInputStream input(userDefinedOutput);
136  if (!input.IsOk())
137  {
138  wxLogError(wxString::Format(_("Can't open user defined output sequence \"%s\"."), userDefinedOutput.c_str()));
139  return false;
140  }
141  wxFileConfig settings(input);
142  // disable cropped output if user defined setting is requesting
143  long supportsCroppedOutput;
144  settings.Read(wxT("/General/SupportsCroppedTIFF"), &supportsCroppedOutput, 1l);
145  if (supportsCroppedOutput != 1)
146  {
147  opts.tiff_saveROI = false;
148  };
149  };
151  if (opts.enblendOptions.length() == 0) {
152  // no options stored in file, use default arguments in config file
153  opts.enblendOptions = wxConfigBase::Get()->Read(wxT("/Enblend/Args"), wxT(HUGIN_ENBLEND_ARGS)).mb_str(wxConvLocal);
154  }
155  pano.setOptions(opts);
156  DEBUG_DEBUG("output file specified is " << (const char *)outname.mb_str(wxConvLocal));
157 
158  wxString basename;
159  wxString outpath;
160  wxFileName outputPrefix(outname);
161  outputPrefix.MakeAbsolute();
162  outpath = outputPrefix.GetPath();
163  basename = outputPrefix.GetFullName();
164  //get temp dir from preferences
165  wxString tempDir= wxConfigBase::Get()->Read(wxT("tempDir"),wxT(""));
166  if(!tempDir.IsEmpty())
167  if(tempDir.Last()!=wxFileName::GetPathSeparator())
168  tempDir.Append(wxFileName::GetPathSeparator());
169 
170  try {
171  // copy pto file to temporary file
172  m_currentPTOfn = wxFileName::CreateTempFileName(tempDir+wxT("huginpto_"));
173  if(m_currentPTOfn.empty()) {
174  wxLogError(_("Could not create temporary file"));
175  }
176  DEBUG_DEBUG("tmpPTOfn file: " << (const char *)m_currentPTOfn.mb_str(wxConvLocal));
177  // copy is not enough, need to adjust image path names...
178  const std::string script(m_currentPTOfn.mb_str(HUGIN_CONV_FILENAME));
179  pano.WritePTOFile(script);
180 
181  // cd to output directory, if one is given.
182  m_oldCwd = wxFileName::GetCwd();
183  wxFileName::SetCwd(outpath);
184  const wxFileName exePath(wxStandardPaths::Get().GetExecutablePath());
185  wxArrayString outputFiles;
186  wxString statusText;
187  m_tempFiles.clear();
188  HuginQueue::CommandQueue* commands;
189  std::stringstream errors;
190  if (userDefinedOutput.IsEmpty())
191  {
192  commands = HuginQueue::GetStitchingCommandQueue(pano, exePath.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR), m_currentPTOfn, basename, statusText, outputFiles, m_tempFiles, errors);
193  }
194  else
195  {
196  commands= HuginQueue::GetStitchingCommandQueueUserOutput(pano, exePath.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR), m_currentPTOfn, basename, userDefinedOutput, statusText, outputFiles, m_tempFiles, errors);
197  };
198  if (commands->empty())
199  {
200  wxMessageBox(_("Queue is empty. This should never happen.") + "\n\n" + wxString(errors.str()), _("Error during stitching"), wxICON_ERROR | wxOK);
201  return false;
202  };
203  // check output directories.
204  wxString overwrittenFiles;
205  if (!m_overwrite)
206  {
207  for (size_t i = 0; i < outputFiles.size(); i++)
208  {
209  wxString fn(outputFiles[i]);
210  if (wxFile::Exists(fn))
211  {
212  overwrittenFiles.Append(fn + wxT(" "));
213  };
214  };
215 
216  if (!overwrittenFiles.IsEmpty())
217  {
218  int overwriteret = wxMessageBox(_("Overwrite existing images?\n\n") + overwrittenFiles, _("Overwrite existing images"), wxYES_NO | wxICON_QUESTION);
219  // TODO: change button label ok to overwrite
220  if (overwriteret != wxYES) {
221  DEBUG_DEBUG("Abort, do not overwrite images!");
222  return false;
223  }
224  DEBUG_DEBUG("Overwrite existing images!");
225  };
226  };
227  if (!statusText.empty())
228  {
229  m_execPanel->AddString(statusText);
230  };
231  if (m_execPanel->ExecQueue(commands) == -1)
232  {
233  wxMessageBox(wxString::Format(_("Error while stitching project\n%s"), scriptFile.c_str()),
234  _("Error during stitching"), wxICON_ERROR | wxOK );
235  };
236  } catch (std::exception & e)
237  {
238  std::cerr << "caught exception: " << e.what() << std::endl;
239  wxMessageBox(wxString(e.what(), wxConvLocal),
240  _("Error during stitching"), wxICON_ERROR | wxOK );
241  }
242  return true;
243 }
244 
245 bool RunStitchPanel::DetectProject(const wxString& scriptFile, const wxString& userDefinedAssistant)
246 {
247  m_currentPTOfn=wxEmptyString;
248  wxFileName fname(scriptFile);
249  if ( !fname.FileExists() ) {
250  wxLogError( _("Could not open project file:") + scriptFile);
251  return false;
252  }
253  // check user defined assistant file
254  if (!userDefinedAssistant.IsEmpty())
255  {
256  wxFileInputStream input(userDefinedAssistant);
257  if (!input.IsOk())
258  {
259  wxLogError(wxString::Format(_("Can't open user defined output sequence \"%s\"."), userDefinedAssistant.c_str()));
260  return false;
261  };
262  };
263 
264  // get path to project file
265  wxString pathToPTO;
266  wxFileName::SplitPath(scriptFile, &pathToPTO, NULL, NULL);
267  pathToPTO.Append(wxFileName::GetPathSeparator());
268 
269  //read project file
270  std::ifstream prjfile((const char *)scriptFile.mb_str(HUGIN_CONV_FILENAME));
271  if (prjfile.bad())
272  {
273  wxLogError( wxString::Format(_("could not open script: %s"), scriptFile.c_str()));
274  return false;
275  }
276  HuginBase::Panorama pano;
278  int ptoVersion = 0;
279  if (!newPano.loadPTScript(prjfile, ptoVersion, (const char *)pathToPTO.mb_str(HUGIN_CONV_FILENAME)))
280  {
281  wxLogError(wxString::Format(_("error while parsing panotools script: %s"), scriptFile.c_str()));
282  return false;
283  }
284  pano.setMemento(newPano);
285 
286  //read settings
287  wxString tempDir= wxConfigBase::Get()->Read(wxT("tempDir"),wxT(""));
288  if (!tempDir.IsEmpty())
289  {
290  if (tempDir.Last() != wxFileName::GetPathSeparator())
291  {
292  tempDir.Append(wxFileName::GetPathSeparator());
293  };
294  };
295 
296  try {
297  // prepare running assistant
298  fname.Normalize(wxPATH_NORM_ABSOLUTE | wxPATH_NORM_DOTS | wxPATH_NORM_TILDE | wxPATH_NORM_SHORTCUT);
299  const wxFileName exePath(wxStandardPaths::Get().GetExecutablePath());
300  HuginQueue::CommandQueue* commands;
301  if (userDefinedAssistant.IsEmpty())
302  {
303  commands = HuginQueue::GetAssistantCommandQueue(pano, exePath.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR), fname.GetFullPath());
304  }
305  else
306  {
307  std::stringstream errors;
308  commands = HuginQueue::GetAssistantCommandQueueUserDefined(pano, exePath.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR), fname.GetFullPath(), userDefinedAssistant, m_tempFiles, errors);
309  };
310  if (commands->empty())
311  {
312  wxMessageBox(_("Queue is empty. This should never happen."), _("Error during running assistant"), wxICON_ERROR | wxOK);
313  return false;
314  };
315  if (m_execPanel->ExecQueue(commands) == -1)
316  {
317  wxMessageBox(wxString::Format(_("Error while running assistant\n%s"), scriptFile.c_str()),
318  _("Error during running assistant"), wxICON_ERROR | wxOK );
319  }
320  }
321  catch (std::exception & e)
322  {
323  std::cerr << "caught exception: " << e.what() << std::endl;
324  wxMessageBox(wxString(e.what(), wxConvLocal),
325  _("Error during running assistant"), wxICON_ERROR | wxOK );
326  }
327  return true;
328 }
329 
330 void RunStitchPanel::OnProcessTerminate(wxProcessEvent & event)
331 {
332  DEBUG_TRACE("");
333 #ifndef DEBUG
334  if(!m_currentPTOfn.IsEmpty())
335  {
336  wxRemoveFile(m_currentPTOfn);
337  };
338 #endif
339  // delete all temp files
340  if (!m_tempFiles.empty())
341  {
342  for (size_t i = 0; i < m_tempFiles.size(); ++i)
343  {
344  if (wxFileExists(m_tempFiles[i]))
345  {
346  wxRemoveFile(m_tempFiles[i]);
347  };
348  };
349  };
350  // restore old working directory, if changed
351  if (!m_oldCwd.IsEmpty())
352  {
353  wxFileName::SetCwd(m_oldCwd);
354  };
355  // notify parent of exit
356  if (this->GetParent())
357  {
358  event.SetEventObject( this );
359  DEBUG_TRACE("Sending wxProcess event");
360  this->GetParent()->GetEventHandler()->ProcessEvent( event );
361  }
362 }
363 
365 {
366  DEBUG_TRACE("");
368 }
369 
371 {
372  return m_paused;
373 }
374 
376 {
377  m_overwrite = over;
378 }
379 
381 {
382  m_paused=true;
384 }
385 
387 {
389  m_paused=false;
390 }
391 
393 {
394  return m_execPanel->GetPid();
395 }
396 
397 bool RunStitchPanel::SaveLog(const wxString &filename)
398 {
399  return m_execPanel->SaveLog(filename);
400 };
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)
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
RunStitchPanel(wxWindow *parent)
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