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