OSDN Git Service

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