Fixed issue #3668: "Revert to revision" fails for added files
[TortoiseGit.git] / src / TortoiseProc / PatchListCtrl.cpp
blob80de4a215a0aff6ac9ad7f708b9359be4f07c42b
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2009-2013, 2015-2016, 2018-2019 - TortoiseGit
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 2
8 // of the License, or (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software Foundation,
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 // PathListCtrl.cpp : implementation file
22 #include "stdafx.h"
23 #include "TortoiseProc.h"
24 #include "PatchListCtrl.h"
25 #include "IconMenu.h"
26 #include "AppUtils.h"
27 #include "Git.h"
28 #include "AppUtils.h"
29 // CPatchListCtrl
31 IMPLEMENT_DYNAMIC(CPatchListCtrl, CListCtrl)
33 CPatchListCtrl::CPatchListCtrl()
34 : m_ContextMenuMask(0xFFFFFFFF)
38 CPatchListCtrl::~CPatchListCtrl()
42 void CPatchListCtrl::PreSubclassWindow()
44 __super::PreSubclassWindow();
46 // use the default font, create a copy of it and
47 // change the copy to BOLD (leave the rest of the font
48 // the same)
49 LOGFONT lf = { 0 };
50 GetFont()->GetLogFont(&lf);
51 lf.lfWeight = FW_BOLD;
52 m_boldFont.CreateFontIndirect(&lf);
55 BEGIN_MESSAGE_MAP(CPatchListCtrl, CListCtrl)
56 ON_NOTIFY_REFLECT(NM_DBLCLK, &CPatchListCtrl::OnNMDblclk)
57 ON_WM_CONTEXTMENU()
58 ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, &CPatchListCtrl::OnNMCustomdraw)
59 ON_WM_DROPFILES()
60 END_MESSAGE_MAP()
64 // CPatchListCtrl message handlers
68 void CPatchListCtrl::OnNMDblclk(NMHDR *pNMHDR, LRESULT *pResult)
70 LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
72 CString path=GetItemText(pNMItemActivate->iItem,0);
73 CTGitPath gitpath;
74 gitpath.SetFromWin(path);
76 CAppUtils::StartUnifiedDiffViewer(path, gitpath.GetFilename(), 0, !!(GetAsyncKeyState(VK_SHIFT) & 0x8000));
78 *pResult = 0;
81 void CPatchListCtrl::OnContextMenu(CWnd* /*pWnd*/, CPoint point)
83 int selected=this->GetSelectedCount();
84 POSITION pos=this->GetFirstSelectedItemPosition();
85 auto index = this->GetNextSelectedItem(pos);
87 CIconMenu popup;
88 if (popup.CreatePopupMenu())
90 if(selected == 1)
92 if( m_ContextMenuMask&GetMenuMask(MENU_VIEWPATCH))
93 popup.AppendMenuIcon(MENU_VIEWPATCH, IDS_MENU_VIEWPATCH, 0);
95 if( m_ContextMenuMask&GetMenuMask(MENU_VIEWWITHMERGE))
96 popup.AppendMenuIcon(MENU_VIEWWITHMERGE, IDS_MENU_VIEWWITHMERGE, 0);
98 popup.SetDefaultItem(MENU_VIEWPATCH, FALSE);
100 if(selected >= 1)
102 if( m_ContextMenuMask&GetMenuMask(MENU_SENDMAIL))
103 popup.AppendMenuIcon(MENU_SENDMAIL, IDS_MENU_SENDMAIL, IDI_MENUSENDMAIL);
105 if( m_ContextMenuMask&GetMenuMask(MENU_APPLY))
106 popup.AppendMenuIcon(MENU_APPLY, IDS_MENU_APPLY, 0);
109 int cmd = popup.TrackPopupMenu(TPM_RETURNCMD | TPM_LEFTALIGN | TPM_NONOTIFY, point.x, point.y, this);
111 switch (cmd)
113 case MENU_VIEWPATCH:
115 CString path=GetItemText(index,0);
116 CTGitPath gitpath;
117 gitpath.SetFromWin(path);
119 CAppUtils::StartUnifiedDiffViewer(path, gitpath.GetFilename(), 0, !!(GetAsyncKeyState(VK_SHIFT) & 0x8000));
120 break;
122 case MENU_VIEWWITHMERGE:
124 CString path=GetItemText(index,0);
125 CTGitPath gitpath;
126 gitpath.SetFromWin(path);
128 CTGitPath dir;
129 dir.SetFromGit(g_Git.m_CurrentDir);
131 CAppUtils::StartExtPatch(gitpath,dir);
132 break;
134 case MENU_SENDMAIL:
136 LaunchProc(L"sendmail");
137 break;
139 case MENU_APPLY:
141 LaunchProc(L"importpatch");
143 break;
145 default:
146 break;
151 int CPatchListCtrl::LaunchProc(const CString& command)
153 CString tempfile=GetTempFile();
154 POSITION pos=this->GetFirstSelectedItemPosition();
155 CFile file;
156 file.Open(tempfile,CFile::modeWrite|CFile::modeCreate);
158 while(pos)
160 int index = this->GetNextSelectedItem(pos);
161 CString one=this->GetItemText(index,0);
162 file.Write(static_cast<LPCTSTR>(one), sizeof(TCHAR) * one.GetLength());
163 file.Write(L"\n", sizeof(TCHAR) * 1);
166 file.Close();
168 CString cmd = L"/command:";
169 cmd += command;
170 cmd += L" /pathfile:\"";
171 cmd += tempfile;
172 cmd += L"\" /deletepathfile";
173 CAppUtils::RunTortoiseGitProc(cmd);
174 return 0;
177 void CPatchListCtrl::OnNMCustomdraw(NMHDR *pNMHDR, LRESULT *pResult)
179 NMLVCUSTOMDRAW *pNMCD = reinterpret_cast<NMLVCUSTOMDRAW*>(pNMHDR);
181 *pResult = 0;
183 switch (pNMCD->nmcd.dwDrawStage)
185 case CDDS_PREPAINT:
187 *pResult = CDRF_NOTIFYITEMDRAW;
188 return;
190 break;
191 case CDDS_ITEMPREPAINT:
193 // This is the prepaint stage for an item. Here's where we set the
194 // item's text color.
196 // Tell Windows to send draw notifications for each subitem.
197 *pResult = CDRF_NOTIFYSUBITEMDRAW;
199 DWORD_PTR data = this->GetItemData(static_cast<int>(pNMCD->nmcd.dwItemSpec));
200 if(data & (STATUS_APPLY_FAIL | STATUS_APPLY_SUCCESS | STATUS_APPLY_SKIP))
201 pNMCD->clrTextBk = RGB(200,200,200);
203 switch(data & STATUS_MASK)
205 case STATUS_APPLY_SUCCESS:
206 pNMCD->clrText = RGB(0,128,0);
207 break;
208 case STATUS_APPLY_FAIL:
209 pNMCD->clrText = RGB(255,0,0);
210 break;
211 case STATUS_APPLY_SKIP:
212 pNMCD->clrText = RGB(128,64,0);
213 break;
216 if(data & STATUS_APPLYING)
218 SelectObject(pNMCD->nmcd.hdc, m_boldFont.GetSafeHandle());
219 *pResult = CDRF_NOTIFYSUBITEMDRAW | CDRF_NEWFONT;
223 break;
225 *pResult = CDRF_DODEFAULT;
228 void CPatchListCtrl::OnDropFiles(HDROP hDropInfo)
230 UINT nNumFiles = DragQueryFile(hDropInfo, 0xFFFFFFFF, nullptr, 0);
231 for (UINT i = 0; i < nNumFiles; ++i)
233 CString file;
234 DragQueryFile(hDropInfo, i, CStrBuf(file, MAX_PATH), MAX_PATH);
235 if (PathIsDirectory(file))
236 continue;
238 // no duplicates
239 LVFINDINFO lvInfo;
240 lvInfo.flags = LVFI_STRING;
241 lvInfo.psz = file;
242 if (FindItem(&lvInfo, -1) != -1)
243 continue;
245 int index = InsertItem(GetItemCount(), file);
246 if (index >= 0)
247 SetCheck(index, true);
249 DragFinish(hDropInfo);
250 SetColumnWidth(0, LVSCW_AUTOSIZE);