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