1 // -*- c-basic-offset: 4 -*-
2 
3 /** @file BatchFrame.cpp
4  *
5  *  @brief Batch processor for Hugin with GUI
6  *
7  *  @author Marko Kuder <marko.kuder@gmail.com>
8  *
9  *  $Id: BatchFrame.cpp 3322 2008-08-18 1:10:07Z mkuder $
10  *
11  *  This program is free software; you can redistribute it and/or
12  *  modify it under the terms of the GNU General Public
13  *  License as published by the Free Software Foundation; either
14  *  version 2 of the License, or (at your option) any later version.
15  *
16  *  This software is distributed in the hope that it will be useful,
17  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  *  General Public License for more details.
20  *
21  *  You should have received a copy of the GNU General Public
22  *  License along with this software. If not, see
23  *  <http://www.gnu.org/licenses/>.
24  *
25  */
26 
27 #include "BatchFrame.h"
28 #include <wx/stdpaths.h>
29 #include "PTBatcherGUI.h"
30 #include "FindPanoDialog.h"
31 #include "FailedProjectsDialog.h"
32 #ifdef __WXMSW__
33 #include <powrprof.h>
34 #ifdef _MSC_VER
35 #pragma comment(lib, "PowrProf.lib")
36 #endif
37 #if wxCHECK_VERSION(3,1,0)
38 #include <wx/taskbarbutton.h>
39 #endif
40 #endif
41 
42 /* file drag and drop handler method */
OnDropFiles(wxCoord x,wxCoord y,const wxArrayString & filenames)43 bool BatchDropTarget::OnDropFiles(wxCoord x, wxCoord y, const wxArrayString& filenames)
44 {
45     BatchFrame* MyBatchFrame = wxGetApp().GetFrame();
46     if (!MyBatchFrame)
47     {
48         return false;
49     }
50     if(filenames.GetCount()==0)
51     {
52         return false;
53     }
54     for(unsigned int i=0; i< filenames.GetCount(); i++)
55     {
56         wxFileName file(filenames[i]);
57         if(file.HasExt())
58         {
59             if (file.GetExt().CmpNoCase(wxT("pto")) == 0 ||
60                     file.GetExt().CmpNoCase(wxT("ptp")) == 0 ||
61                     file.GetExt().CmpNoCase(wxT("pts")) == 0 )
62             {
63                 if(file.FileExists())
64                 {
65                     MyBatchFrame->AddToList(filenames[i]);
66                 }
67             };
68         }
69         else
70         {
71             if(file.DirExists())
72             {
73                 MyBatchFrame->AddDirToList(filenames[i]);
74             }
75         };
76     };
77     return true;
78 };
79 
80 enum
81 {
82     EVT_TIMER_UPDATE_LISTBOX
83 };
84 
BEGIN_EVENT_TABLE(BatchFrame,wxFrame)85 BEGIN_EVENT_TABLE(BatchFrame, wxFrame)
86     EVT_TOOL(XRCID("tool_clear"),BatchFrame::OnButtonClear)
87     EVT_TOOL(XRCID("tool_open"),BatchFrame::OnButtonOpenBatch)
88     EVT_TOOL(XRCID("tool_save"),BatchFrame::OnButtonSaveBatch)
89     EVT_TOOL(XRCID("tool_start"),BatchFrame::OnButtonRunBatch)
90     EVT_TOOL(XRCID("tool_skip"),BatchFrame::OnButtonSkip)
91     EVT_TOOL(XRCID("tool_pause"),BatchFrame::OnButtonPause)
92     EVT_TOOL(XRCID("tool_cancel"),BatchFrame::OnButtonCancel)
93     EVT_TOOL(XRCID("tool_add"),BatchFrame::OnButtonAddToStitchingQueue)
94     EVT_TOOL(XRCID("tool_remove"),BatchFrame::OnButtonRemoveFromList)
95     EVT_TOOL(XRCID("tool_adddir"),BatchFrame::OnButtonAddDir)
96     EVT_MENU(XRCID("menu_add"),BatchFrame::OnButtonAddToStitchingQueue)
97     EVT_MENU(XRCID("menu_add_assistant"),BatchFrame::OnButtonAddToAssistantQueue)
98     EVT_MENU(XRCID("menu_remove"),BatchFrame::OnButtonRemoveFromList)
99     EVT_MENU(XRCID("menu_adddir"),BatchFrame::OnButtonAddDir)
100     EVT_MENU(XRCID("menu_searchpano"), BatchFrame::OnButtonSearchPano)
101     EVT_MENU(XRCID("menu_open"),BatchFrame::OnButtonOpenBatch)
102     EVT_MENU(XRCID("menu_save"),BatchFrame::OnButtonSaveBatch)
103     EVT_MENU(XRCID("menu_clear"),BatchFrame::OnButtonClear)
104     EVT_MENU(XRCID("menu_tray"), BatchFrame::OnMinimizeTrayMenu)
105     EVT_MENU(XRCID("menu_exit"),BatchFrame::OnUserExit)
106     EVT_MENU(XRCID("menu_help"),BatchFrame::OnButtonHelp)
107     EVT_BUTTON(XRCID("button_addcommand"),BatchFrame::OnButtonAddCommand)
108     EVT_BUTTON(XRCID("button_remove"),BatchFrame::OnButtonRemoveComplete)
109     EVT_BUTTON(XRCID("button_prefix"),BatchFrame::OnButtonChangePrefix)
110     EVT_BUTTON(XRCID("button_reset"),BatchFrame::OnButtonReset)
111     EVT_BUTTON(XRCID("button_resetall"),BatchFrame::OnButtonResetAll)
112     EVT_BUTTON(XRCID("button_edit"),BatchFrame::OnButtonOpenWithHugin)
113     EVT_BUTTON(XRCID("button_move_up"),BatchFrame::OnButtonMoveUp)
114     EVT_BUTTON(XRCID("button_move_down"),BatchFrame::OnButtonMoveDown)
115     EVT_CHECKBOX(XRCID("cb_overwrite"), BatchFrame::OnCheckOverwrite)
116     EVT_CHOICE(XRCID("choice_end"), BatchFrame::OnChoiceEnd)
117     EVT_CHECKBOX(XRCID("cb_verbose"), BatchFrame::OnCheckVerbose)
118     EVT_CHECKBOX(XRCID("cb_autoremove"), BatchFrame::OnCheckAutoRemove)
119     EVT_CHECKBOX(XRCID("cb_autostitch"), BatchFrame::OnCheckAutoStitch)
120     EVT_CHECKBOX(XRCID("cb_savelog"), BatchFrame::OnCheckSaveLog)
121     EVT_END_PROCESS(-1, BatchFrame::OnProcessTerminate)
122     EVT_CLOSE(BatchFrame::OnClose)
123     EVT_TIMER(EVT_TIMER_UPDATE_LISTBOX, BatchFrame::OnUpdateListBox)
124     EVT_COMMAND(wxID_ANY, EVT_BATCH_FAILED, BatchFrame::OnBatchFailed)
125     EVT_COMMAND(wxID_ANY, EVT_INFORMATION, BatchFrame::OnBatchInformation)
126     EVT_COMMAND(wxID_ANY, EVT_UPDATE_PARENT, BatchFrame::OnRefillListBox)
127     EVT_COMMAND(wxID_ANY, EVT_QUEUE_PROGRESS, BatchFrame::OnProgress)
128     EVT_ICONIZE(BatchFrame::OnMinimize)
129 END_EVENT_TABLE()
130 
131 BatchFrame::BatchFrame(wxLocale* locale, wxString xrc)
132 {
133     this->SetLocaleAndXRC(locale,xrc);
134     m_cancelled = false;
135 
136     //load xrc resources
137     wxXmlResource::Get()->LoadFrame(this, (wxWindow* )NULL, wxT("batch_frame"));
138     // load our menu bar
139 #ifdef __WXMAC__
140     wxApp::s_macExitMenuItemId = XRCID("menu_exit");
141     wxApp::s_macHelpMenuTitleName = _("&Help");
142 #endif
143     SetMenuBar(wxXmlResource::Get()->LoadMenuBar(this, wxT("batch_menu")));
144 
145     // create tool bar
146     SetToolBar(wxXmlResource::Get()->LoadToolBar(this, wxT("batch_toolbar")));
147 
148     int widths[2] = { -1, 150 };
149     CreateStatusBar(2);
150     SetStatusWidths(2, widths);
151     SetStatusText(_("Not doing much..."));
152 
153     // set the minimize icon
154 #ifdef __WXMSW__
155     m_iconNormal = wxIcon(m_xrcPrefix + wxT("data/ptbatcher.ico"), wxBITMAP_TYPE_ICO);
156     m_iconRunning = wxIcon(m_xrcPrefix + wxT("data/ptbatcher_running.ico"), wxBITMAP_TYPE_ICO);
157     m_iconPaused = wxIcon(m_xrcPrefix + wxT("data/ptbatcher_pause.ico"), wxBITMAP_TYPE_ICO);
158 #else
159     m_iconNormal = wxIcon(m_xrcPrefix + wxT("data/ptbatcher.png"), wxBITMAP_TYPE_PNG);
160     m_iconRunning = wxIcon(m_xrcPrefix + wxT("data/ptbatcher_running.png"), wxBITMAP_TYPE_PNG);
161     m_iconPaused = wxIcon(m_xrcPrefix + wxT("data/ptbatcher_pause.png"), wxBITMAP_TYPE_PNG);
162 #endif
163     SetIcon(m_iconNormal);
164 
165     m_batch = new Batch(this);
166     if(wxGetKeyState(WXK_COMMAND))
167     {
168 #ifdef __WXMAC__
169         wxString text(_("You have pressed the Command key."));
170 #else
171         wxString text(_("You have pressed the Control key."));
172 #endif
173         text.Append(wxT("\n"));
174         text.Append(_("Should the loading of the batch queue be skipped?"));
175         if(wxMessageBox(text,
176 #ifdef __WXMSW__
177             wxT("PTBatcherGUI"),
178 #else
179             wxEmptyString,
180 #endif
181             wxYES_NO | wxICON_EXCLAMATION, NULL)==wxNO)
182         {
183             m_batch->LoadTemp();
184         }
185         else
186         {
187             // save empty batch queue
188             m_batch->SaveTemp();
189         };
190     }
191     else
192     {
193         m_batch->LoadTemp();
194     };
195     projListBox = XRCCTRL(*this,"project_listbox",ProjectListBox);
196     // fill at end list box, check which options are available
197     m_endChoice = XRCCTRL(*this, "choice_end", wxChoice);
198     m_endChoice->Clear();
199     m_endChoice->Append(_("Do nothing"), (void*)Batch::DO_NOTHING);
200     m_endChoice->Append(_("Close PTBatcherGUI"), (void*)Batch::CLOSE_PTBATCHERGUI);
201 #if !defined __WXMAC__ && !defined __WXOSX_COCOA__
202     // there is no wxShutdown for wxMac
203     m_endChoice->Append(_("Shutdown computer"), (void*)Batch::SHUTDOWN);
204 #endif
205 #ifdef __WXMSW__
206     SYSTEM_POWER_CAPABILITIES pwrCap;
207     if (GetPwrCapabilities(&pwrCap))
208     {
209         if (pwrCap.SystemS3)
210         {
211             m_endChoice->Append(_("Suspend computer"), (void*)Batch::SUSPEND);
212         };
213         if (pwrCap.SystemS4 && pwrCap.HiberFilePresent)
214         {
215             m_endChoice->Append(_("Hibernate computer"), (void*)Batch::HIBERNATE);
216         };
217     };
218 #endif
219 
220     //TO-DO: include a batch or project progress gauge?
221     projListBox->Fill(m_batch);
222     SetDropTarget(new BatchDropTarget());
223 
224     m_tray = NULL;
225     if (wxTaskBarIcon::IsAvailable())
226     {
227         // minimize to tray is by default disabled
228         // activate only if task bar icon is available
229         GetMenuBar()->Enable(XRCID("menu_tray"), true);
230         bool minTray;
231         // tray icon is disabled by default
232         wxConfigBase::Get()->Read(wxT("/BatchFrame/minimizeTray"), &minTray, false);
233         GetMenuBar()->Check(XRCID("menu_tray"), minTray);
234         UpdateTrayIcon(minTray);
235     }
236 
237     UpdateTaskBarProgressBar();
238 
239 #ifndef __WXMSW__
240     // check settings of help window and fix when needed
241     FixHelpSettings();
242 #endif
243     m_updateProjectsTimer = new wxTimer(this, EVT_TIMER_UPDATE_LISTBOX);
244     // start timer for check for updates in project files
245     m_updateProjectsTimer->StartOnce(5000);
246 }
247 
OnCreateStatusBar(int number,long style,wxWindowID id,const wxString & name)248 wxStatusBar* BatchFrame::OnCreateStatusBar(int number, long style, wxWindowID id, const wxString& name)
249 {
250     m_progStatusBar = new ProgressStatusBar(this, id, style, name);
251     m_progStatusBar->SetFieldsCount(number);
252     return m_progStatusBar;
253 }
254 
IsRunning()255 bool BatchFrame::IsRunning()
256 {
257     return m_batch->IsRunning();
258 };
259 
IsPaused()260 bool BatchFrame::IsPaused()
261 {
262     return m_batch->IsPaused();
263 };
264 
OnUpdateListBox(wxTimerEvent & event)265 void BatchFrame::OnUpdateListBox(wxTimerEvent& event)
266 {
267     wxFileName tempFile;
268     bool change = false;
269     for(int i = 0; i< m_batch->GetProjectCount(); i++)
270     {
271         if(m_batch->GetProject(i)->id >= 0 && m_batch->GetStatus(i)!=Project::FINISHED)
272         {
273             tempFile.Assign(m_batch->GetProject(i)->path);
274             if(tempFile.FileExists())
275             {
276                 wxDateTime modify;
277                 modify=tempFile.GetModificationTime();
278                 if(m_batch->GetProject(i)->skip)
279                 {
280                     change = true;
281                     m_batch->GetProject(i)->skip = false;
282                     m_batch->SetStatus(i,Project::WAITING);
283                     projListBox->ReloadProject(projListBox->GetIndex(m_batch->GetProject(i)->id),m_batch->GetProject(i));
284                 }
285                 else if(!modify.IsEqualTo(m_batch->GetProject(i)->modDate))
286                 {
287                     change = true;
288                     m_batch->GetProject(i)->modDate = modify;
289                     m_batch->GetProject(i)->ResetOptions();
290                     if(m_batch->GetProject(i)->target==Project::STITCHING)
291                     {
292                         m_batch->SetStatus(i,Project::WAITING);
293                     };
294                     projListBox->ReloadProject(projListBox->GetIndex(m_batch->GetProject(i)->id),m_batch->GetProject(i));
295                 }
296             }
297             else
298             {
299                 if(m_batch->GetStatus(i) != Project::MISSING)
300                 {
301                     change = true;
302                     m_batch->GetProject(i)->skip = true;
303                     m_batch->SetStatus(i,Project::MISSING);
304                     projListBox->SetMissing(projListBox->GetIndex(m_batch->GetProject(i)->id));
305                 }
306             }
307         }
308         if(projListBox->UpdateStatus(i,m_batch->GetProject(i)))
309         {
310             change = true;
311         }
312     }
313     if(change)
314     {
315         m_batch->SaveTemp();
316     };
317     // start timer again
318     m_updateProjectsTimer->StartOnce(2000);
319 };
320 
OnUserExit(wxCommandEvent & event)321 void BatchFrame::OnUserExit(wxCommandEvent& event)
322 {
323     Close(true);
324 };
325 
OnButtonAddCommand(wxCommandEvent & event)326 void BatchFrame::OnButtonAddCommand(wxCommandEvent& event)
327 {
328     wxTextEntryDialog dlg(this,_("Please enter the command-line application to execute:"),_("Enter application"));
329     wxTheApp->SetEvtHandlerEnabled(false);
330     if(dlg.ShowModal() == wxID_OK)
331     {
332         wxString line = dlg.GetValue();
333         m_batch->AddAppToBatch(line);
334         //SetStatusText(_T("Added application"));
335         projListBox->AppendProject(m_batch->GetProject(m_batch->GetProjectCount()-1));
336         m_batch->SaveTemp();
337     }
338     wxTheApp->SetEvtHandlerEnabled(true);
339 }
340 
OnButtonAddDir(wxCommandEvent & event)341 void BatchFrame::OnButtonAddDir(wxCommandEvent& event)
342 {
343     wxString defaultdir = wxConfigBase::Get()->Read(wxT("/BatchFrame/actualPath"),wxT(""));
344     wxDirDialog dlg(this,
345                     _("Specify a directory to search for projects in"),
346                     defaultdir, wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST);
347     dlg.SetPath(wxConfigBase::Get()->Read(wxT("/BatchFrame/actualPath"),wxT("")));
348     if (dlg.ShowModal() == wxID_OK)
349     {
350         wxConfig::Get()->Write(wxT("/BatchFrame/actualPath"), dlg.GetPath());  // remember for later
351         AddDirToList(dlg.GetPath());
352     };
353 }
354 
OnButtonSearchPano(wxCommandEvent & e)355 void BatchFrame::OnButtonSearchPano(wxCommandEvent& e)
356 {
357     FindPanoDialog findpano_dlg(this,m_xrcPrefix);
358     findpano_dlg.ShowModal();
359 };
360 
OnButtonAddToStitchingQueue(wxCommandEvent & event)361 void BatchFrame::OnButtonAddToStitchingQueue(wxCommandEvent& event)
362 {
363     wxString defaultdir = wxConfigBase::Get()->Read(wxT("/BatchFrame/actualPath"),wxT(""));
364     wxFileDialog dlg(0,
365                      _("Specify project source file(s)"),
366                      defaultdir, wxT(""),
367                      _("Project files (*.pto)|*.pto|All files (*)|*"),
368                      wxFD_OPEN | wxFD_MULTIPLE, wxDefaultPosition);
369     dlg.SetDirectory(defaultdir);
370 
371     if (dlg.ShowModal() == wxID_OK)
372     {
373         wxArrayString paths;
374         dlg.GetPaths(paths);
375 #ifdef __WXGTK__
376         //workaround a bug in GTK, see https://bugzilla.redhat.com/show_bug.cgi?id=849692 and http://trac.wxwidgets.org/ticket/14525
377         wxConfig::Get()->Write(wxT("/BatchFrame/actualPath"), wxPathOnly(paths[0]));  // remember for later
378 #else
379         wxConfig::Get()->Write(wxT("/BatchFrame/actualPath"), dlg.GetDirectory());  // remember for later
380 #endif
381         for(unsigned int i=0; i<paths.GetCount(); i++)
382         {
383             AddToList(paths.Item(i));
384         }
385         m_batch->SaveTemp();
386     };
387 }
388 
OnButtonAddToAssistantQueue(wxCommandEvent & event)389 void BatchFrame::OnButtonAddToAssistantQueue(wxCommandEvent& event)
390 {
391     wxString defaultdir = wxConfigBase::Get()->Read(wxT("/BatchFrame/actualPath"),wxT(""));
392     wxFileDialog dlg(0,
393                      _("Specify project source file(s)"),
394                      defaultdir, wxT(""),
395                      _("Project files (*.pto)|*.pto|All files (*)|*"),
396                      wxFD_OPEN | wxFD_MULTIPLE, wxDefaultPosition);
397     dlg.SetDirectory(defaultdir);
398 
399     if (dlg.ShowModal() == wxID_OK)
400     {
401         wxArrayString paths;
402         dlg.GetPaths(paths);
403 #ifdef __WXGTK__
404         //workaround a bug in GTK, see https://bugzilla.redhat.com/show_bug.cgi?id=849692 and http://trac.wxwidgets.org/ticket/14525
405         wxConfig::Get()->Write(wxT("/BatchFrame/actualPath"), wxPathOnly(paths[0]));  // remember for later
406 #else
407         wxConfig::Get()->Write(wxT("/BatchFrame/actualPath"), dlg.GetDirectory());  // remember for later
408 #endif
409 
410         for(unsigned int i=0; i<paths.GetCount(); i++)
411         {
412             AddToList(paths.Item(i),Project::DETECTING);
413         }
414         m_batch->SaveTemp();
415     };
416 }
417 
AddDirToList(wxString aDir)418 void BatchFrame::AddDirToList(wxString aDir)
419 {
420     //we traverse all subdirectories of chosen path
421     DirTraverser traverser;
422     wxDir dir(aDir);
423     dir.Traverse(traverser);
424     wxArrayString projects = traverser.GetProjectFiles();
425     for(unsigned int i=0; i<projects.GetCount(); i++)
426     {
427         m_batch->AddProjectToBatch(projects.Item(i));
428         Project* proj=m_batch->GetProject(m_batch->GetProjectCount()-1);
429         if(!proj->isAligned)
430         {
431             proj->target=Project::DETECTING;
432         };
433         projListBox->AppendProject(proj);
434     };
435     m_batch->SaveTemp();
436     SetStatusText(wxString::Format(_("Added projects from dir %s"), aDir.c_str()));
437 };
438 
AddToList(wxString aFile,Project::Target target)439 void BatchFrame::AddToList(wxString aFile,Project::Target target)
440 {
441     m_batch->AddProjectToBatch(aFile,wxT(""),target);
442     wxString s;
443     switch(target)
444     {
445         case Project::STITCHING:
446             s=wxString::Format(_("Add project %s to stitching queue."),aFile.c_str());
447             break;
448         case Project::DETECTING:
449             s=wxString::Format(_("Add project %s to assistant queue."),aFile.c_str());
450             break;
451     };
452     SetStatusInformation(s);
453     projListBox->AppendProject(m_batch->GetProject(m_batch->GetProjectCount()-1));
454     m_batch->SaveTemp();
455 }
456 
457 
OnButtonCancel(wxCommandEvent & event)458 void BatchFrame::OnButtonCancel(wxCommandEvent& event)
459 {
460     GetToolBar()->ToggleTool(XRCID("tool_pause"),false);
461     m_cancelled = true;
462     m_batch->CancelBatch();
463     SetStatusInformation(_("Batch stopped"));
464     if (m_tray)
465     {
466         m_tray->SetIcon(m_iconNormal, _("Hugin's Batch processor"));
467     };
468 }
469 
OnButtonChangePrefix(wxCommandEvent & event)470 void BatchFrame::OnButtonChangePrefix(wxCommandEvent& event)
471 {
472     const HuginBase::UIntSet selected(projListBox->GetSelectedProjects());
473     if(selected.size()== 1)
474     {
475         Project* project = m_batch->GetProject(*selected.begin());
476         if (project->target == Project::STITCHING)
477         {
478             wxFileName prefix(project->prefix);
479             wxFileDialog dlg(0, wxString::Format(_("Specify output prefix for project %s"), project->path),
480                              prefix.GetPath(),
481                              prefix.GetFullName(), wxT(""),
482                              wxFD_SAVE, wxDefaultPosition);
483             if (dlg.ShowModal() == wxID_OK)
484             {
485                 while(containsInvalidCharacters(dlg.GetPath()))
486                 {
487                     wxArrayString list;
488                     list.Add(dlg.GetPath());
489                     ShowFilenameWarning(this, list);
490                     if(dlg.ShowModal()!=wxID_OK)
491                     {
492                         return;
493                     }
494                 };
495                 wxFileName prefix(dlg.GetPath());
496                 while (!prefix.IsDirWritable())
497                 {
498                     wxMessageBox(wxString::Format(_("You have no permissions to write in folder \"%s\".\nPlease select another folder for the final output."), prefix.GetPath().c_str()),
499 #ifdef __WXMSW__
500                         wxT("PTBatcherGUI"),
501 #else
502                         wxT(""),
503 #endif
504                         wxOK | wxICON_INFORMATION);
505                     if (dlg.ShowModal() != wxID_OK)
506                     {
507                         return;
508                     };
509                     prefix = dlg.GetPath();
510                 };
511 
512                 wxString outname(dlg.GetPath());
513                 ChangePrefix(*selected.begin(), outname);
514                 //SetStatusText(_T("Changed prefix for "+projListBox->GetSelectedProject()));
515                 m_batch->SaveTemp();
516             }
517         }
518         else
519         {
520             SetStatusText(_("The prefix of an assistant target cannot be changed."));
521             wxBell();
522         };
523     }
524     else
525     {
526         if (selected.empty())
527         {
528             SetStatusText(_("Please select a project"));
529         }
530         else
531         {
532             wxBell();
533             SetStatusText(_("Please select only one project"));
534         };
535     };
536 }
537 
ChangePrefix(int index,wxString newPrefix)538 void BatchFrame::ChangePrefix(int index,wxString newPrefix)
539 {
540     int i;
541     if(index!=-1)
542     {
543         i=index;
544     }
545     else
546     {
547         i=m_batch->GetProjectCount()-1;
548     }
549     m_batch->ChangePrefix(i,newPrefix);
550     projListBox->ChangePrefix(i,newPrefix);
551 }
552 
OnButtonClear(wxCommandEvent & event)553 void BatchFrame::OnButtonClear(wxCommandEvent& event)
554 {
555     int returnCode = m_batch->ClearBatch();
556     if(returnCode == 0)
557     {
558         projListBox->DeleteAllItems();
559     }
560     else if(returnCode == 2)
561     {
562         m_cancelled = true;
563         projListBox->DeleteAllItems();
564         if(GetToolBar()->GetToolState(XRCID("tool_pause")))
565         {
566             GetToolBar()->ToggleTool(XRCID("tool_pause"),false);
567         }
568     }
569     m_batch->SaveTemp();
570 }
571 
OnButtonHelp(wxCommandEvent & event)572 void BatchFrame::OnButtonHelp(wxCommandEvent& event)
573 {
574     DEBUG_TRACE("");
575 #if defined __wxMSW__ && !(wxCHECK_VERSION(3,1,1))
576     // wxWidgets 3.x has a bug, that prevents DisplaySection to work on Win8/10 64 bit
577     // see: http://trac.wxwidgets.org/ticket/14888
578     // so using DisplayContents() and our own implementation of HuginCHMHelpController
579     GetHelpController().DisplayHelpPage(wxT("Hugin_Batch_Processor.html"));
580 #else
581     GetHelpController().DisplaySection(wxT("Hugin_Batch_Processor.html"));
582 #endif
583 }
584 
OnButtonMoveDown(wxCommandEvent & event)585 void BatchFrame::OnButtonMoveDown(wxCommandEvent& event)
586 {
587     const HuginBase::UIntSet selected(projListBox->GetSelectedProjects());
588     if (selected.size() == 1)
589     {
590         SwapProject(*selected.begin(), true);
591         m_batch->SaveTemp();
592     }
593     else
594     {
595         wxBell();
596     };
597 }
598 
OnButtonMoveUp(wxCommandEvent & event)599 void BatchFrame::OnButtonMoveUp(wxCommandEvent& event)
600 {
601     const HuginBase::UIntSet selected(projListBox->GetSelectedProjects());
602     if (selected.size() == 1)
603     {
604         SwapProject(*selected.begin() - 1, false);
605         m_batch->SaveTemp();
606     }
607     else
608     {
609         wxBell();
610     };
611 }
612 
OnButtonOpenBatch(wxCommandEvent & event)613 void BatchFrame::OnButtonOpenBatch(wxCommandEvent& event)
614 {
615     wxString defaultdir = wxConfigBase::Get()->Read(wxT("/BatchFrame/batchPath"),wxT(""));
616     wxFileDialog dlg(0,
617                      _("Specify batch file to open"),
618                      defaultdir, wxT(""),
619                      _("Batch files (*.ptb)|*.ptb;|All files (*)|*"),
620                      wxFD_OPEN, wxDefaultPosition);
621     if (dlg.ShowModal() == wxID_OK)
622     {
623         wxConfig::Get()->Write(wxT("/BatchFrame/batchPath"), dlg.GetDirectory());  // remember for later
624         int clearCode = m_batch->LoadBatchFile(dlg.GetPath());
625         //1 is error code for not clearing batch
626         if(clearCode!=1)
627         {
628             /*if(clearCode==2) //we just cancelled the batch, so we need to try loading again
629             	m_batch->LoadBatchFile(dlg.GetPath());*/
630             projListBox->DeleteAllItems();
631             projListBox->Fill(m_batch);
632             m_batch->SaveTemp();
633         }
634     }
635 }
636 
OnButtonOpenWithHugin(wxCommandEvent & event)637 void BatchFrame::OnButtonOpenWithHugin(wxCommandEvent& event)
638 {
639     const wxFileName exePath(wxStandardPaths::Get().GetExecutablePath());
640     const HuginBase::UIntSet selected(projListBox->GetSelectedProjects());
641     if (selected.size() == 1)
642     {
643         if (projListBox->GetText(*selected.begin(), 0).Cmp(_T("")) != 0)
644 #ifdef __WXMAC__
645             wxExecute(_T("open -b net.sourceforge.Hugin \"" + m_batch->GetProject(*selected.begin())->path + _T("\"")));
646 #else
647             wxExecute(exePath.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR) + _T("hugin \"" + m_batch->GetProject(*selected.begin())->path + _T("\" -notips")));
648 #endif
649         else
650         {
651             SetStatusText(_("Cannot open app in Hugin."));
652         };
653     }
654     else
655     {
656         if (selected.empty())
657         {
658             //ask user if he/she wants to load an empty project
659             wxMessageDialog message(this, _("No project selected. Open Hugin without project?"),
660 #ifdef _WIN32
661                 _("PTBatcherGUI"),
662 #else
663                 wxT(""),
664 #endif
665                 wxYES_NO | wxICON_INFORMATION);
666             if (message.ShowModal() == wxID_YES)
667             {
668 #ifdef __WXMAC__
669                 wxExecute(_T("open -b net.sourceforge.Hugin"));
670 #else
671                 wxExecute(exePath.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR) + _T("hugin"));
672 #endif
673             }
674         }
675         else
676         {
677             wxBell();
678             SetStatusText(_("Please select only one project"));
679         };
680     };
681 }
682 
OnButtonPause(wxCommandEvent & event)683 void BatchFrame::OnButtonPause(wxCommandEvent& event)
684 {
685     if(m_batch->GetRunningCount()>0)
686     {
687         if(!m_batch->IsPaused())
688         {
689             m_batch->PauseBatch();
690             GetToolBar()->ToggleTool(XRCID("tool_pause"),true);
691             SetStatusInformation(_("Batch paused"));
692             if (m_tray)
693             {
694                 m_tray->SetIcon(m_iconPaused, _("Pausing processing Hugin's batch queue"));
695             };
696         }
697         else
698         {
699             m_batch->PauseBatch();
700             GetToolBar()->ToggleTool(XRCID("tool_pause"),false);
701             SetStatusInformation(_("Continuing batch..."));
702             if (m_tray)
703             {
704                 m_tray->SetIcon(m_iconRunning, _("Processing Hugin's batch queue"));
705             };
706         }
707     }
708     else //if no projects are running, we deactivate the button
709     {
710         GetToolBar()->ToggleTool(XRCID("tool_pause"),false);
711     }
712     UpdateTaskBarProgressBar();
713 }
714 
OnButtonRemoveComplete(wxCommandEvent & event)715 void BatchFrame::OnButtonRemoveComplete(wxCommandEvent& event)
716 {
717     bool removeErrors=false;
718     if(!m_batch->NoErrors())
719     {
720         wxMessageDialog message(this,_("There are failed projects in the list.\nRemove them too?"),
721 #ifdef _WIN32
722                                 _("PTBatcherGUI"),
723 #else
724                                 wxT(""),
725 #endif
726                                 wxYES_NO | wxICON_INFORMATION );
727         if(message.ShowModal()==wxID_YES)
728         {
729             removeErrors=true;
730         }
731     }
732     for(int i=projListBox->GetItemCount()-1; i>=0; i--)
733     {
734         if(m_batch->GetStatus(i)==Project::FINISHED ||
735                 (removeErrors && m_batch->GetStatus(i)==Project::FAILED))
736         {
737             projListBox->Deselect(i);
738             projListBox->DeleteItem(i);
739             m_batch->RemoveProjectAtIndex(i);
740         }
741     }
742     m_batch->SaveTemp();
743 }
744 
OnButtonRemoveFromList(wxCommandEvent & event)745 void BatchFrame::OnButtonRemoveFromList(wxCommandEvent& event)
746 {
747 
748     const HuginBase::UIntSet selected = projListBox->GetSelectedProjects();
749     if(!selected.empty())
750     {
751         for (auto i = selected.rbegin(); i != selected.rend(); ++i)
752         {
753             const int selIndex = *i;
754             if (m_batch->GetStatus(selIndex) == Project::RUNNING || m_batch->GetStatus(selIndex) == Project::PAUSED)
755             {
756                 wxMessageDialog message(this, _("Cannot remove project in progress.\nDo you want to cancel it?"),
757 #ifdef _WIN32
758                     _("PTBatcherGUI"),
759 #else
760                     wxT(""),
761 #endif
762                     wxYES_NO | wxICON_INFORMATION);
763                 if (message.ShowModal() == wxID_YES)
764                 {
765                     OnButtonSkip(event);
766                 };
767             }
768             else
769             {
770                 SetStatusText(wxString::Format(_("Removed project %s"), m_batch->GetProject(selIndex)->path.c_str()));
771                 projListBox->Deselect(selIndex);
772                 projListBox->DeleteItem(selIndex);
773                 m_batch->RemoveProjectAtIndex(selIndex);
774                 m_batch->SaveTemp();
775             };
776         };
777     }
778     else
779     {
780         SetStatusText(_("Please select a project to remove"));
781     }
782 }
783 
784 
OnButtonReset(wxCommandEvent & event)785 void BatchFrame::OnButtonReset(wxCommandEvent& event)
786 {
787     const HuginBase::UIntSet selected(projListBox->GetSelectedProjects());
788     if(!selected.empty())
789     {
790         for (auto selIndex : selected)
791         {
792             if (m_batch->GetStatus(selIndex) == Project::RUNNING || m_batch->GetStatus(selIndex) == Project::PAUSED)
793             {
794                 wxMessageDialog message(this, _("Cannot reset project in progress.\nDo you want to cancel it?"),
795 #ifdef _WIN32
796                     _("PTBatcherGUI"),
797 #else
798                     wxT(""),
799 #endif
800                     wxYES_NO | wxICON_INFORMATION);
801                 if (message.ShowModal() == wxID_YES)
802                 {
803                     OnButtonSkip(event);
804                 }
805             }
806             else
807             {
808                 m_batch->SetStatus(selIndex, Project::WAITING);
809                 SetStatusText(wxString::Format(_("Reset project %s"), m_batch->GetProject(selIndex)->path.c_str()));
810             };
811         };
812     }
813     else
814     {
815         SetStatusText(_("Please select a project to reset"));
816     }
817     m_batch->SaveTemp();
818 }
819 
OnButtonResetAll(wxCommandEvent & event)820 void BatchFrame::OnButtonResetAll(wxCommandEvent& event)
821 {
822     if(m_batch->GetRunningCount()!=0)
823     {
824         wxMessageDialog message(this, _("Cannot reset projects in progress.\nDo you want to cancel the batch?"),
825 #ifdef _WIN32
826                                 _("PTBatcherGUI"),
827 #else
828                                 wxT(""),
829 #endif
830                                 wxYES_NO | wxICON_INFORMATION);
831         if(message.ShowModal()==wxID_YES)
832         {
833             OnButtonCancel(event);
834         }
835     }
836     else
837     {
838         for(int i=projListBox->GetItemCount()-1; i>=0; i--)
839         {
840             m_batch->SetStatus(i,Project::WAITING);
841         }
842     }
843     m_batch->SaveTemp();
844 }
845 
OnButtonRunBatch(wxCommandEvent & event)846 void BatchFrame::OnButtonRunBatch(wxCommandEvent& event)
847 {
848     if(m_batch->IsPaused())
849     {
850         //m_batch->paused = false;
851         OnButtonPause(event);
852     }
853     else
854     {
855         RunBatch();
856     }
857 }
858 
OnButtonSaveBatch(wxCommandEvent & event)859 void BatchFrame::OnButtonSaveBatch(wxCommandEvent& event)
860 {
861     wxString defaultdir = wxConfigBase::Get()->Read(wxT("/BatchFrame/batchPath"),wxT(""));
862     wxFileDialog dlg(0,
863                      _("Specify batch file to save"),
864                      defaultdir, wxT(""),
865                      _("Batch file (*.ptb)|*.ptb;|All files (*)|*"),
866                      wxFD_SAVE | wxFD_OVERWRITE_PROMPT, wxDefaultPosition);
867     if (dlg.ShowModal() == wxID_OK)
868     {
869         wxConfig::Get()->Write(wxT("/BatchFrame/batchPath"), dlg.GetDirectory());  // remember for later
870         m_batch->SaveBatchFile(dlg.GetPath());
871     }
872 }
873 
OnButtonSkip(wxCommandEvent & event)874 void BatchFrame::OnButtonSkip(wxCommandEvent& event)
875 {
876     const HuginBase::UIntSet selected(projListBox->GetSelectedProjects());
877     if(!selected.empty())
878     {
879         for (auto selIndex : selected)
880         {
881             if (m_batch->GetStatus(selIndex) == Project::RUNNING
882                 || m_batch->GetStatus(selIndex) == Project::PAUSED)
883             {
884                 if (m_batch->GetStatus(selIndex) == Project::PAUSED)
885                 {
886                     if (m_batch->GetRunningCount() == 1)
887                     {
888                         GetToolBar()->ToggleTool(XRCID("tool_pause"), false);
889                     }
890                     for (int i = 0; i < m_batch->GetRunningCount(); i++)
891                     {
892                         if (m_batch->GetStatus(selIndex) == Project::PAUSED
893                             && m_batch->CompareProjectsInLists(i, selIndex))
894                         {
895                             m_batch->CancelProject(i);
896                         }
897                     }
898                 }
899                 else
900                 {
901                     //we go through all running projects to find the one with the same id as chosen one
902                     for (int i = 0; i < m_batch->GetRunningCount(); i++)
903                     {
904                         if (m_batch->GetStatus(selIndex) == Project::RUNNING
905                             && m_batch->CompareProjectsInLists(i, selIndex))
906                         {
907                             m_batch->CancelProject(i);
908                         }
909                     }
910                 }
911             }
912             else
913             {
914                 m_batch->SetStatus(selIndex, Project::FAILED);
915             };
916         };
917     }
918 }
919 
SelectEndTask(wxControlWithItems * list,const Batch::EndTask endTask)920 void SelectEndTask(wxControlWithItems* list, const Batch::EndTask endTask)
921 {
922     for (unsigned int i = 0; i<list->GetCount(); i++)
923     {
924         if (static_cast<Batch::EndTask>((size_t)list->GetClientData(i)) == endTask)
925         {
926             list->SetSelection(i);
927             return;
928         };
929     };
930     list->SetSelection(0);
931 };
932 
SetCheckboxes()933 void BatchFrame::SetCheckboxes()
934 {
935     wxConfigBase* config=wxConfigBase::Get();
936     int i;
937     // read older version
938 #if defined __WXMAC__ || defined __WXOSX_COCOA__
939     i = 0;
940 #else
941     i=config->Read(wxT("/BatchFrame/ShutdownCheck"), 0l);
942 #endif
943     if (i != 0)
944     {
945         SelectEndTask(m_endChoice, Batch::SHUTDOWN);
946         m_batch->atEnd = Batch::SHUTDOWN;
947     };
948     config->DeleteEntry(wxT("/BatchFrame/ShutdownCheck"));
949     // now read current version
950     i = config->Read(wxT("/BatchFrame/AtEnd"), 0l);
951 #if defined __WXMAC__ || defined __WXOSX_COCOA__
952     // wxWidgets for MacOS does not support wxShutdown
953     if (i == Batch::SHUTDOWN)
954     {
955         i = 0;
956     };
957 #endif
958     m_batch->atEnd = static_cast<Batch::EndTask>(i);
959     SelectEndTask(m_endChoice, m_batch->atEnd);
960     i=config->Read(wxT("/BatchFrame/OverwriteCheck"), 0l);
961     XRCCTRL(*this,"cb_overwrite",wxCheckBox)->SetValue(i!=0);
962     m_batch->overwrite=(i!=0);
963     i=config->Read(wxT("/BatchFrame/VerboseCheck"), 0l);
964     XRCCTRL(*this,"cb_verbose",wxCheckBox)->SetValue(i!=0);
965     m_batch->verbose=(i!=0);
966     i=config->Read(wxT("/BatchFrame/AutoRemoveCheck"), 1l);
967     XRCCTRL(*this,"cb_autoremove",wxCheckBox)->SetValue(i!=0);
968     m_batch->autoremove=(i!=0);
969     i=config->Read(wxT("/BatchFrame/AutoStitchCheck"), 0l);
970     XRCCTRL(*this,"cb_autostitch",wxCheckBox)->SetValue(i!=0);
971     m_batch->autostitch=(i!=0);
972     i=config->Read(wxT("/BatchFrame/SaveLog"), 0l);
973     XRCCTRL(*this, "cb_savelog",wxCheckBox)->SetValue(i!=0);
974     m_batch->saveLog=(i!=0);
975 };
976 
GetEndTask()977 Batch::EndTask BatchFrame::GetEndTask()
978 {
979     return static_cast<Batch::EndTask>((size_t)m_endChoice->GetClientData(m_endChoice->GetSelection()));
980 };
981 
GetCheckOverwrite()982 bool BatchFrame::GetCheckOverwrite()
983 {
984     return XRCCTRL(*this,"cb_overwrite",wxCheckBox)->IsChecked();
985 };
986 
GetCheckVerbose()987 bool BatchFrame::GetCheckVerbose()
988 {
989     return XRCCTRL(*this,"cb_verbose",wxCheckBox)->IsChecked();
990 };
991 
GetCheckAutoRemove()992 bool BatchFrame::GetCheckAutoRemove()
993 {
994     return XRCCTRL(*this,"cb_autoremove",wxCheckBox)->IsChecked();
995 };
996 
GetCheckAutoStitch()997 bool BatchFrame::GetCheckAutoStitch()
998 {
999     return XRCCTRL(*this,"cb_autostitch",wxCheckBox)->IsChecked();
1000 };
1001 
GetCheckSaveLog()1002 bool BatchFrame::GetCheckSaveLog()
1003 {
1004     return XRCCTRL(*this,"cb_savelog",wxCheckBox)->IsChecked();
1005 };
1006 
OnCheckOverwrite(wxCommandEvent & event)1007 void BatchFrame::OnCheckOverwrite(wxCommandEvent& event)
1008 {
1009     wxConfigBase* config=wxConfigBase::Get();
1010     if(event.IsChecked())
1011     {
1012         m_batch->overwrite = true;
1013         config->Write(wxT("/BatchFrame/OverwriteCheck"), 1l);
1014     }
1015     else
1016     {
1017         m_batch->overwrite = false;
1018         config->Write(wxT("/BatchFrame/OverwriteCheck"), 0l);
1019     }
1020     config->Flush();
1021 }
1022 
OnChoiceEnd(wxCommandEvent & event)1023 void BatchFrame::OnChoiceEnd(wxCommandEvent& event)
1024 {
1025     m_batch->atEnd = static_cast<Batch::EndTask>((size_t)m_endChoice->GetClientData(event.GetSelection()));
1026     wxConfigBase* config=wxConfigBase::Get();
1027     config->Write(wxT("/BatchFrame/AtEnd"), static_cast<long>(m_batch->atEnd));
1028     config->Flush();
1029 }
1030 
OnCheckVerbose(wxCommandEvent & event)1031 void BatchFrame::OnCheckVerbose(wxCommandEvent& event)
1032 {
1033     wxConfigBase* config=wxConfigBase::Get();
1034     if(event.IsChecked())
1035     {
1036         m_batch->verbose = true;
1037         config->Write(wxT("/BatchFrame/VerboseCheck"), 1l);
1038     }
1039     else
1040     {
1041         m_batch->verbose = false;
1042         config->Write(wxT("/BatchFrame/VerboseCheck"), 0l);
1043     };
1044     config->Flush();
1045     m_batch->ShowOutput(m_batch->verbose);
1046 }
1047 
SetInternalVerbose(bool newVerbose)1048 void BatchFrame::SetInternalVerbose(bool newVerbose)
1049 {
1050     m_batch->verbose=newVerbose;
1051 };
1052 
OnCheckAutoRemove(wxCommandEvent & event)1053 void BatchFrame::OnCheckAutoRemove(wxCommandEvent& event)
1054 {
1055     m_batch->autoremove=event.IsChecked();
1056     wxConfigBase* config=wxConfigBase::Get();
1057     if(m_batch->autoremove)
1058     {
1059         config->Write(wxT("/BatchFrame/AutoRemoveCheck"), 1l);
1060     }
1061     else
1062     {
1063         config->Write(wxT("/BatchFrame/AutoRemoveCheck"), 0l);
1064     }
1065     config->Flush();
1066 };
1067 
OnCheckAutoStitch(wxCommandEvent & event)1068 void BatchFrame::OnCheckAutoStitch(wxCommandEvent& event)
1069 {
1070     m_batch->autostitch=event.IsChecked();
1071     wxConfigBase* config=wxConfigBase::Get();
1072     if(m_batch->autostitch)
1073     {
1074         config->Write(wxT("/BatchFrame/AutoStitchCheck"), 1l);
1075     }
1076     else
1077     {
1078         config->Write(wxT("/BatchFrame/AutoStitchCheck"), 0l);
1079     }
1080     config->Flush();
1081 };
1082 
OnCheckSaveLog(wxCommandEvent & event)1083 void BatchFrame::OnCheckSaveLog(wxCommandEvent& event)
1084 {
1085     m_batch->saveLog=event.IsChecked();
1086     wxConfigBase* config=wxConfigBase::Get();
1087     if(m_batch->saveLog)
1088     {
1089         config->Write(wxT("/BatchFrame/SaveLog"), 1l);
1090     }
1091     else
1092     {
1093         config->Write(wxT("/BatchFrame/SaveLog"), 0l);
1094     }
1095     config->Flush();
1096 };
1097 
OnClose(wxCloseEvent & event)1098 void BatchFrame::OnClose(wxCloseEvent& event)
1099 {
1100     // check size of batch queue
1101     if (m_batch->GetProjectCount() > 500)
1102     {
1103         wxMessageDialog message(this, _("The batch queue contains many items.\nThis can have negative effects on performance.\nShould the batch queue be cleared now?"),
1104 #ifdef __WXMSW__
1105             _("PTBatcherGUI"),
1106 #else
1107             wxT(""),
1108 #endif
1109             wxYES_NO | wxICON_INFORMATION);
1110         message.SetYesNoLabels(_("Clear batch queue now"), _("Keep batch queue"));
1111         if (message.ShowModal() == wxID_YES)
1112         {
1113             m_batch->ClearBatch();
1114             m_batch->SaveTemp();
1115         };
1116     };
1117     //save windows position
1118     wxConfigBase* config=wxConfigBase::Get();
1119     if(IsMaximized())
1120     {
1121         config->Write(wxT("/BatchFrame/Max"), 1l);
1122         config->Write(wxT("/BatchFrame/Minimized"), 0l);
1123     }
1124     else
1125     {
1126         config->Write(wxT("/BatchFrame/Max"), 0l);
1127         if(m_tray!=NULL && !IsShown())
1128         {
1129             config->Write(wxT("/BatchFrame/Minimized"), 1l);
1130         }
1131         else
1132         {
1133             config->Write(wxT("/BatchFrame/Minimized"), 0l);
1134             config->Write(wxT("/BatchFrame/Width"), GetSize().GetWidth());
1135             config->Write(wxT("/BatchFrame/Height"), GetSize().GetHeight());
1136         };
1137     }
1138     config->Flush();
1139     if(m_tray!=NULL)
1140     {
1141         delete m_tray;
1142         m_tray = NULL;
1143     }
1144     delete m_updateProjectsTimer;
1145     this->Destroy();
1146 }
1147 
PropagateDefaults()1148 void BatchFrame::PropagateDefaults()
1149 {
1150     m_batch->atEnd = GetEndTask();
1151     m_batch->overwrite=GetCheckOverwrite();
1152     m_batch->verbose=GetCheckVerbose();
1153     m_batch->autoremove=GetCheckAutoRemove();
1154     m_batch->autostitch=GetCheckAutoStitch();
1155 }
1156 
RunBatch()1157 void BatchFrame::RunBatch()
1158 {
1159     if(!IsRunning())
1160     {
1161         SetStatusInformation(_("Starting batch"));
1162         if (m_tray)
1163         {
1164             m_tray->SetIcon(m_iconRunning, _("Processing Hugin's batch queue"));
1165         };
1166     }
1167     m_batch->RunBatch();
1168 }
1169 
SetLocaleAndXRC(wxLocale * locale,wxString xrc)1170 void BatchFrame::SetLocaleAndXRC(wxLocale* locale, wxString xrc)
1171 {
1172     m_locale = locale;
1173     m_xrcPrefix = xrc;
1174 }
1175 
SwapProject(int index,bool down)1176 void BatchFrame::SwapProject(int index, bool down)
1177 {
1178     if(index>=0 && index<(projListBox->GetItemCount()-1))
1179     {
1180         projListBox->SwapProject(index);
1181         m_batch->SwapProject(index);
1182         if(down)
1183         {
1184             projListBox->Deselect(index);
1185             projListBox->Select(index + 1);
1186         }
1187         else
1188         {
1189             projListBox->Select(index);
1190             projListBox->Deselect(index + 1);
1191         };
1192     }
1193 }
1194 
1195 
OnProcessTerminate(wxProcessEvent & event)1196 void BatchFrame::OnProcessTerminate(wxProcessEvent& event)
1197 {
1198     if(m_batch->GetRunningCount()==1)
1199     {
1200         GetToolBar()->ToggleTool(XRCID("tool_pause"),false);
1201         if (m_tray)
1202         {
1203             m_tray->SetIcon(m_iconNormal, _("Hugin's Batch processor"));
1204         };
1205     }
1206     event.Skip();
1207 }
1208 
RestoreSize()1209 void BatchFrame::RestoreSize()
1210 {
1211     //get saved size
1212     wxConfigBase* config=wxConfigBase::Get();
1213     int width = config->Read(wxT("/BatchFrame/Width"), -1l);
1214     int height = config->Read(wxT("/BatchFrame/Height"), -1l);
1215     int max = config->Read(wxT("/BatchFrame/Max"), -1l);
1216     int min = config->Read(wxT("/BatchFrame/Minimized"), -1l);
1217     if((width != -1) && (height != -1))
1218     {
1219         SetSize(width,height);
1220     }
1221     else
1222     {
1223         SetSize(600,400);
1224     }
1225 
1226     if(max==1)
1227     {
1228         Maximize();
1229     };
1230     m_startedMinimized=(m_tray!=NULL) && (min==1);
1231 }
1232 
OnBatchFailed(wxCommandEvent & event)1233 void BatchFrame::OnBatchFailed(wxCommandEvent& event)
1234 {
1235     if(m_batch->GetFailedProjectsCount()>0)
1236     {
1237         if (m_tray)
1238         {
1239             m_tray->SetIcon(m_iconNormal, _("Hugin's Batch processor"));
1240         };
1241         FailedProjectsDialog failedProjects_dlg(this, m_batch, m_xrcPrefix);
1242         failedProjects_dlg.ShowModal();
1243     };
1244 };
1245 
OnBatchInformation(wxCommandEvent & e)1246 void BatchFrame::OnBatchInformation(wxCommandEvent& e)
1247 {
1248     SetStatusInformation(e.GetString());
1249     if (m_tray && e.GetInt() == 1)
1250     {
1251         // batch finished, reset icon in task bar
1252         m_tray->SetIcon(m_iconNormal, _("Hugin's Batch processor"));
1253     };
1254 };
1255 
SetStatusInformation(wxString status)1256 void BatchFrame::SetStatusInformation(wxString status)
1257 {
1258     SetStatusText(status);
1259     if(m_tray!=NULL)
1260     {
1261 #if defined __WXMSW__ && wxUSE_TASKBARICON_BALLOONS
1262         m_tray->ShowBalloon(_("PTBatcherGUI"),status,5000,wxICON_INFORMATION);
1263 #else
1264 #ifndef __WXMAC__
1265         // the balloon does not work correctly on MacOS; it gets the focus
1266         // and can not be closed
1267         if(!IsShown())
1268         {
1269             TaskBarBalloon* balloon=new TaskBarBalloon(_("PTBatcherGUI"),status);
1270             balloon->showBalloon(5000);
1271         };
1272 #endif
1273 #endif
1274     };
1275 };
1276 
OnProgress(wxCommandEvent & e)1277 void BatchFrame::OnProgress(wxCommandEvent& e)
1278 {
1279     m_progStatusBar->SetProgress(e.GetInt());
1280     UpdateTaskBarProgressBar();
1281 };
1282 
UpdateTaskBarProgressBar()1283 void BatchFrame::UpdateTaskBarProgressBar()
1284 {
1285 #if defined __WXMSW__ && wxCHECK_VERSION(3,1,0)
1286     // provide also a feedback in task bar if available
1287     if (IsShown())
1288     {
1289         wxTaskBarButton* taskBarButton = MSWGetTaskBarButton();
1290         if (taskBarButton != NULL)
1291         {
1292             if (m_progStatusBar->GetProgress() < 0)
1293             {
1294                 taskBarButton->SetProgressValue(wxTASKBAR_BUTTON_NO_PROGRESS);
1295             }
1296             else
1297             {
1298                 taskBarButton->SetProgressRange(100);
1299                 taskBarButton->SetProgressState(m_batch->IsPaused() ? wxTASKBAR_BUTTON_PAUSED : wxTASKBAR_BUTTON_NORMAL);
1300                 taskBarButton->SetProgressValue(m_progStatusBar->GetProgress());
1301             };
1302         };
1303     };
1304 #endif
1305 };
1306 
OnMinimize(wxIconizeEvent & e)1307 void BatchFrame::OnMinimize(wxIconizeEvent& e)
1308 {
1309     //hide/show window in taskbar when minimizing
1310     if(m_tray!=NULL)
1311     {
1312         Show(!e.IsIconized());
1313         //switch off verbose output if PTBatcherGUI is in tray/taskbar
1314         if(e.IsIconized())
1315         {
1316             m_batch->verbose=false;
1317         }
1318         else
1319         {
1320             m_batch->verbose=XRCCTRL(*this,"cb_verbose",wxCheckBox)->IsChecked();
1321             UpdateTaskBarProgressBar();
1322         };
1323         m_batch->ShowOutput(m_batch->verbose);
1324     }
1325     else //don't hide window if no tray icon
1326     {
1327         if (!e.IsIconized())
1328         {
1329             // window is restored, update progress indicators
1330             UpdateTaskBarProgressBar();
1331         };
1332         e.Skip();
1333     };
1334 };
1335 
UpdateBatchVerboseStatus()1336 void BatchFrame::UpdateBatchVerboseStatus()
1337 {
1338     m_batch->verbose=XRCCTRL(*this,"cb_verbose",wxCheckBox)->IsChecked();
1339     m_batch->ShowOutput(m_batch->verbose);
1340 };
1341 
OnRefillListBox(wxCommandEvent & event)1342 void BatchFrame::OnRefillListBox(wxCommandEvent& event)
1343 {
1344     const HuginBase::UIntSet selected = projListBox->GetSelectedProjects();
1345     std::set<long> selectedID;
1346     for (auto index : selected)
1347     {
1348         selectedID.insert(m_batch->GetProject(index)->id);
1349     };
1350     projListBox->DeleteAllItems();
1351     projListBox->Fill(m_batch);
1352     for(auto id:selectedID)
1353     {
1354         int index=projListBox->GetIndex(id);
1355         if(index!=-1)
1356         {
1357             projListBox->Select(index);
1358         };
1359     };
1360 };
1361 
OnMinimizeTrayMenu(wxCommandEvent & event)1362 void BatchFrame::OnMinimizeTrayMenu(wxCommandEvent& event)
1363 {
1364     UpdateTrayIcon(event.IsChecked());
1365     wxConfigBase* config=wxConfigBase::Get();
1366     config->Write(wxT("/BatchFrame/minimizeTray"), event.IsChecked());
1367     config->Flush();
1368 }
1369 
UpdateTrayIcon(const bool createTrayIcon)1370 void BatchFrame::UpdateTrayIcon(const bool createTrayIcon)
1371 {
1372     if (createTrayIcon)
1373     {
1374         // create tray icon only if it not exists
1375         if (m_tray)
1376         {
1377             delete m_tray;
1378             m_tray = NULL;
1379         }
1380         m_tray = new BatchTaskBarIcon();
1381         if (m_batch->IsRunning())
1382         {
1383             m_tray->SetIcon(m_iconRunning, _("Processing Hugin's batch queue"));
1384         }
1385         else
1386         {
1387             if (m_batch->IsPaused())
1388             {
1389                 m_tray->SetIcon(m_iconPaused, _("Pausing processing Hugin's batch queue"));
1390             }
1391             else
1392             {
1393                 m_tray->SetIcon(m_iconNormal, _("Hugin's Batch processor"));
1394             }
1395         }
1396     }
1397     else
1398     {
1399         // destroy tray icon
1400         if (m_tray)
1401         {
1402             delete m_tray;
1403             m_tray = NULL;
1404         }
1405     }
1406 }
1407