OSDN Git Service

Unified SyncDlg and progressdlg log handle
[tortoisegit/TortoiseGitJp.git] / src / TortoiseProc / ProgressDlg.cpp
index b7e8514..f7ab402 100644 (file)
 IMPLEMENT_DYNAMIC(CProgressDlg, CResizableStandAloneDialog)\r
 \r
 CProgressDlg::CProgressDlg(CWnd* pParent /*=NULL*/)\r
-       : CResizableStandAloneDialog(CProgressDlg::IDD, pParent)\r
+       : CResizableStandAloneDialog(CProgressDlg::IDD, pParent), m_bShowCommand(true), m_bAutoCloseOnSuccess(false), m_bAbort(false), m_bDone(false)\r
 {\r
-\r
+       m_pThread = NULL;\r
+       m_bAltAbortPress=false;\r
+       m_bBufferAll=false;\r
 }\r
 \r
 CProgressDlg::~CProgressDlg()\r
@@ -35,6 +37,9 @@ void CProgressDlg::DoDataExchange(CDataExchange* pDX)
 \r
 \r
 BEGIN_MESSAGE_MAP(CProgressDlg, CResizableStandAloneDialog)\r
+       ON_MESSAGE(MSG_PROGRESSDLG_UPDATE_UI, OnProgressUpdateUI)\r
+       ON_BN_CLICKED(IDOK, &CProgressDlg::OnBnClickedOk)\r
+       ON_BN_CLICKED(IDC_PROGRESS_BUTTON1,&CProgressDlg::OnBnClickedButton1)\r
 END_MESSAGE_MAP()\r
 \r
 BOOL CProgressDlg::OnInitDialog()\r
@@ -47,10 +52,23 @@ BOOL CProgressDlg::OnInitDialog()
 \r
        AddAnchor(IDOK,BOTTOM_RIGHT);\r
        AddAnchor(IDCANCEL,BOTTOM_RIGHT);\r
+       AddAnchor(IDC_PROGRESS_BUTTON1,BOTTOM_RIGHT);\r
 \r
+       this->GetDlgItem(IDC_PROGRESS_BUTTON1)->ShowWindow(SW_HIDE);\r
        m_Animate.Open(IDR_DOWNLOAD);\r
        \r
-       m_Log.SetWindowTextW(this->m_GitCmd+_T("\r\n\r\n"));\r
+       CString InitialText;\r
+       if ( !m_PreText.IsEmpty() )\r
+       {\r
+               InitialText = m_PreText + _T("\r\n");\r
+       }\r
+#if 0\r
+       if (m_bShowCommand && (!m_GitCmd.IsEmpty() ))\r
+       {\r
+               InitialText += m_GitCmd+_T("\r\n\r\n");\r
+       }\r
+#endif\r
+       m_Log.SetWindowTextW(InitialText);\r
        m_CurrentWork.SetWindowTextW(_T(""));\r
 \r
        m_pThread = AfxBeginThread(ProgressThreadEntry, this, THREAD_PRIORITY_NORMAL,0,CREATE_SUSPENDED);\r
@@ -63,6 +81,9 @@ BOOL CProgressDlg::OnInitDialog()
                m_pThread->m_bAutoDelete = FALSE;\r
                m_pThread->ResumeThread();\r
        }\r
+\r
+       if(!m_Title.IsEmpty())\r
+               this->SetWindowText(m_Title);\r
        return TRUE;\r
 }\r
 \r
@@ -71,52 +92,161 @@ UINT CProgressDlg::ProgressThreadEntry(LPVOID pVoid)
        return ((CProgressDlg*)pVoid)->ProgressThread();\r
 }\r
 \r
