use gitdll gethash and clean up some warning
[TortoiseGit.git] / src / TortoiseProc / GitLogListBase.h
blobb0bb1adbfa9d96d1842ade7b0cab0798af9bf88a
1 #pragma once
3 #include "HintListCtrl.h"
4 #include "XPTheme.h"
5 #include "CommonResource.h"
6 #include "Git.h"
7 #include "ProjectProperties.h"
8 #include "TGitPath.h"
9 #include "registry.h"
10 #include "SplitterControl.h"
11 #include "Colors.h"
12 #include "MenuButton.h"
13 #include "LogDlgHelper.h"
14 #include "FilterEdit.h"
15 #include "GitRev.h"
16 #include "Tooltip.h"
17 //#include "GitLogList.h"
18 #include "lanes.h"
19 #include "GitLogCache.h"
20 #include <regex>
21 #include <GitStatusListCtrl.h>
22 #include "FindDlg.h"
24 // CGitLogList
25 #if (NTDDI_VERSION < NTDDI_LONGHORN)
27 enum LISTITEMSTATES_MINE {
28 LISS_NORMAL = 1,
29 LISS_HOT = 2,
30 LISS_SELECTED = 3,
31 LISS_DISABLED = 4,
32 LISS_SELECTEDNOTFOCUS = 5,
33 LISS_HOTSELECTED = 6,
36 // these defines must be in the order the columns are inserted!
39 #define MCS_NOTRAILINGDATES 0x0040
40 #define MCS_SHORTDAYSOFWEEK 0x0080
41 #define MCS_NOSELCHANGEONNAV 0x0100
43 #define DTM_SETMCSTYLE (DTM_FIRST + 11)
45 #endif
47 #define ICONITEMBORDER 5
49 #define GITLOG_START 0
50 #define GITLOG_START_ALL 1
51 #define GITLOG_END 100
53 #define LOGFILTER_ALL 1
54 #define LOGFILTER_MESSAGES 2
55 #define LOGFILTER_PATHS 3
56 #define LOGFILTER_AUTHORS 4
57 #define LOGFILTER_REVS 5
58 #define LOGFILTER_REGEX 6
59 #define LOGFILTER_BUGID 7
61 //typedef void CALLBACK_PROCESS(void * data, int progress);
62 #define MSG_LOADED (WM_USER+110)
63 #define MSG_LOAD_PERCENTAGE (WM_USER+111)
64 #define MSG_REFLOG_CHANGED (WM_USER+112)
65 #define MSG_FETCHED_DIFF (WM_USER+113)
67 class CThreadSafePtrArray: public CPtrArray
69 CComCriticalSection *m_critSec;
70 public:
71 CThreadSafePtrArray(CComCriticalSection *section){ m_critSec = section ;}
72 void * SafeGetAt(INT_PTR i)
74 if(m_critSec)
75 m_critSec->Lock();
77 if( i<0 || i>=GetCount())
79 if(m_critSec)
80 m_critSec->Unlock();
82 return NULL;
85 if(m_critSec)
86 m_critSec->Unlock();
88 return GetAt(i);
90 INT_PTR SafeAdd(void *newElement)
92 INT_PTR ret;
93 if(m_critSec)
94 m_critSec->Lock();
95 ret = Add(newElement);
96 if(m_critSec)
97 m_critSec->Unlock();
98 return ret;
101 void SafeRemoveAll()
103 if(m_critSec)
104 m_critSec->Lock();
105 RemoveAll();
106 if(m_critSec)
107 m_critSec->Unlock();
112 class CGitLogListBase : public CHintListCtrl
114 DECLARE_DYNAMIC(CGitLogListBase)
116 public:
117 CGitLogListBase();
118 virtual ~CGitLogListBase();
119 ProjectProperties m_ProjectProperties;
121 CFilterData m_Filter;
123 void UpdateProjectProperties()
125 m_ProjectProperties.ReadProps(this->m_Path);
127 if ((!m_ProjectProperties.sUrl.IsEmpty())||(!m_ProjectProperties.sCheckRe.IsEmpty()))
128 m_bShowBugtraqColumn = true;
129 else
130 m_bShowBugtraqColumn = false;
133 void ResetWcRev()
135 m_wcRev.GetBody()=_T("Fetching Status...");
136 m_wcRev.m_CallDiffAsync = DiffAsync;
137 InterlockedExchange(&m_wcRev.m_IsDiffFiles, FALSE);
139 void SetProjectPropertiesPath(const CTGitPath& path) {m_ProjectProperties.ReadProps(path);}
141 volatile LONG m_bNoDispUpdates;
142 BOOL m_IsIDReplaceAction;
143 BOOL m_IsOldFirst;
144 void hideFromContextMenu(unsigned __int64 hideMask, bool exclusivelyShow);
145 BOOL m_IsRebaseReplaceGraph;
147 void MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct);
149 BOOL m_bStrictStopped;
150 BOOL m_bShowBugtraqColumn;
151 BOOL m_bSearchIndex;
152 BOOL m_bCancelled;
153 unsigned __int64 m_ContextMenuMask;
155 bool m_hasWC;
156 bool m_bShowWC;
157 GitRev m_wcRev;
158 volatile LONG m_bThreadRunning;
159 CLogCache m_LogCache;
161 CString m_startrev;
162 CString m_endrev;
164 // don't forget to bump BLAME_COLUMN_VERSION in GitStatusListCtrlHelpers.cpp if you change columns
165 enum
167 LOGLIST_GRAPH,
168 LOGLIST_REBASE,
169 LOGLIST_ID,
170 LOGLIST_HASH,
171 LOGLIST_ACTION,
172 LOGLIST_MESSAGE,
173 LOGLIST_AUTHOR,
174 LOGLIST_DATE,
175 LOGLIST_EMAIL,
176 LOGLIST_COMMIT_NAME,
177 LOGLIST_COMMIT_EMAIL,
178 LOGLIST_COMMIT_DATE,
179 LOGLIST_BUG,
180 LOGLIST_MESSAGE_MAX=300,
181 LOGLIST_MESSAGE_MIN=200,
183 GIT_LOG_GRAPH = 1<< LOGLIST_GRAPH,
184 GIT_LOG_REBASE = 1<< LOGLIST_REBASE,
185 GIT_LOG_ID = 1<< LOGLIST_ID,
186 GIT_LOG_HASH = 1<< LOGLIST_HASH,
187 GIT_LOG_ACTIONS = 1<< LOGLIST_ACTION,
188 GIT_LOG_MESSAGE = 1<< LOGLIST_MESSAGE,
189 GIT_LOG_AUTHOR = 1<< LOGLIST_AUTHOR,
190 GIT_LOG_DATE = 1<< LOGLIST_DATE,
191 GIT_LOG_EMAIL = 1<< LOGLIST_EMAIL,
192 GIT_LOG_COMMIT_NAME = 1<< LOGLIST_COMMIT_NAME,
193 GIT_LOG_COMMIT_EMAIL= 1<< LOGLIST_COMMIT_EMAIL,
194 GIT_LOG_COMMIT_DATE = 1<< LOGLIST_COMMIT_DATE,
195 GIT_LOGLIST_BUG = 1<< LOGLIST_BUG,
198 enum
200 // needs to start with 1, since 0 is the return value if *nothing* is clicked on in the context menu
201 ID_COMPARE = 1,
202 ID_SAVEAS,
203 ID_COMPARETWO,
204 ID_UPDATE,
205 ID_COPY,
206 ID_REVERTREV,
207 ID_MERGEREV,
208 ID_GNUDIFF1,
209 ID_GNUDIFF2,
210 ID_FINDENTRY,
211 ID_OPEN,
212 ID_BLAME,
213 ID_REPOBROWSE,
214 ID_LOG,
215 ID_POPPROPS,
216 ID_EDITNOTE,
217 ID_EDITLOG,
218 ID_DIFF,
219 ID_OPENWITH,
220 ID_COPYCLIPBOARD,
221 ID_COPYHASH,
222 ID_CHECKOUT,
223 ID_REVERTTOREV,
224 ID_BLAMECOMPARE,
225 ID_BLAMETWO,
226 ID_BLAMEDIFF,
227 ID_VIEWREV,
228 ID_VIEWPATHREV,
229 ID_EXPORT,
230 ID_COMPAREWITHPREVIOUS,
231 ID_BLAMEWITHPREVIOUS,
232 ID_GETMERGELOGS,
233 ID_REVPROPS,
234 ID_CHERRY_PICK,
235 ID_CREATE_BRANCH,
236 ID_CREATE_TAG,
237 ID_SWITCHTOREV,
238 ID_SWITCHBRANCH,
239 ID_RESET,
240 ID_REBASE_PICK,
241 ID_REBASE_EDIT,
242 ID_REBASE_SQUASH,
243 ID_REBASE_SKIP,
244 ID_COMBINE_COMMIT,
245 ID_STASH_APPLY,
246 ID_REFLOG_DEL,
247 ID_REBASE_TO_VERSION,
248 ID_CREATE_PATCH,
249 ID_DELETE,
250 ID_COMMIT,
252 inline unsigned __int64 GetContextMenuBit(int i){ return ((unsigned __int64 )0x1)<<i ;}
253 void InsertGitColumn();
254 void ResizeAllListCtrlCols();
255 void CopySelectionToClipBoard(bool hashonly=FALSE);
256 void DiffSelectedRevWithPrevious();
257 bool IsSelectionContinuous();
258 int BeginFetchLog();
259 int FillGitLog(CTGitPath *path,int infomask=CGit:: LOG_INFO_STAT| CGit::LOG_INFO_FILESTATE | CGit::LOG_INFO_SHOW_MERGEDFILE,CString *from=NULL,CString *to=NULL);
261 CFindDlg *m_pFindDialog;
262 static const UINT m_FindDialogMessage;
263 void OnFind();
265 inline int ShownCountWithStopped() const { return (int)m_arShownList.GetCount() + (m_bStrictStopped ? 1 : 0); }
266 int FetchLogAsync(void * data=NULL);
267 CThreadSafePtrArray m_arShownList;
268 void Refresh(BOOL IsCleanFilter=TRUE);
269 void RecalculateShownList(CThreadSafePtrArray * pShownlist);
270 void Clear();
272 int m_nSelectedFilter;
273 bool m_bFilterWithRegex;
274 CLogDataVector m_logEntries;
275 void RemoveFilter();
276 void StartFilter();
277 bool ValidateRegexp(LPCTSTR regexp_str, tr1::wregex& pat, bool bMatchCase = false );
278 CString m_sFilterText;
280 __time64_t m_From;
281 __time64_t m_To;
283 CTGitPath m_Path;
284 int m_ShowMask;
286 void GetTimeRange(CTime &oldest,CTime &latest);
287 virtual void ContextMenuAction(int cmd,int FirstSelect, int LastSelect, CMenu * menu)=0;
288 void ReloadHashMap()
290 m_HashMap.clear();
291 g_Git.GetMapHashToFriendName(m_HashMap);
292 m_CurrentBranch=g_Git.GetCurrentBranch();
293 this->m_HeadHash=g_Git.GetHash(_T("HEAD"));
294 m_wcRev.m_ParentHash.clear();
295 m_wcRev.m_ParentHash.push_back(m_HeadHash);
297 void SafeTerminateThread()
299 if(m_LoadingThread!=NULL)
301 InterlockedExchange(&m_bExitThread,TRUE);
302 DWORD ret =::WaitForSingleObject(m_LoadingThread->m_hThread,20000);
303 if(ret == WAIT_TIMEOUT)
304 ::TerminateThread(m_LoadingThread,0);
305 m_LoadingThread = NULL;
309 bool IsInWorkingThread()
311 return (AfxGetThread() == m_LoadingThread);
314 void SetStartRef(const CString& StartRef)
316 m_StartRef=StartRef;
319 CString GetStartRef() const {return m_StartRef;}
321 int m_nSearchIndex;
323 volatile LONG m_bExitThread;
324 CWinThread* m_LoadingThread;
325 MAP_HASH_NAME m_HashMap;
327 public:
328 CString m_ColumnRegKey;
330 protected:
331 DECLARE_MESSAGE_MAP()
332 afx_msg void OnDestroy();
333 virtual afx_msg void OnNMCustomdrawLoglist(NMHDR *pNMHDR, LRESULT *pResult);
334 virtual afx_msg void OnLvnGetdispinfoLoglist(NMHDR *pNMHDR, LRESULT *pResult);
335 afx_msg LRESULT OnFindDialogMessage(WPARAM wParam, LPARAM lParam);
336 afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
337 afx_msg void OnContextMenu(CWnd* pWnd, CPoint point);
338 afx_msg LRESULT OnLoad(WPARAM wParam, LPARAM lParam);
339 afx_msg void OnHdnBegintrack(NMHDR *pNMHDR, LRESULT *pResult);
340 afx_msg void OnHdnItemchanging(NMHDR *pNMHDR, LRESULT *pResult);
341 afx_msg void OnColumnResized(NMHDR *pNMHDR, LRESULT *pResult);
342 afx_msg void OnColumnMoved(NMHDR *pNMHDR, LRESULT *pResult);
343 void OnNMDblclkLoglist(NMHDR * /*pNMHDR*/, LRESULT *pResult);
344 afx_msg void OnLvnOdfinditemLoglist(NMHDR *pNMHDR, LRESULT *pResult);
345 void PreSubclassWindow();
346 virtual BOOL PreTranslateMessage(MSG* pMsg);
347 static UINT LogThreadEntry(LPVOID pVoid);
348 UINT LogThread();
349 void FetchLastLogInfo();
350 void FetchFullLogInfo(CString &from, CString &to);
351 void FillBackGround(HDC hdc, int Index,CRect &rect);
352 void DrawTagBranch(HDC,CRect &rect,INT_PTR index);
353 void DrawGraph(HDC,CRect &rect,INT_PTR index);
355 BOOL GetShortName(CString ref, CString &shortname,CString prefix);
356 void paintGraphLane(HDC hdc,int laneHeight, int type, int x1, int x2,
357 const COLORREF& col,const COLORREF& activeColor, int top) ;
358 void DrawLine(HDC hdc, int x1, int y1, int x2, int y2){::MoveToEx(hdc,x1,y1,NULL);::LineTo(hdc,x2,y2);}
360 * Save column widths to the registry
362 void SaveColumnWidths(); // save col widths to the registry
364 BOOL IsEntryInDateRange(int i);
366 int GetHeadIndex();
368 std::vector<GitRev*> m_AsynDiffList;
369 CComCriticalSection m_AysnDiffListLock;
370 HANDLE m_AsyncDiffEvent;
371 volatile LONG m_AsyncThreadExit;
372 CWinThread* m_DiffingThread;
374 static int DiffAsync(GitRev *rev, void *data)
376 ULONGLONG offset=((CGitLogListBase*)data)->m_LogCache.GetOffset(rev->m_CommitHash);
377 if(!offset)
379 ((CGitLogListBase*)data)->m_AysnDiffListLock.Lock();
380 ((CGitLogListBase*)data)->m_AsynDiffList.push_back(rev);
381 ((CGitLogListBase*)data)->m_AysnDiffListLock.Unlock();
382 ::SetEvent(((CGitLogListBase*)data)->m_AsyncDiffEvent);
383 }else
385 if(((CGitLogListBase*)data)->m_LogCache.LoadOneItem(*rev,offset))
387 ((CGitLogListBase*)data)->m_AysnDiffListLock.Lock();
388 ((CGitLogListBase*)data)->m_AsynDiffList.push_back(rev);
389 ((CGitLogListBase*)data)->m_AysnDiffListLock.Unlock();
390 ::SetEvent(((CGitLogListBase*)data)->m_AsyncDiffEvent);
392 InterlockedExchange(&rev->m_IsDiffFiles, TRUE);
393 if(rev->m_IsDiffFiles && rev->m_IsCommitParsed)
394 InterlockedExchange(&rev->m_IsFull, TRUE);
396 return 0;
399 static UINT AsyncThread(LPVOID data)
401 return ((CGitLogListBase*)data)->AsyncDiffThread();
404 int AsyncDiffThread();
405 public:
406 void SafeTerminateAsyncDiffThread()
408 if(m_DiffingThread!=NULL && m_AsyncThreadExit != TRUE)
410 m_AsyncThreadExit = TRUE;
411 ::SetEvent(m_AsyncDiffEvent);
412 DWORD ret = WAIT_TIMEOUT;
413 // do not block here, but process messages and ask until the thread ends
414 while (ret == WAIT_TIMEOUT)
416 AfxGetThread()->PumpMessage(); // process messages, so that GetTopIndex and so on in the thread work
417 ret = ::WaitForSingleObject(m_DiffingThread->m_hThread, 100);
419 m_DiffingThread = NULL;
423 protected:
424 CComCriticalSection m_critSec;
426 CXPTheme m_Theme;
427 BOOL m_bVista;
429 HICON m_hModifiedIcon;
430 HICON m_hReplacedIcon;
431 HICON m_hAddedIcon;
432 HICON m_hDeletedIcon;
433 HICON m_hFetchIcon;
435 HFONT m_boldFont;
437 CRegDWORD m_regMaxBugIDColWidth;
439 void *m_ProcData;
440 CStoreSelection* m_pStoreSelection;
442 CColors m_Colors;
444 CString m_CurrentBranch;
445 CGitHash m_HeadHash;
447 CString m_StartRef; //Ref of the top-commit
449 COLORREF m_LineColors[Lanes::COLORS_NUM];
450 DWORD m_DateFormat; // DATE_SHORTDATE or DATE_LONGDATE
451 bool m_bRelativeTimes; // Show relative times
452 GIT_LOG m_DllGitLog;
454 ColumnManager m_ColumnManager;
455 DWORD m_dwDefaultColumns;