Batch.cpp

Go to the documentation of this file.
00001 // -*- c-basic-offset: 4 -*-
00002 
00027 #include "Batch.h"
00028 #include <wx/stdpaths.h>
00029 #ifdef __WXMSW__
00030 #include <powrprof.h>
00031 #pragma comment(lib, "PowrProf.lib")
00032 #endif
00033 
00034 BEGIN_EVENT_TABLE(Batch, wxFrame)
00035     EVT_END_PROCESS(-1, Batch::OnProcessTerminate)
00036 END_EVENT_TABLE()
00037 
00038 #if defined _WIN32 && defined Hugin_shared
00039 DEFINE_LOCAL_EVENT_TYPE(EVT_BATCH_FAILED)
00040 DEFINE_LOCAL_EVENT_TYPE(EVT_INFORMATION)
00041 DEFINE_LOCAL_EVENT_TYPE(EVT_UPDATE_PARENT)
00042 #else
00043 DEFINE_EVENT_TYPE(EVT_BATCH_FAILED)
00044 DEFINE_EVENT_TYPE(EVT_INFORMATION)
00045 DEFINE_EVENT_TYPE(EVT_UPDATE_PARENT)
00046 #endif
00047 
00048 Batch::Batch(wxFrame* parent) : wxFrame(parent, wxID_ANY, _T("Batch"))
00049 {
00050     //default flag settings
00051     deleteFiles = false;
00052     atEnd = DO_NOTHING;
00053 #if wxCHECK_VERSION(3,1,0)
00054     m_resBlocker = NULL;
00055 #endif
00056     overwrite = true;
00057     verbose = false;
00058     autoremove = false;
00059     autostitch = false;
00060     saveLog = false;
00061     m_cancelled = false;
00062     m_paused = false;
00063     m_running = false;
00064     m_clearedInProgress = false;
00065     m_lastFile = wxT("");
00066 
00067     // Required to access the preferences of hugin
00068     //SetAppName(wxT("hugin"));
00069 
00070 }
00071 
00072 Batch::~Batch()
00073 {
00074 #if wxCHECK_VERSION(3,1,0)
00075     if (m_resBlocker != NULL)
00076     {
00077         delete m_resBlocker;
00078     };
00079 #endif
00080 }
00081 
00082 void Batch::AddAppToBatch(wxString app)
00083 {
00084     Project* newApp = new Project(app);
00085     m_projList.Add(newApp);
00086 }
00087 
00088 void Batch::AddProjectToBatch(wxString projectFile, wxString outputFile,Project::Target target)
00089 {
00090     wxFileName projectName(projectFile);
00091     wxFileName outName(outputFile);
00092     projectName.Normalize();
00093     outName.Normalize();
00094 
00095     if(outputFile.Cmp(_T(""))!=0 || target==Project::DETECTING)
00096     {
00097         Project* proj = new Project(projectName.GetFullPath(),outName.GetFullPath(),target);
00098         m_projList.Add(proj);
00099     }
00100     else
00101     {
00102         //on output set as "", it defaults to same path and name as project file
00103         Project* proj = new Project(projectName.GetFullPath(),wxT(""));
00104         m_projList.Add(proj);
00105     }
00106 }
00107 
00108 bool Batch::AllDone()
00109 {
00110     for(unsigned int i=0; i<m_projList.GetCount(); i++)
00111     {
00112         if(m_projList.Item(i).status==Project::WAITING ||
00113                 m_projList.Item(i).status==Project::RUNNING ||
00114                 m_projList.Item(i).status==Project::PAUSED)
00115         {
00116             return false;
00117         }
00118     }
00119     return true;
00120 }
00121 
00122 void Batch::AppendBatchFile(wxString file)
00123 {
00124     wxFileName aFile(file);
00125     if(aFile.FileExists())
00126     {
00127         m_lastFile = file;
00128         aFile.GetTimes(NULL,NULL,&m_lastmod);
00129         wxFileInputStream fileStream(file);
00130         wxString projectName = _T("");
00131 #ifdef __WXMSW__
00132         wxTextInputStream textStream(fileStream, wxT(" \t"), wxConvLocal);
00133 #else
00134         wxTextInputStream textStream(fileStream);
00135 #endif
00136 
00137         //TO-DO: batch file error checking?
00138         //first line in file is idGenerator, we save it a temp variable, cause it gets set when adding projects
00139         long idGenTemp = 1;
00140         if (fileStream.Eof())
00141         {
00142             return;
00143         };
00144         textStream.ReadLine().ToLong(&idGenTemp);
00145         //then for each project: project path, prefix, id, status, skip
00146         if (fileStream.Eof())
00147         {
00148             return;
00149         };
00150         while((projectName = textStream.ReadLine()).Cmp(wxT(""))!=0)
00151         {
00152             // read all line, check before reading
00153             if (fileStream.Eof())
00154             {
00155                 break;
00156             };
00157             wxString line=textStream.ReadLine();
00158             if (fileStream.Eof())
00159             {
00160                 break;
00161             };
00162             long id;
00163             textStream.ReadLine().ToLong(&id);
00164             long status;
00165             if (fileStream.Eof())
00166             {
00167                 break;
00168             };
00169             textStream.ReadLine().ToLong(&status);
00170             if (fileStream.Eof())
00171             {
00172                 break;
00173             };
00174             const bool skip = textStream.ReadLine().StartsWith(_T("T"));
00175 
00176             //we add project to internal list
00177             if (id == -1)
00178             {
00179                 AddAppToBatch(projectName);
00180             }
00181             else
00182             {
00183                 if (line.IsEmpty())
00184                 {
00185                     AddProjectToBatch(projectName, wxT(""), Project::DETECTING);
00186                 }
00187                 else
00188                 {
00189                     AddProjectToBatch(projectName, line);
00190                 };
00191             };
00192             //if status was RUNNING or PAUSED, we set it to FAILED
00193             if(status==(long)Project::RUNNING || status==(long)Project::PAUSED)
00194             {
00195                 status=(long)Project::FAILED;
00196             }
00197             m_projList.Last().id = id;
00198             m_projList.Last().status = (Project::Status)status;
00199             if(skip)
00200             {
00201                 m_projList.Last().skip = true;
00202             };
00203 
00204             if (fileStream.Eof())
00205             {
00206                 break;
00207             };
00208         }
00209         //we set the id generator we got from file
00210         Project::idGenerator = idGenTemp;
00211     }
00212 }
00213 
00214 void Batch::CancelBatch()
00215 {
00216     m_cancelled = true;
00217     for(int i=0; i<GetRunningCount(); i++)
00218     {
00219         CancelProject(i);
00220     }
00221 #if wxCHECK_VERSION(3,1,0)
00222     if (m_resBlocker != NULL)
00223     {
00224         delete m_resBlocker;
00225         m_resBlocker = NULL;
00226     };
00227 #endif
00228     m_running = false;
00229 }
00230 void Batch::CancelProject(int index)
00231 {
00232     wxCommandEvent event;
00233     if(GetRunningCount()==1)
00234     {
00235         m_paused = false;
00236     }
00237     m_stitchFrames.Item(index)->OnCancel(event);
00238     if(GetRunningCount()==0)
00239     {
00240         m_running = false;
00241     }
00242 }
00243 void Batch::ChangePrefix(int index, wxString newPrefix)
00244 {
00245     m_projList.Item(index).prefix = newPrefix;
00246 }
00247 
00248 int Batch::ClearBatch()
00249 {
00250     if(m_stitchFrames.GetCount()!=0)
00251     {
00252         wxMessageDialog message(this, _("Cannot clear batch in progress.\nDo you want to cancel it?"),
00253 #ifdef _WIN32
00254                                 _("PTBatcherGUI"),
00255 #else
00256                                 wxT(""),
00257 #endif
00258                                 wxYES_NO | wxICON_INFORMATION);
00259         if(message.ShowModal()==wxID_YES)
00260         {
00261             CancelBatch();
00262 
00263             //we set a flag so we don't process terminating events
00264             m_clearedInProgress = true;
00265             Project::idGenerator=1;
00266             m_projList.Clear();
00267             ((wxFrame*)GetParent())->SetStatusText(_("Cleared batch."));
00268             return 2;
00269         }
00270         return 1;
00271         //TO-DO: return
00272     }
00273     else
00274     {
00275         Project::idGenerator=1;
00276         m_projList.Clear();
00277         ((wxFrame*)GetParent())->SetStatusText(_("Cleared batch."));
00278         return 0;
00279     }
00280 }
00281 
00282 bool Batch::CompareProjectsInLists(int stitchListIndex, int batchListIndex)
00283 {
00284     return m_stitchFrames.Item(stitchListIndex)->GetProjectId() == m_projList.Item(batchListIndex).id;
00285 }
00286 
00287 int Batch::GetFirstAvailable()
00288 {
00289     unsigned int i = 0;
00290     while(i<m_projList.Count())
00291     {
00292         if(m_projList.Item(i).skip || m_projList.Item(i).status!=Project::WAITING)
00293         {
00294             i++;
00295         }
00296         else
00297         {
00298             break;
00299         }
00300     }
00301     if((m_projList.Count() == 0) || (i == m_projList.Count()))
00302     {
00303         //no projects are available anymore
00304         return -1;
00305     }
00306     else
00307     {
00308         return i;
00309     }
00310 }
00311 
00312 int Batch::GetIndex(int id)
00313 {
00314     for(unsigned int i=0; i<m_projList.GetCount(); i++)
00315     {
00316         if(m_projList.Item(i).id==id)
00317         {
00318             return i;
00319         }
00320     }
00321     return -1;
00322 }
00323 
00324 Project* Batch::GetProject(int index)
00325 {
00326     return (Project*)&m_projList.Item(index);
00327 }
00328 
00329 int Batch::GetProjectCount()
00330 {
00331     return m_projList.GetCount();
00332 }
00333 
00334 int Batch::GetProjectCountByPath(wxString path)
00335 {
00336     int count = 0;
00337     for(unsigned int i=0; i<m_projList.GetCount(); i++)
00338     {
00339         if(!m_projList.Item(i).skip && (path.Cmp(m_projList.Item(i).path)==0))
00340         {
00341             count++;
00342         }
00343     }
00344     return count;
00345 }
00346 
00347 int Batch::GetRunningCount()
00348 {
00349     return m_stitchFrames.GetCount();
00350 }
00351 
00352 Project::Status Batch::GetStatus(int index)
00353 {
00354     if((unsigned int)index<m_projList.GetCount())
00355     {
00356         return m_projList.Item(index).status;
00357     }
00358     else
00359     {
00360         wxMessageBox(wxString::Format(_("Error: Could not get status, project with index %d is not in list."),index),_("Error!"),wxOK | wxICON_INFORMATION );
00361     }
00362     return Project::MISSING;
00363 }
00364 
00365 bool Batch::IsRunning()
00366 {
00367     return m_running;
00368 };
00369 
00370 bool Batch::IsPaused()
00371 {
00372     return m_paused;
00373 }
00374 
00375 void Batch::ListBatch()
00376 {
00377     if(m_projList.GetCount() == 0)
00378     {
00379         std::cout << "Batch is empty." << std::endl;
00380     }
00381     else
00382     {
00383         std::cout << "List of projects in batch:" << std::endl <<
00384              "[ID] [project path] [output filename] [status]" << std::endl <<
00385              "-------------------------------------" << std::endl;
00386         for(unsigned int i=0; i<m_projList.GetCount(); i++)
00387         {
00388             std::cout << m_projList.Item(i).id << "  "  << (const char*)m_projList.Item(i).path.char_str()  << "  " << (const char*)m_projList.Item(i).prefix.char_str()
00389                  << "  " << (const char*)m_projList.Item(i).GetStatusText().char_str() << std::endl;
00390         }
00391     }
00392 }
00393 
00394 int Batch::LoadBatchFile(wxString file)
00395 {
00396     int clearCode = ClearBatch();
00397     if(clearCode==0)
00398     {
00399         AppendBatchFile(file);
00400         return 0;
00401     }
00402     else if(clearCode==2)
00403     {
00404         AppendBatchFile(file);
00405         return 2;
00406     }
00407     else
00408     {
00409         wxMessageBox(_("Error: Could not load batch file."));
00410     };
00411     return 1;
00412 }
00413 
00414 int Batch::LoadTemp()
00415 {
00416     wxDir* workingDir = new wxDir(wxStandardPaths::Get().GetUserConfigDir());
00417     wxString pending;
00418     wxString fileTemp = _T(".ptbt*");
00419     wxString temp = _T("");
00420     //we check for existing temporary files
00421     if(workingDir->GetFirst(&temp,fileTemp,wxDIR_FILES | wxDIR_HIDDEN))
00422     {
00423         //we find the last existing tempfile (there should be at most two, but we check for multiple just in case)
00424         while(workingDir->GetNext(&pending))
00425         {
00426             wxFileName tempFile(temp);
00427             wxFileName pendingFile(pending);
00428             wxDateTime* create1 = new wxDateTime();
00429             wxDateTime* create2 = new wxDateTime();
00430             if(tempFile.FileExists() && pendingFile.FileExists())
00431             {
00432                 tempFile.GetTimes(NULL,NULL,create1);
00433                 pendingFile.GetTimes(NULL,NULL,create2);
00434                 if(create2->IsLaterThan(*create1))
00435                 {
00436                     wxRemoveFile(temp);
00437                     temp=wxString(pending);
00438                 }
00439             }
00440             else
00441             {
00442                 //wxMessageBox( _T("Error reading temporary file"),_T("Error!"),wxOK | wxICON_INFORMATION );
00443                 return 1;
00444             }
00445         }
00446     }
00447     //we load the data from the temp file
00448     AppendBatchFile(workingDir->GetName()+wxFileName::GetPathSeparator()+temp);
00449     return 0;
00450 }
00451 
00452 bool Batch::NoErrors()
00453 {
00454     for(unsigned int i=0; i<m_projList.GetCount(); i++)
00455     {
00456         if(m_projList.Item(i).status==Project::FAILED)
00457         {
00458             return false;
00459         }
00460     }
00461     return true;
00462 }
00463 
00464 void Batch::OnProcessTerminate(wxProcessEvent& event)
00465 {
00466     //we find the right pointer to remove
00467     unsigned int i = 0;
00468     while(i < m_stitchFrames.GetCount() &&
00469             m_stitchFrames.Item(i)->GetProjectId()!=event.GetId())
00470     {
00471         i++;
00472     }
00473     m_stitchFrames.RemoveAt(i);
00474     if(m_clearedInProgress)
00475     {
00476         if(m_stitchFrames.GetCount()==0)
00477         {
00478             m_paused = false;
00479             m_running = false;
00480             m_cancelled = false;
00481             m_clearedInProgress = false;
00482         }
00483     }
00484     else
00485     {
00486         if(m_stitchFrames.GetCount()==0)
00487         {
00488             m_paused = false;
00489         }
00490         i = GetIndex(event.GetId());
00491         wxString savedLogfile=wxEmptyString;
00492         if(saveLog || event.GetExitCode() != 0 || event.GetTimestamp()==-1)
00493         {
00494             //get filename for automatic saving of log file
00495             wxFileName logFile(m_projList.Item(i).path);
00496             logFile.MakeAbsolute();
00497             logFile.SetExt(wxT("log"));
00498             wxString name=logFile.GetName();
00499             unsigned int i=1;
00500             while(logFile.FileExists() && i<1000)
00501             {
00502                 logFile.SetName(wxString::Format(wxT("%s_%d"),name.c_str(),i));
00503                 i++;
00504             };
00505             if(i<1000)
00506             {
00507                 //now save log file
00508                 if((static_cast<RunStitchFrame*>(event.GetEventObject()))->SaveLog(logFile.GetFullPath()))
00509                 {
00510                     savedLogfile=logFile.GetFullPath();
00511                 }
00512             };
00513         };
00514         if (event.GetExitCode() != 0 || event.GetTimestamp()==-1) //timestamp is used as a fake exit code because it cannot be set manually
00515         {
00516             m_projList.Item(i).status=Project::FAILED;
00517             struct FailedProject failedProject;
00518             failedProject.project=m_projList.Item(i).path;
00519             failedProject.logfile=savedLogfile;
00520             //remember failed project
00521             m_failedProjects.push_back(failedProject);
00522         }
00523         else
00524         {
00525             m_projList.Item(i).status=Project::FINISHED;
00526             // don't sent event for command app
00527             if(m_projList.Item(i).id>=0)
00528             {
00529                 bool notifyParent=false;
00530                 if(autostitch && m_projList.Item(i).target==Project::DETECTING)
00531                 {
00532                     wxFileName name(m_projList.Item(i).path);
00533                     AddProjectToBatch(m_projList.Item(i).path,name.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR) + name.GetName(),Project::STITCHING);
00534                     notifyParent=true;
00535                 };
00536                 if(autoremove)
00537                 {
00538                     RemoveProjectAtIndex(i);
00539                     SaveTemp();
00540                     notifyParent=true;
00541                 };
00542                 if(notifyParent)
00543                 {
00544                     wxCommandEvent e(EVT_UPDATE_PARENT,wxID_ANY);
00545                     GetParent()->GetEventHandler()->AddPendingEvent(e);
00546                 };
00547             };
00548         }
00549         if(!m_cancelled && !m_paused)
00550         {
00551             if(AllDone())
00552             {
00553                 SaveTemp();
00554                 m_running = false;
00555 #if wxCHECK_VERSION(3,1,0)
00556                 if (m_resBlocker != NULL)
00557                 {
00558                     delete m_resBlocker;
00559                     m_resBlocker = NULL;
00560                 };
00561 #endif
00562                 if(NoErrors())
00563                 {
00564                     wxCommandEvent e(EVT_INFORMATION,wxID_ANY);
00565                     e.SetString(_("Batch successfully completed."));
00566                     // setting int to 1 to indicate we are finished
00567                     e.SetInt(1);
00568                     GetParent()->GetEventHandler()->AddPendingEvent(e);
00569                 }
00570                 else
00571                 {
00572                     ((wxFrame*)GetParent())->SetStatusText(_("Batch completed with errors."));
00573                     if(atEnd==DO_NOTHING)
00574                     {
00575                         //notify parent, that at least one project failed
00576                         // show dialog only if we don't shutdown the computer or end PTBatcherGUI
00577                         wxCommandEvent e(EVT_BATCH_FAILED,wxID_ANY);
00578                         GetParent()->GetEventHandler()->AddPendingEvent(e);
00579                     };
00580                 };
00581                 switch (atEnd)
00582                 {
00583                     case DO_NOTHING:
00584                         // no action needed
00585                         break;
00586                     case CLOSE_PTBATCHERGUI:
00587                         GetParent()->Close();
00588                         break;
00589                     case SHUTDOWN:
00590                         {
00591                             wxProgressDialog progress(_("Initializing shutdown..."), _("Shutting down..."), 49, this,
00592                                 wxPD_AUTO_HIDE | wxPD_SMOOTH | wxPD_APP_MODAL | wxPD_CAN_ABORT | wxPD_CAN_SKIP);
00593                             progress.Fit();
00594                             int i = 0;
00595                             bool skip = false;
00596                             while (progress.Update(i, _("Shutting down..."), &skip))
00597                             {
00598                                 if (skip || i == 50)
00599                                 {
00600                                     wxShutdown(wxSHUTDOWN_POWEROFF);
00601                                 }
00602                                 i++;
00603 #if defined __WXMSW__
00604                                 Sleep(200);
00605 #else
00606                                 sleep(200);
00607 #endif
00608                             }
00609                             progress.Close();
00610                         }
00611                         break;
00612                     case SUSPEND:
00613                     case HIBERNATE:
00614 #ifdef __WXMSW__
00615                         {
00616                             wxString progressCaption(_("Prepare to hibernate..."));
00617                             wxString progressLabel(_("Initializing hibernating..."));
00618                             if (atEnd == SUSPEND)
00619                             {
00620                                 progressCaption = wxString(_("Prepare to suspend..."));
00621                                 progressLabel = wxString(_("Initializing suspend mode..."));
00622                             };
00623                             wxProgressDialog progress(progressLabel, progressCaption, 49, this,
00624                                 wxPD_AUTO_HIDE | wxPD_SMOOTH | wxPD_APP_MODAL | wxPD_CAN_ABORT | wxPD_CAN_SKIP);
00625                             progress.Fit();
00626                             int i = 0;
00627                             bool skip = false;
00628                             while (progress.Update(i, progressCaption, &skip))
00629                             {
00630                                 if (skip || i == 50)
00631                                 {
00632                                     SetSuspendState(atEnd==HIBERNATE, false, false);
00633                                     break;
00634                                 }
00635                                 i++;
00636                                 Sleep(200);
00637                             }
00638                             progress.Close();
00639                         };
00640 #endif
00641                         break;
00642                 };
00643             }
00644             else
00645             {
00646                 RunNextInBatch();
00647             }
00648         }
00649         else
00650         {
00651             //after all processes have ended on a cancel, we reset the boolean back to false
00652             //if(stitchFrames.GetCount()==0)
00653             if(GetRunningCount()==0)
00654             {
00655                 m_cancelled=false;
00656             }
00657         }
00658     }
00659 }
00660 
00661 bool Batch::OnStitch(wxString scriptFile, wxString outname, int id)
00662 {
00663     // delete the existing wxConfig to force reloading of settings from file/registy
00664     delete wxConfigBase::Set((wxConfigBase*)NULL);
00665     wxConfigBase* config = wxConfigBase::Get();
00666     if(wxIsEmpty(scriptFile))
00667     {
00668         wxString defaultdir = config->Read(wxT("/actualPath"),wxT(""));
00669         wxFileDialog dlg(0,
00670                          _("Specify project file"),
00671                          defaultdir, wxT(""),
00672                          _("Project files (*.pto)|*.pto|All files (*)|*"),
00673                          wxFD_OPEN, wxDefaultPosition);
00674 
00675         dlg.SetDirectory(wxConfigBase::Get()->Read(wxT("/actualPath"),wxT("")));
00676         if (dlg.ShowModal() == wxID_OK)
00677         {
00678             config->Write(wxT("/actualPath"), dlg.GetDirectory());  // remember for later
00679             config->Flush();
00680             wxFileDialog dlg2(0,_("Specify output prefix"),
00681                               wxConfigBase::Get()->Read(wxT("/actualPath"),wxT("")),
00682                               wxT(""), wxT(""),
00683                               wxFD_SAVE, wxDefaultPosition);
00684             dlg2.SetDirectory(wxConfigBase::Get()->Read(wxT("/actualPath"),wxT("")));
00685             if (dlg2.ShowModal() == wxID_OK)
00686             {
00687                 outname = dlg2.GetPath();
00688             }
00689             else     // bail
00690             {
00691                 wxLogError( _("No output prefix specified"));
00692                 return false;
00693             }
00694             scriptFile = dlg.GetPath();
00695         }
00696         else     // bail
00697         {
00698             wxLogError(_("No project files specified"));
00699             return false;
00700         }
00701     }
00702 
00703     // check output filename
00704     wxFileName outfn(outname);
00705     wxString ext = outfn.GetExt();
00706     // remove extension if it indicates an image file
00707     if (ext.CmpNoCase(wxT("jpg")) == 0 || ext.CmpNoCase(wxT("jpeg")) == 0 ||
00708             ext.CmpNoCase(wxT("tif")) == 0 || ext.CmpNoCase(wxT("tiff")) == 0 ||
00709             ext.CmpNoCase(wxT("png")) == 0 || ext.CmpNoCase(wxT("exr")) == 0 ||
00710             ext.CmpNoCase(wxT("pnm")) == 0 || ext.CmpNoCase(wxT("hdr")) == 0)
00711     {
00712         outfn.ClearExt();
00713         outname = outfn.GetFullPath();
00714     }
00715 
00716     RunStitchFrame* stitchFrame = new RunStitchFrame(this, wxT("Hugin Stitcher"), wxDefaultPosition, wxSize(640,600));
00717     stitchFrame->SetProjectId(id);
00718     if(verbose)
00719     {
00720         stitchFrame->Show( true );
00721         wxTheApp->SetTopWindow( stitchFrame );
00722     }
00723 
00724     wxFileName basename(scriptFile);
00725     stitchFrame->SetTitle(wxString::Format(_("%s - Stitching"), basename.GetName().c_str()));
00726     if(overwrite)
00727     {
00728         stitchFrame->m_stitchPanel->SetOverwrite(true);
00729     }
00730 
00731     bool n = stitchFrame->StitchProject(scriptFile, outname);
00732     if(n)
00733     {
00734         m_stitchFrames.Add(stitchFrame);
00735     }
00736     else
00737     {
00738         stitchFrame->Close();
00739     }
00740     return n;
00741 
00742 }
00743 
00744 bool Batch::OnDetect(wxString scriptFile, int id)
00745 {
00746     // delete the existing wxConfig to force reloading of settings from file/registy
00747     delete wxConfigBase::Set((wxConfigBase*)NULL);
00748     RunStitchFrame* stitchFrame = new RunStitchFrame(this, wxT("Hugin Assistant"), wxDefaultPosition, wxSize(640, 600));
00749     stitchFrame->SetProjectId(id);
00750     if(verbose)
00751     {
00752         stitchFrame->Show( true );
00753         wxTheApp->SetTopWindow( stitchFrame );
00754     }
00755 
00756     wxFileName basename(scriptFile);
00757     stitchFrame->SetTitle(wxString::Format(_("%s - Assistant"), basename.GetName().c_str()));
00758 
00759     bool n = stitchFrame->DetectProject(scriptFile);
00760     if(n)
00761     {
00762         m_stitchFrames.Add(stitchFrame);
00763     }
00764     else
00765     {
00766         stitchFrame->Close();
00767     }
00768     return n;
00769 
00770 }
00771 
00772 void Batch::PauseBatch()
00773 {
00774     if(!m_paused)
00775     {
00776         m_paused = true;
00777         for(int i=0; i<GetRunningCount(); i++)
00778         {
00779             m_stitchFrames.Item(i)->m_stitchPanel->PauseStitch();
00780         }
00781         for(unsigned int i=0; i<m_projList.GetCount(); i++)
00782         {
00783             if(m_projList.Item(i).status==Project::RUNNING)
00784             {
00785                 m_projList.Item(i).status=Project::PAUSED;
00786             }
00787         }
00788     }
00789     else
00790     {
00791         m_paused = false;
00792         for(int i=0; i<GetRunningCount(); i++)
00793         {
00794             m_stitchFrames.Item(i)->m_stitchPanel->ContinueStitch();
00795         }
00796         for(unsigned int i=0; i<m_projList.GetCount(); i++)
00797         {
00798             if(m_projList.Item(i).status==Project::PAUSED)
00799             {
00800                 m_projList.Item(i).status=Project::RUNNING;
00801             }
00802         }
00803     }
00804 }
00805 
00806 void Batch::RemoveProject(int id)
00807 {
00808     if(GetIndex(id) != -1)
00809     {
00810         RemoveProjectAtIndex(GetIndex(id));
00811     }
00812     else
00813     {
00814         wxMessageBox(wxString::Format(_("Error removing, project with id %d is not in list."),id),_("Error!"),wxOK | wxICON_INFORMATION );
00815     }
00816 }
00817 
00818 void Batch::RemoveProjectAtIndex(int selIndex)
00819 {
00820     //we delete only successful project files and no applications
00821     if(deleteFiles
00822             && m_projList.Item(selIndex).id>=0
00823             && m_projList.Item(selIndex).status==Project::FINISHED)
00824     {
00825         wxFileName file(m_projList.Item(selIndex).path);
00826         if(file.FileExists())
00827         {
00828             if(!wxRemoveFile(file.GetFullPath()))
00829             {
00830                 wxMessageBox( _("Error: Could not delete project file ")+file.GetFullPath(),_("Error!"),wxOK | wxICON_INFORMATION );
00831             }
00832         }
00833     }
00834     m_projList.RemoveAt(selIndex);
00835     if(m_projList.GetCount()==0) //reset the id generator on empty list
00836     {
00837         Project::idGenerator=1;
00838     }
00839 }
00840 
00841 void Batch::RunBatch()
00842 {
00843     if(!m_running)
00844     {
00845         m_failedProjects.clear();
00846         ((wxFrame*)GetParent())->SetStatusText(_("Running batch..."));
00847         m_running = true;
00848 #if wxCHECK_VERSION(3,1,0)
00849         m_resBlocker = new wxPowerResourceBlocker(wxPOWER_RESOURCE_SYSTEM, _("PTBatcherGUI is stitching"));
00850 #endif
00851         RunNextInBatch();
00852     }
00853     else
00854     {
00855         ((wxFrame*)GetParent())->SetStatusText(_("Batch already in progress."));
00856     }
00857 }
00858 
00859 void Batch::RunNextInBatch()
00860 {
00861     bool value;
00862     bool repeat = true;
00863     unsigned int i;
00864     while(((i=GetFirstAvailable())!=-1) && repeat)
00865     {
00866         //execute command line instructions
00867         if(m_projList.Item(i).id<0)
00868         {
00869             SetStatusText(wxString::Format(_("Running command \"%s\""), m_projList.Item(i).path.c_str()));
00870             m_projList.Item(i).status=Project::RUNNING;
00871             //we create a fake stitchFrame, so program waits for app to complete
00872             if(wxExecute(m_projList.Item(i).path, wxEXEC_SYNC)==0)
00873             {
00874                 m_projList.Item(i).status=Project::FINISHED;
00875             }
00876             else
00877             {
00878                 m_projList.Item(i).status=Project::FAILED;
00879             }
00880         }
00881         else
00882         {
00883             m_projList.Item(i).status=Project::RUNNING;
00884             m_running = true;
00885             if(m_projList.Item(i).target==Project::STITCHING)
00886             {
00887                 wxCommandEvent e(EVT_INFORMATION,wxID_ANY);
00888                 e.SetString(wxString::Format(_("Now stitching: %s"),m_projList.Item(i).path.c_str()));
00889                 GetParent()->GetEventHandler()->AddPendingEvent(e);
00890                 value = OnStitch(m_projList.Item(i).path, m_projList.Item(i).prefix, m_projList.Item(i).id);
00891             }
00892             else
00893             {
00894                 wxCommandEvent e(EVT_INFORMATION,wxID_ANY);
00895                 e.SetString(wxString::Format(_("Now detecting: %s"),m_projList.Item(i).path.c_str()));
00896                 GetParent()->GetEventHandler()->AddPendingEvent(e);
00897                 value = OnDetect(m_projList.Item(i).path,m_projList.Item(i).id);
00898             };
00899             if(!value)
00900             {
00901                 m_projList.Item(i).status=Project::FAILED;
00902             }
00903             else
00904             {
00905                 repeat = false;
00906             }
00907         }
00908     }
00909     if(AllDone())
00910     {
00911         m_running = false;
00912     }
00913 }
00914 
00915 void Batch::SaveBatchFile(wxString file)
00916 {
00917     wxFileOutputStream fileStream(file);
00918 #ifdef __WXMSW__
00919     wxTextOutputStream textStream(fileStream, wxEOL_NATIVE, wxConvLocal);
00920 #else
00921     wxTextOutputStream textStream(fileStream);
00922 #endif
00923     //we write current idGenerator to file
00924     wxString line = _T("");
00925     line << Project::idGenerator;
00926     textStream.WriteString(line+_T("\n"));
00927     //then for each project: project path, prefix, id, status, skip
00928     for(unsigned int i = 0; i< m_projList.GetCount(); i++)
00929     {
00930         textStream.WriteString(m_projList.Item(i).path+_T("\n"));
00931         if(m_projList.Item(i).target==Project::STITCHING)
00932         {
00933             textStream.WriteString(m_projList.Item(i).prefix+_T("\n"));
00934         }
00935         else
00936         {
00937             textStream.WriteString(_T("\n"));
00938         };
00939         line = _T("");
00940         line << m_projList.Item(i).id;
00941         textStream.WriteString(line+_T("\n"));
00942         line = _T("");
00943         line << m_projList.Item(i).status;
00944         textStream.WriteString(line+_T("\n"));
00945         if(m_projList.Item(i).skip)
00946         {
00947             textStream.WriteString(_T("T\n"));
00948         }
00949         else
00950         {
00951             textStream.WriteString(_T("F\n"));
00952         }
00953     }
00954     fileStream.Close();
00955     m_lastFile = file;
00956     wxFileName aFile(file);
00957     aFile.GetTimes(NULL,NULL,&m_lastmod);
00958 }
00959 
00960 void Batch::SaveTemp()
00961 {
00962     wxDir* workingDir = new wxDir(wxStandardPaths::Get().GetUserConfigDir());
00963     wxString fileTemp = _T(".ptbt*");
00964     //we get the old temp file
00965     fileTemp = workingDir->FindFirst(workingDir->GetName(),fileTemp,wxDIR_FILES | wxDIR_HIDDEN);
00966     wxFileName oldFile(fileTemp);
00967     //we alternate between 0 and 1
00968     wxString suffix;
00969     if(fileTemp.EndsWith(_T("0")))
00970     {
00971         suffix = _T("1");
00972     }
00973     else
00974     {
00975         suffix = _T("0");
00976     }
00977     SaveBatchFile(wxStandardPaths::Get().GetUserConfigDir()+wxFileName::GetPathSeparator()+_T(".ptbt")+suffix);
00978     //we remove the previous temp file
00979     if(oldFile.FileExists())
00980     {
00981         wxRemoveFile(fileTemp);
00982     }
00983 }
00984 
00985 void Batch::SetStatus(int index,Project::Status status)
00986 {
00987     if((unsigned int)index<m_projList.GetCount())
00988     {
00989         m_projList.Item(index).status = status;
00990     }
00991     else
00992     {
00993         wxMessageBox(wxString::Format(_("Error: Could not set status, project with index %d is not in list."),index),_("Error!"),wxOK | wxICON_INFORMATION );
00994     }
00995 }
00996 
00997 void Batch::SwapProject(int index)
00998 {
00999     Project* proj = m_projList.Detach(index+1);
01000     m_projList.Insert(proj,index);
01001 }
01002 
01003 void Batch::ShowOutput(bool isVisible)
01004 {
01005     for(unsigned int i=0; i<m_stitchFrames.Count(); i++)
01006     {
01007         m_stitchFrames.Item(i)->Show(isVisible);
01008     };
01009 };
01010 
01011 wxString Batch::GetFailedProjectName(unsigned int i)
01012 {
01013     if(i<m_failedProjects.size())
01014     {
01015         return m_failedProjects[i].project;
01016     }
01017     else
01018     {
01019         return wxEmptyString;
01020     }
01021 };
01022 
01023 wxString Batch::GetFailedProjectLog(unsigned int i)
01024 {
01025     if(i<m_failedProjects.size())
01026     {
01027         return m_failedProjects[i].logfile;
01028     }
01029     else
01030     {
01031         return wxEmptyString;
01032     }
01033 };

Generated on 21 Nov 2017 for Hugintrunk by  doxygen 1.4.7