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