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

Generated on Wed Apr 23 01:25:38 2014 for Hugintrunk by  doxygen 1.3.9.1