-UINT CProgressDlg::ProgressThread()\r
+//static function, Share with SyncDialog\r
+UINT CProgressDlg::RunCmdList(CWnd *pWnd,std::vector<CString> &cmdlist,bool bShowCommand,CString *pfilename,bool *bAbort,std::vector<TCHAR>*pdata)\r
 {\r
+       UINT ret=0;\r
+\r
        PROCESS_INFORMATION pi;\r
        HANDLE hRead;\r
 \r
-       m_Animate.Play(0,-1,-1);\r
+       pWnd->PostMessage(MSG_PROGRESSDLG_UPDATE_UI,MSG_PROGRESSDLG_START,0);\r
+\r
+       if(pdata)\r
+               pdata->clear();\r
+                \r
+       for(int i=0;i<cmdlist.size();i++)\r
+       {\r
+               if(cmdlist[i].IsEmpty())\r
+                       continue;\r
+\r
+               if (bShowCommand)\r
+               {\r
+                       CString str;\r
+                       str+= cmdlist[i]+_T("\n\n");\r
+                       for(int j=0;j<str.GetLength();j++)\r
+                       {\r
+                               if(pdata)\r
+                                       pdata->push_back(str[j]);\r
+                               else\r
+                                       pWnd->PostMessage(MSG_PROGRESSDLG_UPDATE_UI,MSG_PROGRESSDLG_RUN,str[j]);\r
+                       }\r
+                       if(pdata)\r
+                               pWnd->PostMessage(MSG_PROGRESSDLG_UPDATE_UI,MSG_PROGRESSDLG_RUN,0);\r
+               }\r
+\r
+               g_Git.RunAsync(cmdlist[i],&pi, &hRead,pfilename);\r
+\r
+               DWORD readnumber;\r
+               char buffer[2];\r
+               CString output;\r
+               while(ReadFile(hRead,buffer,1,&readnumber,NULL))\r
+               {\r
+                       buffer[readnumber]=0;\r
+                       \r
+                       if(pdata)\r
+                       {\r
+                               pdata->push_back((TCHAR)buffer[0]);\r
+\r
+                               if(buffer[0] == '\r' || buffer[0] == '\n')\r
+                                       pWnd->PostMessage(MSG_PROGRESSDLG_UPDATE_UI,MSG_PROGRESSDLG_RUN,0);\r
+                       }else\r
+                               pWnd->PostMessage(MSG_PROGRESSDLG_UPDATE_UI,MSG_PROGRESSDLG_RUN,buffer[0]);\r
+               }\r
+       \r
+               CloseHandle(pi.hThread);\r
+\r
+               WaitForSingleObject(pi.hProcess, INFINITE);\r
+               \r
+               DWORD status=0;\r
+               if(!GetExitCodeProcess(pi.hProcess,&status) || *bAbort)\r
+               {\r
+                       CloseHandle(pi.hProcess);\r
+\r
+                       CloseHandle(hRead);\r
+\r
+                       pWnd->PostMessage(MSG_PROGRESSDLG_UPDATE_UI,MSG_PROGRESSDLG_FAILED,0);\r
+                       return GIT_ERROR_GET_EXIT_CODE;\r
+               }\r
+               ret |= status;\r
+       }\r
+\r
+       CloseHandle(pi.hProcess);\r
+\r
+       CloseHandle(hRead);\r
+\r
+       pWnd->PostMessage(MSG_PROGRESSDLG_UPDATE_UI,MSG_PROGRESSDLG_END,0);\r
+\r
+       return ret;\r
+\r
+}\r
+\r
+UINT CProgressDlg::ProgressThread()\r
+{\r
+       \r
+       m_GitCmdList.push_back(m_GitCmd);\r
 \r
        CString *pfilename;\r
+\r
        if(m_LogFile.IsEmpty())\r
                pfilename=NULL;\r
        else\r
-               pfilename=&m_LogFile;\r
+               pfilename=&m_LogFile;   \r
 \r
-       g_Git.RunAsync(this->m_GitCmd,&pi, &hRead,pfilename);\r
-       this->DialogEnableWindow(IDOK,FALSE);\r
+       m_GitStatus = RunCmdList(this,m_GitCmdList,m_bShowCommand,pfilename,&m_bAbort,&this->m_Databuf);;\r
+       return 0;\r
+}\r
 \r
