1 // ProgressDlg.cpp : implementation file
\r
5 #include "TortoiseProc.h"
\r
6 #include "ProgressDlg.h"
\r
9 // CProgressDlg dialog
\r
11 IMPLEMENT_DYNAMIC(CProgressDlg, CResizableStandAloneDialog)
\r
13 CProgressDlg::CProgressDlg(CWnd* pParent /*=NULL*/)
\r
14 : CResizableStandAloneDialog(CProgressDlg::IDD, pParent), m_bShowCommand(true), m_bAutoCloseOnSuccess(false), m_bAbort(false), m_bDone(false)
\r
17 m_bAltAbortPress=false;
\r
21 CProgressDlg::~CProgressDlg()
\r
23 if(m_pThread != NULL)
\r
29 void CProgressDlg::DoDataExchange(CDataExchange* pDX)
\r
31 CDialog::DoDataExchange(pDX);
\r
32 DDX_Control(pDX, IDC_CURRENT, this->m_CurrentWork);
\r
33 DDX_Control(pDX, IDC_TITLE_ANIMATE, this->m_Animate);
\r
34 DDX_Control(pDX, IDC_RUN_PROGRESS, this->m_Progress);
\r
35 DDX_Control(pDX, IDC_LOG, this->m_Log);
\r
39 BEGIN_MESSAGE_MAP(CProgressDlg, CResizableStandAloneDialog)
\r
40 ON_MESSAGE(MSG_PROGRESSDLG_UPDATE_UI, OnProgressUpdateUI)
\r
41 ON_BN_CLICKED(IDOK, &CProgressDlg::OnBnClickedOk)
\r
42 ON_BN_CLICKED(IDC_PROGRESS_BUTTON1,&CProgressDlg::OnBnClickedButton1)
\r
45 BOOL CProgressDlg::OnInitDialog()
\r
47 CResizableStandAloneDialog::OnInitDialog();
\r
49 AddAnchor(IDC_TITLE_ANIMATE, TOP_LEFT, TOP_RIGHT);
\r
50 AddAnchor(IDC_RUN_PROGRESS, TOP_LEFT,TOP_RIGHT);
\r
51 AddAnchor(IDC_LOG, TOP_LEFT,BOTTOM_RIGHT);
\r
53 AddAnchor(IDOK,BOTTOM_RIGHT);
\r
54 AddAnchor(IDCANCEL,BOTTOM_RIGHT);
\r
55 AddAnchor(IDC_PROGRESS_BUTTON1,BOTTOM_RIGHT);
\r
57 this->GetDlgItem(IDC_PROGRESS_BUTTON1)->ShowWindow(SW_HIDE);
\r
58 m_Animate.Open(IDR_DOWNLOAD);
\r
60 CString InitialText;
\r
61 if ( !m_PreText.IsEmpty() )
\r
63 InitialText = m_PreText + _T("\r\n");
\r
66 if (m_bShowCommand && (!m_GitCmd.IsEmpty() ))
\r
68 InitialText += m_GitCmd+_T("\r\n\r\n");
\r
71 m_Log.SetWindowTextW(InitialText);
\r
72 m_CurrentWork.SetWindowTextW(_T(""));
\r
74 m_pThread = AfxBeginThread(ProgressThreadEntry, this, THREAD_PRIORITY_NORMAL,0,CREATE_SUSPENDED);
\r
75 if (m_pThread==NULL)
\r
77 // ReportError(CString(MAKEINTRESOURCE(IDS_ERR_THREADSTARTFAILED)));
\r
81 m_pThread->m_bAutoDelete = FALSE;
\r
82 m_pThread->ResumeThread();
\r
85 if(!m_Title.IsEmpty())
\r
86 this->SetWindowText(m_Title);
\r
90 UINT CProgressDlg::ProgressThreadEntry(LPVOID pVoid)
\r
92 return ((CProgressDlg*)pVoid)->ProgressThread();
\r
95 //static function, Share with SyncDialog
\r
96 UINT CProgressDlg::RunCmdList(CWnd *pWnd,std::vector<CString> &cmdlist,bool bShowCommand,CString *pfilename,bool *bAbort,std::vector<TCHAR>*pdata)
\r
100 PROCESS_INFORMATION pi;
\r
103 pWnd->PostMessage(MSG_PROGRESSDLG_UPDATE_UI,MSG_PROGRESSDLG_START,0);
\r
108 for(int i=0;i<cmdlist.size();i++)
\r
110 if(cmdlist[i].IsEmpty())
\r
116 str+= cmdlist[i]+_T("\n\n");
\r
117 for(int j=0;j<str.GetLength();j++)
\r
120 pdata->push_back(str[j]);
\r
122 pWnd->PostMessage(MSG_PROGRESSDLG_UPDATE_UI,MSG_PROGRESSDLG_RUN,str[j]);
\r
125 pWnd->PostMessage(MSG_PROGRESSDLG_UPDATE_UI,MSG_PROGRESSDLG_RUN,0);
\r
128 g_Git.RunAsync(cmdlist[i],&pi, &hRead,pfilename);
\r
133 while(ReadFile(hRead,buffer,1,&readnumber,NULL))
\r
135 buffer[readnumber]=0;
\r
139 pdata->push_back((TCHAR)buffer[0]);
\r
141 if(buffer[0] == '\r' || buffer[0] == '\n')
\r
142 pWnd->PostMessage(MSG_PROGRESSDLG_UPDATE_UI,MSG_PROGRESSDLG_RUN,0);
\r
144 pWnd->PostMessage(MSG_PROGRESSDLG_UPDATE_UI,MSG_PROGRESSDLG_RUN,buffer[0]);
\r
147 CloseHandle(pi.hThread);
\r
149 WaitForSingleObject(pi.hProcess, INFINITE);
\r
152 if(!GetExitCodeProcess(pi.hProcess,&status) || *bAbort)
\r
154 CloseHandle(pi.hProcess);
\r
156 CloseHandle(hRead);
\r
158 pWnd->PostMessage(MSG_PROGRESSDLG_UPDATE_UI,MSG_PROGRESSDLG_FAILED,0);
\r
159 return GIT_ERROR_GET_EXIT_CODE;
\r
164 CloseHandle(pi.hProcess);
\r
166 CloseHandle(hRead);
\r
168 pWnd->PostMessage(MSG_PROGRESSDLG_UPDATE_UI,MSG_PROGRESSDLG_END,0);
\r
174 UINT CProgressDlg::ProgressThread()
\r
177 m_GitCmdList.push_back(m_GitCmd);
\r
179 CString *pfilename;
\r
181 if(m_LogFile.IsEmpty())
\r
184 pfilename=&m_LogFile;
\r
186 m_GitStatus = RunCmdList(this,m_GitCmdList,m_bShowCommand,pfilename,&m_bAbort,&this->m_Databuf);;
\r
190 LRESULT CProgressDlg::OnProgressUpdateUI(WPARAM wParam,LPARAM lParam)
\r
192 if(wParam == MSG_PROGRESSDLG_START)
\r
195 m_Animate.Play(0,-1,-1);
\r
196 this->DialogEnableWindow(IDOK,FALSE);
\r
198 if(wParam == MSG_PROGRESSDLG_END || wParam == MSG_PROGRESSDLG_FAILED)
\r
202 m_Databuf.push_back(0);
\r
204 m_Log.SetWindowText(&m_Databuf[0]);
\r
207 this->m_Databuf.clear();
\r
211 m_Progress.SetPos(100);
\r
212 this->DialogEnableWindow(IDOK,TRUE);
\r
215 err.Format(_T("\r\nFailed 0x%x(git return wrong reture code at sometime )\r\n"),m_GitStatus);
\r
216 if(this->m_GitStatus)
\r
217 InsertColorText(this->m_Log,err,RGB(255,0,0));
\r
219 InsertColorText(this->m_Log,_T("\r\nSuccess\r\n"),RGB(0,0,255));
\r
221 if(wParam == MSG_PROGRESSDLG_END && m_GitStatus == 0)
\r
223 if(m_bAutoCloseOnSuccess)
\r
226 if(!m_changeAbortButtonOnSuccessTo.IsEmpty())
\r
228 GetDlgItem(IDC_PROGRESS_BUTTON1)->SetWindowText(m_changeAbortButtonOnSuccessTo);
\r
229 GetDlgItem(IDC_PROGRESS_BUTTON1)->ShowWindow(SW_SHOW);
\r
230 GetDlgItem(IDCANCEL)->ShowWindow(SW_HIDE);
\r
231 //Set default button is "close" rather than "push"
\r
232 this->SendMessage(WM_NEXTDLGCTL, (WPARAM)GetDlgItem(IDOK)->m_hWnd, TRUE);
\r
235 DialogEnableWindow(IDCANCEL, FALSE);
\r
238 DialogEnableWindow(IDCANCEL, FALSE);
\r
245 for(int i=this->m_BufStart;i<this->m_Databuf.size();i++)
\r
247 ParserCmdOutput(this->m_Databuf[m_BufStart]);
\r
251 ParserCmdOutput((TCHAR)lParam);
\r
256 //static function, Share with SyncDialog
\r
257 int CProgressDlg::FindPercentage(CString &log)
\r
259 int s1=log.Find(_T('%'));
\r
264 for(int i=s1-1;i>=0;i--)
\r
266 if(log[i]>=_T('0') && log[i]<=_T('9'))
\r
271 return _ttol(log.Mid(s2,s1-s2));
\r
275 void CProgressDlg::ParserCmdOutput(TCHAR ch)
\r
277 TRACE(_T("%c"),ch);
\r
278 if( ch == _T('\r') || ch == _T('\n'))
\r
280 TRACE(_T("End Char %s \r\n"),ch==_T('\r')?_T("lf"):_T(""));
\r
281 TRACE(_T("End Char %s \r\n"),ch==_T('\n')?_T("cr"):_T(""));
\r
283 int lines=m_Log.GetLineCount();
\r
287 int start=m_Log.LineIndex(lines-1);
\r
288 int length=m_Log.LineLength(lines-1);
\r
289 m_Log.SetSel( start,start+length);
\r
290 m_Log.ReplaceSel(m_LogText);
\r
294 m_Log.SetSel(m_Log.GetWindowTextLength(),
\r
295 m_Log.GetWindowTextLength());
\r
296 m_Log.ReplaceSel(CString(_T("\r\n"))+m_LogText);
\r
299 if( lines > 500 ) //limited log length
\r
301 int end=m_Log.LineIndex(1);
\r
302 m_Log.SetSel(0,end);
\r
303 m_Log.ReplaceSel(_T(""));
\r
305 m_Log.LineScroll(m_Log.GetLineCount());
\r
307 int s1=m_LogText.Find(_T(':'));
\r
308 int s2=m_LogText.Find(_T('%'));
\r
311 this->m_CurrentWork.SetWindowTextW(m_LogText.Left(s1));
\r
312 int pos=FindPercentage(m_LogText);
\r
313 TRACE(_T("Pos %d\r\n"),pos);
\r
315 this->m_Progress.SetPos(pos);
\r
328 void CProgressDlg::ParserCmdOutput(TCHAR ch)
\r
330 ParserCmdOutput(this->m_Log,this->m_Progress,this->m_LogText,ch,&this->m_CurrentWork);
\r
332 void CProgressDlg::ParserCmdOutput(CRichEditCtrl &log,CProgressCtrl &progressctrl,CString &oneline, TCHAR ch, CWnd *CurrentWork)
\r
334 //TRACE(_T("%c"),ch);
\r
335 TRACE(_T("%c"),ch);
\r
336 if( ch == _T('\r') || ch == _T('\n'))
\r
338 TRACE(_T("End Char %s \r\n"),ch==_T('\r')?_T("lf"):_T(""));
\r
339 TRACE(_T("End Char %s \r\n"),ch==_T('\n')?_T("cr"):_T(""));
\r
341 int lines=log.GetLineCount();
\r
345 int start=log.LineIndex(lines-1);
\r
346 int length=log.LineLength(lines-1);
\r
347 log.SetSel( start,start+length);
\r
348 log.ReplaceSel(oneline);
\r
352 log.SetSel(log.GetWindowTextLength(),
\r
353 log.GetWindowTextLength());
\r
354 log.ReplaceSel(CString(_T("\r\n"))+oneline);
\r
357 if( lines > 500 ) //limited log length
\r
359 int end=log.LineIndex(1);
\r
361 log.ReplaceSel(_T(""));
\r
363 log.LineScroll(log.GetLineCount());
\r
365 int s1=oneline.Find(_T(':'));
\r
366 int s2=oneline.Find(_T('%'));
\r
370 CurrentWork->SetWindowTextW(oneline.Left(s1));
\r
372 int pos=FindPercentage(oneline);
\r
373 TRACE(_T("Pos %d\r\n"),pos);
\r
375 progressctrl.SetPos(pos);
\r
386 void CProgressDlg::RemoveLastLine(CString &str)
\r
389 start=str.ReverseFind(_T('\n'));
\r
391 str=str.Left(start);
\r
394 // CProgressDlg message handlers
\r
396 void CProgressDlg::OnBnClickedOk()
\r
398 // TODO: Add your control notification handler code here
\r
399 m_Log.GetWindowText(this->m_LogText);
\r
403 void CProgressDlg::OnBnClickedButton1()
\r
405 this->EndDialog(IDC_PROGRESS_BUTTON1);
\r
408 void CProgressDlg::OnCancel()
\r
413 CResizableStandAloneDialog::OnCancel();
\r
417 if( g_Git.m_CurrentGitPi.hProcess )
\r
419 if(::GenerateConsoleCtrlEvent(CTRL_C_EVENT,0))
\r
421 ::WaitForSingleObject(g_Git.m_CurrentGitPi.hProcess ,10000);
\r
424 int error=::GetLastError();
\r
427 HANDLE hProcessHandle = ::OpenProcess( PROCESS_TERMINATE, FALSE,g_Git.m_CurrentGitPi.dwProcessId);
\r
428 if( hProcessHandle )
\r
429 if(!::TerminateProcess(hProcessHandle,-1) )
\r
431 int error =::GetLastError();
\r
435 ::WaitForSingleObject(g_Git.m_CurrentGitPi.hProcess ,10000);
\r
436 CResizableStandAloneDialog::OnCancel();
\r
440 void CProgressDlg::InsertCRLF()
\r
442 for(int i=0;i<m_Databuf.size();i++)
\r
444 if(m_Databuf[i]==_T('\n'))
\r
446 if(i==0 || m_Databuf[i-1]!= _T('\r'))
\r
448 m_Databuf.insert(m_Databuf.begin()+i,_T('\r'));
\r
455 void CProgressDlg::InsertColorText(CRichEditCtrl &edit,CString text,COLORREF rgb)
\r
458 edit.GetDefaultCharFormat(cf);
\r
460 cf.dwMask|=CFM_COLOR;
\r
461 cf.crTextColor=rgb;
\r
462 cf.dwEffects|=CFE_BOLD;
\r
463 cf.dwEffects &= ~CFE_AUTOCOLOR ;
\r
464 edit.SetSel(edit.GetTextLength()-1,edit.GetTextLength());
\r
465 edit.ReplaceSel(text);
\r
466 edit.SetSel(edit.LineIndex(edit.GetLineCount()-2),edit.GetTextLength());
\r
467 edit.SetSelectionCharFormat(cf);
\r
468 edit.SetSel(edit.GetTextLength(),edit.GetTextLength());
\r
469 edit.SetDefaultCharFormat(old);
\r
470 edit.LineScroll(edit.GetLineCount());
\r