OSDN Git Service

abe8c2cb697076e146c1d05f81a0b5ff9bd3c457
[tortoisegit/TortoiseGitJp.git] / src / TortoiseProc / ProgressDlg.cpp
1 // ProgressDlg.cpp : implementation file\r
2 //\r
3 \r
4 #include "stdafx.h"\r
5 #include "TortoiseProc.h"\r
6 #include "ProgressDlg.h"\r
7 #include "Git.h"\r
8 #include "atlconv.h"\r
9 // CProgressDlg dialog\r
10 \r
11 IMPLEMENT_DYNAMIC(CProgressDlg, CResizableStandAloneDialog)\r
12 \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
15 {\r
16         m_pThread = NULL;\r
17         m_bAltAbortPress=false;\r
18 }\r
19 \r
20 CProgressDlg::~CProgressDlg()\r
21 {\r
22         if(m_pThread != NULL)\r
23         {\r
24                 delete m_pThread;\r
25         }\r
26 }\r
27 \r
28 void CProgressDlg::DoDataExchange(CDataExchange* pDX)\r
29 {\r
30         CDialog::DoDataExchange(pDX);\r
31         DDX_Control(pDX, IDC_CURRENT, this->m_CurrentWork);\r
32         DDX_Control(pDX, IDC_TITLE_ANIMATE, this->m_Animate);\r
33         DDX_Control(pDX, IDC_RUN_PROGRESS, this->m_Progress);\r
34         DDX_Control(pDX, IDC_LOG, this->m_Log);\r
35 }\r
36 \r
37 \r
38 BEGIN_MESSAGE_MAP(CProgressDlg, CResizableStandAloneDialog)\r
39         ON_MESSAGE(MSG_PROGRESSDLG_UPDATE_UI, OnProgressUpdateUI)\r
40         ON_BN_CLICKED(IDOK, &CProgressDlg::OnBnClickedOk)\r
41         ON_BN_CLICKED(IDC_PROGRESS_BUTTON1,&CProgressDlg::OnBnClickedButton1)\r
42 END_MESSAGE_MAP()\r
43 \r
44 BOOL CProgressDlg::OnInitDialog()\r
45 {\r
46         CResizableStandAloneDialog::OnInitDialog();\r
47 \r
48         AddAnchor(IDC_TITLE_ANIMATE, TOP_LEFT, TOP_RIGHT);\r
49         AddAnchor(IDC_RUN_PROGRESS, TOP_LEFT,TOP_RIGHT);\r
50         AddAnchor(IDC_LOG, TOP_LEFT,BOTTOM_RIGHT);\r
51 \r
52         AddAnchor(IDOK,BOTTOM_RIGHT);\r
53         AddAnchor(IDCANCEL,BOTTOM_RIGHT);\r
54         AddAnchor(IDC_PROGRESS_BUTTON1,BOTTOM_RIGHT);\r
55 \r
56         this->GetDlgItem(IDC_PROGRESS_BUTTON1)->ShowWindow(SW_HIDE);\r
57         m_Animate.Open(IDR_DOWNLOAD);\r
58         \r
59         CString InitialText;\r
60         if ( !m_PreText.IsEmpty() )\r
61         {\r
62                 InitialText = m_PreText + _T("\r\n");\r
63         }\r
64         if (m_bShowCommand && (!m_GitCmd.IsEmpty() ))\r
65         {\r
66                 InitialText += m_GitCmd+_T("\r\n\r\n");\r
67         }\r
68         m_Log.SetWindowTextW(InitialText);\r
69         m_CurrentWork.SetWindowTextW(_T(""));\r
70 \r
71         m_pThread = AfxBeginThread(ProgressThreadEntry, this, THREAD_PRIORITY_NORMAL,0,CREATE_SUSPENDED);\r
72         if (m_pThread==NULL)\r
73         {\r
74 //              ReportError(CString(MAKEINTRESOURCE(IDS_ERR_THREADSTARTFAILED)));\r
75         }\r
76         else\r
77         {\r
78                 m_pThread->m_bAutoDelete = FALSE;\r
79                 m_pThread->ResumeThread();\r
80         }\r
81 \r
82         if(!m_Title.IsEmpty())\r
83                 this->SetWindowText(m_Title);\r
84         return TRUE;\r
85 }\r
86 \r
87 UINT CProgressDlg::ProgressThreadEntry(LPVOID pVoid)\r
88 {\r
89         return ((CProgressDlg*)pVoid)->ProgressThread();\r
90 }\r
91 \r
92 UINT CProgressDlg::ProgressThread()\r
93 {\r
94         PROCESS_INFORMATION pi;\r
95         HANDLE hRead;\r
96 \r
97         this->PostMessage(MSG_PROGRESSDLG_UPDATE_UI,MSG_PROGRESSDLG_START,0);\r
98 \r
99         CString *pfilename;\r
100         if(m_LogFile.IsEmpty())\r
101                 pfilename=NULL;\r
102         else\r
103                 pfilename=&m_LogFile;\r
104 \r
105         m_GitCmdList.push_back(m_GitCmd);\r
106 \r
107         m_GitStatus =0;\r
108 \r
109         for(int i=0;i<m_GitCmdList.size();i++)\r
110         {\r
111                 if(m_GitCmdList[i].IsEmpty())\r
112                         continue;\r
113 \r
114                 if (m_bShowCommand && m_GitCmdList[i]!= m_GitCmd)\r
115                 {\r
116                         CString str;\r
117                         str+= m_GitCmdList[i]+_T("\r\n\r\n");\r
118                         for(int j=0;j<str.GetLength();j++)\r
119                                 this->PostMessage(MSG_PROGRESSDLG_UPDATE_UI,MSG_PROGRESSDLG_RUN,str[j]);\r
120                 }\r
121 \r
122                 g_Git.RunAsync(this->m_GitCmdList[i],&pi, &hRead,pfilename);\r
123 \r
124                 DWORD readnumber;\r
125                 char buffer[2];\r
126                 CString output;\r
127                 while(ReadFile(hRead,buffer,1,&readnumber,NULL))\r
128                 {\r
129                         buffer[readnumber]=0;\r
130                         this->PostMessage(MSG_PROGRESSDLG_UPDATE_UI,MSG_PROGRESSDLG_RUN,(TCHAR)buffer[0]);\r
131                 }\r
132         \r
133                 CloseHandle(pi.hThread);\r
134 \r
135                 WaitForSingleObject(pi.hProcess, INFINITE);\r
136                 \r
137                 DWORD status=0;\r
138                 if(!GetExitCodeProcess(pi.hProcess,&status) || m_bAbort)\r
139                 {\r
140                         CloseHandle(pi.hProcess);\r
141 \r
142                         CloseHandle(hRead);\r
143 \r
144                         this->PostMessage(MSG_PROGRESSDLG_UPDATE_UI,MSG_PROGRESSDLG_FAILED,0);\r
145                         return GIT_ERROR_GET_EXIT_CODE;\r
146                 }\r
147                 m_GitStatus |= status;\r
148         }\r
149 \r
150         CloseHandle(pi.hProcess);\r
151 \r
152         CloseHandle(hRead);\r
153 \r
154         this->PostMessage(MSG_PROGRESSDLG_UPDATE_UI,MSG_PROGRESSDLG_END,0);\r
155 \r
156         return 0;\r
157 }\r
158 \r
159 LRESULT CProgressDlg::OnProgressUpdateUI(WPARAM wParam,LPARAM lParam)\r
160 {\r
161         if(wParam == MSG_PROGRESSDLG_START)\r
162         {\r
163                 m_Animate.Play(0,-1,-1);\r
164                 this->DialogEnableWindow(IDOK,FALSE);\r
165         }\r
166         if(wParam == MSG_PROGRESSDLG_END || wParam == MSG_PROGRESSDLG_FAILED)\r
167         {\r
168                 m_bDone = true;\r
169                 m_Animate.Stop();\r
170                 m_Progress.SetPos(100);\r
171                 this->DialogEnableWindow(IDOK,TRUE);\r
172 \r
173                 if(wParam == MSG_PROGRESSDLG_END && m_GitStatus == 0)\r
174                 {\r
175                         if(m_bAutoCloseOnSuccess)\r
176                                 EndDialog(IDOK);\r
177 \r
178                         if(!m_changeAbortButtonOnSuccessTo.IsEmpty())\r
179                         {\r
180                                 GetDlgItem(IDC_PROGRESS_BUTTON1)->SetWindowText(m_changeAbortButtonOnSuccessTo);\r
181                                 GetDlgItem(IDC_PROGRESS_BUTTON1)->ShowWindow(SW_SHOW);\r
182                                 GetDlgItem(IDCANCEL)->ShowWindow(SW_HIDE);\r
183                                 //Set default button is "close" rather than "push"\r
184                                 this->SendMessage(WM_NEXTDLGCTL, (WPARAM)GetDlgItem(IDOK)->m_hWnd, TRUE);\r
185                         }\r
186                         else\r
187                                 DialogEnableWindow(IDCANCEL, FALSE);\r
188                 }\r
189                 else\r
190                         DialogEnableWindow(IDCANCEL, FALSE);\r
191         }\r
192 \r
193         if(lParam != 0)\r
194                 ParserCmdOutput((TCHAR)lParam);\r
195 \r
196         return 0;\r
197 }\r
198 int CProgressDlg::FindPercentage(CString &log)\r
199 {\r
200         int s1=log.Find(_T('%'));\r
201         if(s1<0)\r
202                 return -1;\r
203 \r
204         int s2=s1-1;\r
205         for(int i=s1-1;i>=0;i--)\r
206         {\r
207                 if(log[i]>=_T('0') && log[i]<=_T('9'))\r
208                         s2=i;\r
209                 else\r
210                         break;\r
211         }\r
212         return _ttol(log.Mid(s2,s1-s2));\r
213 }\r
214 \r
215 void CProgressDlg::ParserCmdOutput(TCHAR ch)\r
216 {\r
217         TRACE(_T("%c"),ch);\r
218         if( ch == _T('\r') || ch == _T('\n'))\r
219         {\r
220                 TRACE(_T("End Char %s \r\n"),ch==_T('\r')?_T("lf"):_T(""));\r
221                 TRACE(_T("End Char %s \r\n"),ch==_T('\n')?_T("cr"):_T(""));\r
222 \r
223                 CString text;\r
224                 m_Log.GetWindowTextW(text);\r
225                 if(ch == _T('\r'))\r
226                 {\r
227                         RemoveLastLine(text);\r
228                 }\r
229                 text+=_T("\r\n")+m_LogText;\r
230                 m_Log.SetWindowTextW(text);\r
231                 \r
232                 m_Log.LineScroll(m_Log.GetLineCount());\r
233 \r
234                 int s1=m_LogText.Find(_T(':'));\r
235                 int s2=m_LogText.Find(_T('%'));\r
236                 if(s1>0 && s2>0)\r
237                 {\r
238                         this->m_CurrentWork.SetWindowTextW(m_LogText.Left(s1));\r
239                         int pos=FindPercentage(m_LogText);\r
240                         TRACE(_T("Pos %d\r\n"),pos);\r
241                         if(pos>0)\r
242                                 this->m_Progress.SetPos(pos);\r
243                 }\r
244 \r
245                 m_LogText=_T("");\r
246 \r
247         }else\r
248         {\r
249                 m_LogText+=ch;\r
250         }\r
251 \r
252 }\r
253 void CProgressDlg::RemoveLastLine(CString &str)\r
254 {\r
255         int start;\r
256         start=str.ReverseFind(_T('\n'));\r
257         if(start>0)\r
258                 str=str.Left(start);\r
259         return;\r
260 }\r
261 // CProgressDlg message handlers\r
262 \r
263 void CProgressDlg::OnBnClickedOk()\r
264 {\r
265         // TODO: Add your control notification handler code here\r
266         m_Log.GetWindowText(this->m_LogText);\r
267         OnOK();\r
268 }\r
269 \r
270 void CProgressDlg::OnBnClickedButton1()\r
271 {\r
272         this->EndDialog(IDC_PROGRESS_BUTTON1);\r
273         \r
274 }\r
275 void CProgressDlg::OnCancel()\r
276 {\r
277         if(m_bDone)\r
278         {\r
279                 CResizableStandAloneDialog::OnCancel();\r
280                 return;\r
281         }\r
282         \r
283         m_bAbort = true;\r
284 }\r