-       DWORD readnumber;\r
-       char buffer[2];\r
-       CString output;\r
-       while(ReadFile(hRead,buffer,1,&readnumber,NULL))\r
+LRESULT CProgressDlg::OnProgressUpdateUI(WPARAM wParam,LPARAM lParam)\r
+{\r
+       if(wParam == MSG_PROGRESSDLG_START)\r
        {\r
-               buffer[readnumber]=0;\r
-               ParserCmdOutput((TCHAR)buffer[0]);\r
+               m_BufStart = 0 ;\r
+               m_Animate.Play(0,-1,-1);\r
+               this->DialogEnableWindow(IDOK,FALSE);\r
        }\r
+       if(wParam == MSG_PROGRESSDLG_END || wParam == MSG_PROGRESSDLG_FAILED)\r
+       {\r
+               if(m_bBufferAll)\r
+               {\r
+                       m_Databuf.push_back(0);\r
+                       InsertCRLF();\r
+                       m_Log.SetWindowText(&m_Databuf[0]);\r
+               }\r
+               m_BufStart=0;\r
+               this->m_Databuf.clear();\r
 \r
-       CloseHandle(pi.hThread);\r
+               m_bDone = true;\r
+               m_Animate.Stop();\r
+               m_Progress.SetPos(100);\r
+               this->DialogEnableWindow(IDOK,TRUE);\r
 \r
-       WaitForSingleObject(pi.hProcess, INFINITE);\r
-       m_GitStatus =0;\r
+               if(wParam == MSG_PROGRESSDLG_END && m_GitStatus == 0)\r
+               {\r
+                       if(m_bAutoCloseOnSuccess)\r
+                               EndDialog(IDOK);\r
+\r
+                       if(!m_changeAbortButtonOnSuccessTo.IsEmpty())\r
+                       {\r
+                               GetDlgItem(IDC_PROGRESS_BUTTON1)->SetWindowText(m_changeAbortButtonOnSuccessTo);\r
+                               GetDlgItem(IDC_PROGRESS_BUTTON1)->ShowWindow(SW_SHOW);\r
+                               GetDlgItem(IDCANCEL)->ShowWindow(SW_HIDE);\r
+                               //Set default button is "close" rather than "push"\r
+                               this->SendMessage(WM_NEXTDLGCTL, (WPARAM)GetDlgItem(IDOK)->m_hWnd, TRUE);\r
+                       }\r
+                       else\r
+                               DialogEnableWindow(IDCANCEL, FALSE);\r
+               }\r
+               else\r
+                       DialogEnableWindow(IDCANCEL, FALSE);\r
+       }\r
 \r
-       if(!GetExitCodeProcess(pi.hProcess,&m_GitStatus))\r
+       if(!m_bBufferAll)\r
        {\r
-               return GIT_ERROR_GET_EXIT_CODE;\r
+               if(lParam == 0)\r
+               {\r
+                       for(int i=this->m_BufStart;i<this->m_Databuf.size();i++)\r
+                       {\r
+                               ParserCmdOutput(this->m_Databuf[m_BufStart]);\r
+                               m_BufStart++;\r
+                       }\r
+               }else\r
+                       ParserCmdOutput((TCHAR)lParam);\r
        }\r
-\r
-       CloseHandle(pi.hProcess);\r
-\r
-       CloseHandle(hRead);\r
-\r
-       m_Progress.SetPos(100);\r
-       this->DialogEnableWindow(IDOK,TRUE);\r
-\r
-       m_Animate.Stop();\r
        return 0;\r
 }\r
 \r
+//static function, Share with SyncDialog\r
 int CProgressDlg::FindPercentage(CString &log)\r
 {\r
        int s1=log.Find(_T('%'));\r
@@ -134,6 +264,7 @@ int CProgressDlg::FindPercentage(CString &log)
        return _ttol(log.Mid(s2,s1-s2));\r
 }\r
 \r
+#if 0\r
 void CProgressDlg::ParserCmdOutput(TCHAR ch)\r
 {\r
        TRACE(_T("%c"),ch);\r
@@ -142,15 +273,28 @@ void CProgressDlg::ParserCmdOutput(TCHAR ch)
                TRACE(_T("End Char %s \r\n"),ch==_T('\r')?_T("lf"):_T(""));\r
                TRACE(_T("End Char %s \r\n"),ch==_T('\n')?_T("cr"):_T(""));\r
 \r
-               CString text;\r
-               m_Log.GetWindowTextW(text);\r
+               int lines=m_Log.GetLineCount();\r
+\r
                if(ch == _T('\r'))\r
+               {       \r
+                       int start=m_Log.LineIndex(lines-1);\r
+                       int length=m_Log.LineLength(lines-1);\r
+                       m_Log.SetSel( start,start+length);\r
+                       m_Log.ReplaceSel(m_LogText);\r
+\r
+               }else\r
                {\r
-                       RemoveLastLine(text);\r
+                       m_Log.SetSel(m_Log.GetWindowTextLength(),\r
+                                            m_Log.GetWindowTextLength());\r
+                       m_Log.ReplaceSel(CString(_T("\r\n"))+m_LogText);\r
                }\r
-               text+=_T("\r\n")+m_LogText;\r
-               m_Log.SetWindowTextW(text);\r
                \r
+               if( lines > 500 ) //limited log length\r
+               {\r
+                       int end=m_Log.LineIndex(1);\r
+                       m_Log.SetSel(0,end);\r
+                       m_Log.ReplaceSel(_T(""));\r
+               }\r
                m_Log.LineScroll(m_Log.GetLineCount());\r
 \r
                int s1=m_LogText.Find(_T(':'));\r
@@ -172,6 +316,64 @@ void CProgressDlg::ParserCmdOutput(TCHAR ch)
        }\r
 \r
 }\r
