Added advanced taskbar grouping and highlighting in Win7
[TortoiseGit.git] / src / TortoiseProc / GitProgressDlg.cpp
blobcfc0fe255fb2eb2e533afd75dc89a40f97550e0f
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2008-2013 - TortoiseGit
4 // Copyright (C) 2003-2008 - TortoiseSVN
6 // This program is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU General Public License
8 // as published by the Free Software Foundation; either version 2
9 // of the License, or (at your option) any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software Foundation,
18 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 #include "stdafx.h"
21 #include "TortoiseProc.h"
22 #include "messagebox.h"
23 #include "GITProgressDlg.h"
24 #include "LogDlg.h"
25 #include "TGitPath.h"
26 #include "registry.h"
27 #include "GitStatus.h"
28 #include "AppUtils.h"
29 #include "PathUtils.h"
30 #include "StringUtils.h"
31 #include "TempFile.h"
32 #include "UnicodeUtils.h"
33 #include "SoundUtils.h"
34 #include "GitDiff.h"
35 #include "Hooks.h"
36 #include "DropFiles.h"
37 //#include "GitLogHelper.h"
38 #include "RegHistory.h"
39 //#include "ConflictResolveDlg.h"
40 #include "LogFile.h"
41 #include "ShellUpdater.h"
42 #include "IconMenu.h"
43 #include "BugTraqAssociations.h"
44 #include "patch.h"
45 #include "MassiveGitTask.h"
46 #include "SmartHandle.h"
49 IMPLEMENT_DYNAMIC(CGitProgressDlg, CResizableStandAloneDialog)
50 CGitProgressDlg::CGitProgressDlg(CWnd* pParent /*=NULL*/)
51 : CResizableStandAloneDialog(CGitProgressDlg::IDD, pParent)
53 #if 0
54 , m_Revision(_T("HEAD"))
55 //, m_RevisionEnd(0)
56 , m_bLockWarning(false)
57 , m_bLockExists(false)
58 , m_bThreadRunning(FALSE)
59 , m_nConflicts(0)
60 , m_bMergesAddsDeletesOccurred(FALSE)
61 , m_dwCloseOnEnd((DWORD)-1)
62 , m_bFinishedItemAdded(false)
63 , m_bLastVisible(false)
64 // , m_depth(svn_depth_unknown)
65 , m_itemCount(-1)
66 , m_itemCountTotal(-1)
67 , m_AlwaysConflicted(false)
68 , m_BugTraqProvider(NULL)
69 , sDryRun(MAKEINTRESOURCE(IDS_PROGRS_DRYRUN))
70 , sRecordOnly(MAKEINTRESOURCE(IDS_MERGE_RECORDONLY))
71 #endif
75 CGitProgressDlg::~CGitProgressDlg()
79 void CGitProgressDlg::DoDataExchange(CDataExchange* pDX)
81 CResizableStandAloneDialog::DoDataExchange(pDX);
82 DDX_Control(pDX, IDC_SVNPROGRESS, m_ProgList);
83 DDX_Control(pDX, IDC_TITLE_ANIMATE, m_Animate);
84 DDX_Control(pDX, IDC_PROGRESSBAR, m_ProgCtrl);
85 DDX_Control(pDX, IDC_INFOTEXT, m_InfoCtrl);
86 DDX_Control(pDX, IDC_PROGRESSLABEL, m_ProgLableCtrl);
89 BEGIN_MESSAGE_MAP(CGitProgressDlg, CResizableStandAloneDialog)
90 ON_BN_CLICKED(IDC_LOGBUTTON, OnBnClickedLogbutton)
91 ON_WM_CLOSE()
92 ON_WM_SETCURSOR()
93 ON_EN_SETFOCUS(IDC_INFOTEXT, &CGitProgressDlg::OnEnSetfocusInfotext)
94 ON_BN_CLICKED(IDC_NONINTERACTIVE, &CGitProgressDlg::OnBnClickedNoninteractive)
95 ON_WM_CTLCOLOR()
96 ON_MESSAGE(WM_PROG_CMD_FINISH, OnCmdEnd)
97 ON_MESSAGE(WM_PROG_CMD_START, OnCmdStart)
98 ON_REGISTERED_MESSAGE(WM_TASKBARBTNCREATED, OnTaskbarBtnCreated)
99 END_MESSAGE_MAP()
103 BOOL CGitProgressDlg::OnInitDialog()
105 __super::OnInitDialog();
107 // Let the TaskbarButtonCreated message through the UIPI filter. If we don't
108 // do this, Explorer would be unable to send that message to our window if we
109 // were running elevated. It's OK to make the call all the time, since if we're
110 // not elevated, this is a no-op.
111 CHANGEFILTERSTRUCT cfs = { sizeof(CHANGEFILTERSTRUCT) };
112 typedef BOOL STDAPICALLTYPE ChangeWindowMessageFilterExDFN(HWND hWnd, UINT message, DWORD action, PCHANGEFILTERSTRUCT pChangeFilterStruct);
113 CAutoLibrary hUser = AtlLoadSystemLibraryUsingFullPath(_T("user32.dll"));
114 if (hUser)
116 ChangeWindowMessageFilterExDFN *pfnChangeWindowMessageFilterEx = (ChangeWindowMessageFilterExDFN*)GetProcAddress(hUser, "ChangeWindowMessageFilterEx");
117 if (pfnChangeWindowMessageFilterEx)
119 pfnChangeWindowMessageFilterEx(m_hWnd, WM_TASKBARBTNCREATED, MSGFLT_ALLOW, &cfs);
122 m_ProgList.m_pTaskbarList.Release();
123 if (FAILED(m_ProgList.m_pTaskbarList.CoCreateInstance(CLSID_TaskbarList)))
124 m_ProgList.m_pTaskbarList = nullptr;
126 UpdateData(FALSE);
128 AddAnchor(IDC_SVNPROGRESS, TOP_LEFT, BOTTOM_RIGHT);
129 AddAnchor(IDC_TITLE_ANIMATE, TOP_LEFT, BOTTOM_RIGHT);
130 AddAnchor(IDC_PROGRESSLABEL, BOTTOM_LEFT, BOTTOM_CENTER);
131 AddAnchor(IDC_PROGRESSBAR, BOTTOM_CENTER, BOTTOM_RIGHT);
132 AddAnchor(IDC_INFOTEXT, BOTTOM_LEFT, BOTTOM_RIGHT);
133 AddAnchor(IDC_NONINTERACTIVE, BOTTOM_LEFT, BOTTOM_RIGHT);
134 AddAnchor(IDCANCEL, BOTTOM_RIGHT);
135 AddAnchor(IDOK, BOTTOM_RIGHT);
136 AddAnchor(IDC_LOGBUTTON, BOTTOM_RIGHT);
137 //SetPromptParentWindow(this->m_hWnd);
139 m_Animate.Open(IDR_DOWNLOAD);
140 m_ProgList.m_pAnimate = &m_Animate;
141 m_ProgList.m_pProgControl = &m_ProgCtrl;
142 m_ProgList.m_pProgressLabelCtrl = &m_ProgLableCtrl;
143 m_ProgList.m_pInfoCtrl = &m_InfoCtrl;
144 m_ProgList.m_pPostWnd = this;
145 m_ProgList.m_bSetTitle = true;
147 if (hWndExplorer)
148 CenterWindow(CWnd::FromHandle(hWndExplorer));
149 EnableSaveRestore(_T("GITProgressDlg"));
151 m_background_brush.CreateSolidBrush(GetSysColor(COLOR_WINDOW));
152 m_ProgList.Init();
154 return TRUE;
157 LRESULT CGitProgressDlg::OnTaskbarBtnCreated(WPARAM /*wParam*/, LPARAM /*lParam*/)
159 m_ProgList.m_pTaskbarList.Release();
160 m_ProgList.m_pTaskbarList.CoCreateInstance(CLSID_TaskbarList);
161 SetUUIDOverlayIcon(m_hWnd);
162 return 0;
165 void CGitProgressDlg::OnBnClickedLogbutton()
167 switch(m_ProgList.m_Command)
169 case CGitProgressList::GitProgress_Add:
170 case CGitProgressList::GitProgress_Resolve:
172 CString cmd = _T(" /command:commit");
173 cmd += _T(" /path:\"")+g_Git.m_CurrentDir+_T("\"");
175 CAppUtils::RunTortoiseGitProc(cmd);
176 this->EndDialog(IDOK);
177 break;
180 #if 0
181 if (m_targetPathList.GetCount() != 1)
182 return;
183 StringRevMap::iterator it = m_UpdateStartRevMap.begin();
184 svn_revnum_t rev = -1;
185 if (it != m_UpdateStartRevMap.end())
187 rev = it->second;
189 CLogDlg dlg;
190 dlg.SetParams(m_targetPathList[0], m_RevisionEnd, m_RevisionEnd, rev, 0, TRUE);
191 dlg.DoModal();
192 #endif
196 void CGitProgressDlg::OnClose()
198 DialogEnableWindow(IDCANCEL, TRUE);
199 __super::OnClose();
202 void CGitProgressDlg::OnOK()
204 if ((m_ProgList.IsCancelled())&&(!m_ProgList.IsRunning()))
206 // I have made this wait a sensible amount of time (10 seconds) for the thread to finish
207 // You must be careful in the thread that after posting the WM_COMMAND/IDOK message, you
208 // don't do any more operations on the window which might require message passing
209 // If you try to send windows messages once we're waiting here, then the thread can't finished
210 // because the Window's message loop is blocked at this wait
211 WaitForSingleObject(m_ProgList.m_pThread->m_hThread, 10000);
212 __super::OnOK();
214 m_ProgList.Cancel();
217 void CGitProgressDlg::OnCancel()
219 if ((m_ProgList.IsCancelled())&&(!m_ProgList.IsRunning()))
220 __super::OnCancel();
221 m_ProgList.Cancel();
225 BOOL CGitProgressDlg::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
227 if (!GetDlgItem(IDOK)->IsWindowEnabled())
229 // only show the wait cursor over the list control
230 if ((pWnd)&&(pWnd == GetDlgItem(IDC_SVNPROGRESS)))
232 HCURSOR hCur = LoadCursor(NULL, MAKEINTRESOURCE(IDC_WAIT));
233 SetCursor(hCur);
234 return TRUE;
237 HCURSOR hCur = LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW));
238 SetCursor(hCur);
239 return CResizableStandAloneDialog::OnSetCursor(pWnd, nHitTest, message);
242 BOOL CGitProgressDlg::PreTranslateMessage(MSG* pMsg)
244 if (pMsg->message == WM_KEYDOWN)
246 if (pMsg->wParam == VK_ESCAPE)
248 // pressing the ESC key should close the dialog. But since we disabled the escape
249 // key (so the user doesn't get the idea that he could simply undo an e.g. update)
250 // this won't work.
251 // So if the user presses the ESC key, change it to VK_RETURN so the dialog gets
252 // the impression that the OK button was pressed.
253 if ((!m_ProgList.IsRunning())&&(!GetDlgItem(IDCANCEL)->IsWindowEnabled())
254 &&(GetDlgItem(IDOK)->IsWindowEnabled())&&(GetDlgItem(IDOK)->IsWindowVisible()))
256 // since we convert ESC to RETURN, make sure the OK button has the focus.
257 GetDlgItem(IDOK)->SetFocus();
258 pMsg->wParam = VK_RETURN;
262 return __super::PreTranslateMessage(pMsg);
267 void CGitProgressDlg::OnEnSetfocusInfotext()
269 CString sTemp;
270 GetDlgItemText(IDC_INFOTEXT, sTemp);
271 if (sTemp.IsEmpty())
272 GetDlgItem(IDC_INFOTEXT)->HideCaret();
276 void CGitProgressDlg::OnBnClickedNoninteractive()
278 LRESULT res = ::SendMessage(GetDlgItem(IDC_NONINTERACTIVE)->GetSafeHwnd(), BM_GETCHECK, 0, 0);
279 m_ProgList.m_AlwaysConflicted = (res == BST_CHECKED);
280 CRegDWORD nonint = CRegDWORD(_T("Software\\TortoiseGit\\MergeNonInteractive"), FALSE);
281 nonint = m_ProgList.m_AlwaysConflicted;
284 LRESULT CGitProgressDlg::OnCtlColorStatic(WPARAM wParam, LPARAM lParam)
286 HDC hDC = (HDC)wParam;
287 HWND hwndCtl = (HWND)lParam;
289 if (::GetDlgCtrlID(hwndCtl) == IDC_TITLE_ANIMATE)
291 CDC *pDC = CDC::FromHandle(hDC);
292 pDC->SetBkColor(GetSysColor(COLOR_WINDOW));
293 pDC->SetBkMode(TRANSPARENT);
294 return (LRESULT)(HBRUSH)m_background_brush.GetSafeHandle();
296 return FALSE;
299 HBRUSH CGitProgressDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
301 HBRUSH hbr;
302 if (pWnd->GetDlgCtrlID() == IDC_TITLE_ANIMATE)
304 pDC->SetBkColor(GetSysColor(COLOR_WINDOW)); // add this
305 pDC->SetBkMode(TRANSPARENT);
306 return (HBRUSH)m_background_brush.GetSafeHandle();
308 else
309 hbr = CResizableStandAloneDialog::OnCtlColor(pDC, pWnd, nCtlColor);
311 // TODO: Return a different brush if the default is not desired
312 return hbr;
315 LRESULT CGitProgressDlg::OnCmdEnd(WPARAM wParam, LPARAM /*lParam*/)
317 DialogEnableWindow(IDCANCEL, FALSE);
318 DialogEnableWindow(IDOK, TRUE);
320 switch(wParam)
322 case CGitProgressList::GitProgress_Add:
323 case CGitProgressList::GitProgress_Revert:
324 this->GetDlgItem(IDC_LOGBUTTON)->SetWindowText(CString(MAKEINTRESOURCE(IDS_COMMITBUTTON)));
325 this->GetDlgItem(IDC_LOGBUTTON)->ShowWindow(SW_SHOW);
326 break;
329 CWnd * pWndOk = GetDlgItem(IDOK);
330 if (pWndOk && ::IsWindow(pWndOk->GetSafeHwnd()))
332 SendMessage(DM_SETDEFID, IDOK);
333 GetDlgItem(IDOK)->SetFocus();
336 return 0;
338 LRESULT CGitProgressDlg::OnCmdStart(WPARAM /*wParam*/, LPARAM /*lParam*/)
340 DialogEnableWindow(IDOK, FALSE);
341 DialogEnableWindow(IDCANCEL, TRUE);
343 return 0;