+#endif\r
+\r
+void CProgressDlg::ParserCmdOutput(TCHAR ch)\r
+{\r
+       ParserCmdOutput(this->m_Log,this->m_Progress,this->m_LogText,ch);\r
+}\r
+void CProgressDlg::ParserCmdOutput(CRichEditCtrl &log,CProgressCtrl &progressctrl,CString &oneline, TCHAR ch)\r
+{\r
+       //TRACE(_T("%c"),ch);\r
+       TRACE(_T("%c"),ch);\r
+       if( ch == _T('\r') || ch == _T('\n'))\r
+       {\r
+               TRACE(_T("End Char %s \r\n"),ch==_T('\r')?_T("lf"):_T(""));\r
+               TRACE(_T("End Char %s \r\n"),ch==_T('\n')?_T("cr"):_T(""));\r
+\r
+               int lines=log.GetLineCount();\r
+\r
+               if(ch == _T('\r'))\r
+               {       \r
+                       int start=log.LineIndex(lines-1);\r
+                       int length=log.LineLength(lines-1);\r
+                       log.SetSel( start,start+length);\r
+                       log.ReplaceSel(oneline);\r
+\r
+               }else\r
+               {\r
+                       log.SetSel(log.GetWindowTextLength(),\r
+                                            log.GetWindowTextLength());\r
+                       log.ReplaceSel(CString(_T("\r\n"))+oneline);\r
+               }\r
+               \r
+               if( lines > 500 ) //limited log length\r
+               {\r
+                       int end=log.LineIndex(1);\r
+                       log.SetSel(0,end);\r
+                       log.ReplaceSel(_T(""));\r
+               }\r
+               log.LineScroll(log.GetLineCount());\r
+\r
+               int s1=oneline.Find(_T(':'));\r
+               int s2=oneline.Find(_T('%'));\r
+               if(s1>0 && s2>0)\r
+               {\r
+                       //this->m_CurrentWork.SetWindowTextW(m_LogText.Left(s1));\r
+                       int pos=FindPercentage(oneline);\r
+                       TRACE(_T("Pos %d\r\n"),pos);\r
+                       if(pos>0)\r
+                               progressctrl.SetPos(pos);\r
+               }\r
+\r
+               oneline=_T("");\r
+\r
+       }else\r
+       {\r
+               oneline+=ch;\r
+       }\r
+\r
+}\r
 void CProgressDlg::RemoveLastLine(CString &str)\r
 {\r
        int start;\r
@@ -181,3 +383,62 @@ void CProgressDlg::RemoveLastLine(CString &str)
        return;\r
 }\r
 // CProgressDlg message handlers\r
+\r
+void CProgressDlg::OnBnClickedOk()\r
+{\r
+       // TODO: Add your control notification handler code here\r
+       m_Log.GetWindowText(this->m_LogText);\r
+       OnOK();\r
+}\r
+\r
+void CProgressDlg::OnBnClickedButton1()\r
+{\r
+       this->EndDialog(IDC_PROGRESS_BUTTON1);\r
+       \r
+}\r
+void CProgressDlg::OnCancel()\r
+{\r
+       m_bAbort = true;\r
+       if(m_bDone)\r
+       {\r
+               CResizableStandAloneDialog::OnCancel();\r
+               return;\r
+       }\r
+\r
+       if( g_Git.m_CurrentGitPi.hProcess )\r
+       {\r
+               if(::GenerateConsoleCtrlEvent(CTRL_C_EVENT,0))\r
+               {\r
+                       ::WaitForSingleObject(g_Git.m_CurrentGitPi.hProcess ,10000);\r
+               }else\r
+               {\r
+                       int error=::GetLastError();\r
+               }\r
+\r
+               HANDLE  hProcessHandle = ::OpenProcess( PROCESS_TERMINATE, FALSE,g_Git.m_CurrentGitPi.dwProcessId);\r
+               if( hProcessHandle )\r
+                       if(!::TerminateProcess(hProcessHandle,-1) )\r
+                       {\r
+                               int error =::GetLastError();\r
+                       }\r
+       }\r
+       \r
+       ::WaitForSingleObject(g_Git.m_CurrentGitPi.hProcess ,10000);\r
+       CResizableStandAloneDialog::OnCancel();\r
+\r
+}\r
+\r
+void CProgressDlg::InsertCRLF()\r
+{\r
+       for(int i=0;i<m_Databuf.size();i++)\r
+       {\r
+               if(m_Databuf[i]==_T('\n'))\r
+               {\r
+                       if(i==0 || m_Databuf[i-1]!= _T('\r'))\r
+                       {\r
+                               m_Databuf.insert(m_Databuf.begin()+i,_T('\r'));\r
+                               i++;\r
+                       }\r
+               }\r
+       }\r
+}
\ No newline at end of file