#include "..\\TortoiseShell\\Resource.h"\r
\r
\r
-\r
IMPLEMENT_DYNAMIC(CGitLogListBase, CHintListCtrl)\r
\r
CGitLogListBase::CGitLogListBase():CHintListCtrl()\r
m_bFilterWithRegex = !!CRegDWORD(_T("Software\\TortoiseGit\\UseRegexFilter"), TRUE);\r
\r
g_Git.GetMapHashToFriendName(m_HashMap);\r
+ m_CurrentBranch=g_Git.GetCurrentBranch();\r
\r
m_From=CTime(1970,1,2,0,0,0);\r
m_To=CTime::GetCurrentTime();\r
- m_bAllBranch = FALSE;\r
+ m_ShowMask = 0;\r
+ m_LoadingThread = NULL;\r
+\r
+ m_bExitThread=FALSE;\r
+\r
+ for(int i=0;i<Lanes::COLORS_NUM;i++)\r
+ {\r
+ m_LineColors[i] = m_Colors.GetColor((CColors::Colors)(CColors::BranchLine1+i));\r
+ }\r
+ // get short/long datetime setting from registry\r
+ DWORD RegUseShortDateFormat = CRegDWORD(_T("Software\\TortoiseGit\\LogDateFormat"), TRUE);\r
+ if ( RegUseShortDateFormat )\r
+ {\r
+ m_DateFormat = DATE_SHORTDATE;\r
+ }\r
+ else\r
+ {\r
+ m_DateFormat = DATE_LONGDATE;\r
+ }\r
}\r
\r
CGitLogListBase::~CGitLogListBase()\r
delete m_pStoreSelection;\r
m_pStoreSelection = NULL;\r
}\r
+\r
+ if(this->m_bThreadRunning)\r
+ {\r
+ m_bExitThread=true;\r
+ WaitForSingleObject(m_LoadingThread->m_hThread,1000);\r
+ TerminateThread();\r
+ }\r
}\r
\r
\r
ON_NOTIFY_REFLECT(NM_DBLCLK, OnNMDblclkLoglist)\r
ON_NOTIFY_REFLECT(LVN_ODFINDITEM,OnLvnOdfinditemLoglist)\r
ON_WM_CREATE()\r
+ ON_WM_DESTROY()\r
+ ON_MESSAGE(MSG_LOADED,OnLoad)\r
END_MESSAGE_MAP()\r
\r
int CGitLogListBase:: OnCreate(LPCREATESTRUCT lpCreateStruct)\r
\r
}\r
\r
+/**\r
+ * Resizes all columns in a list control to values in registry.\r
+ */\r
void CGitLogListBase::ResizeAllListCtrlCols()\r
{\r
-\r
- const int nMinimumWidth = ICONITEMBORDER+16*4;\r
- int maxcol = ((CHeaderCtrl*)(GetDlgItem(0)))->GetItemCount()-1;\r
- int nItemCount = GetItemCount();\r
- TCHAR textbuf[MAX_PATH];\r
- CHeaderCtrl * pHdrCtrl = (CHeaderCtrl*)(GetDlgItem(0));\r
+ // column max and min widths to allow\r
+ static const int nMinimumWidth = 10;\r
+ static const int nMaximumWidth = 1000;\r
+ CHeaderCtrl* pHdrCtrl = (CHeaderCtrl*)(GetDlgItem(0));\r
if (pHdrCtrl)\r
{\r
- for (int col = 0; col <= maxcol; col++)\r
+ int numcols = pHdrCtrl->GetItemCount();\r
+ for (int col = 0; col < numcols; col++)\r
{\r
- HDITEM hdi = {0};\r
- hdi.mask = HDI_TEXT;\r
- hdi.pszText = textbuf;\r
- hdi.cchTextMax = sizeof(textbuf);\r
- pHdrCtrl->GetItem(col, &hdi);\r
- int cx = GetStringWidth(hdi.pszText)+20; // 20 pixels for col separator and margin\r
- for (int index = 0; index<nItemCount; ++index)\r
- {\r
- // get the width of the string and add 14 pixels for the column separator and margins\r
- int linewidth = GetStringWidth(GetItemText(index, col)) + 14;\r
- if (index < m_arShownList.GetCount())\r
- {\r
- GitRev * pCurLogEntry = reinterpret_cast<GitRev*>(m_arShownList.GetAt(index));\r
- if ((pCurLogEntry)&&(pCurLogEntry->m_CommitHash == m_wcRev.m_CommitHash))\r
- {\r
- // set the bold font and ask for the string width again\r
- SendMessage(WM_SETFONT, (WPARAM)m_boldFont, NULL);\r
- linewidth = GetStringWidth(GetItemText(index, col)) + 14;\r
- // restore the system font\r
- SendMessage(WM_SETFONT, NULL, NULL);\r
- }\r
- }\r
- if (index == 0)\r
- {\r
- // add the image size\r
- CImageList * pImgList = GetImageList(LVSIL_SMALL);\r
- if ((pImgList)&&(pImgList->GetImageCount()))\r
- {\r
- IMAGEINFO imginfo;\r
- pImgList->GetImageInfo(0, &imginfo);\r
- linewidth += (imginfo.rcImage.right - imginfo.rcImage.left);\r
- linewidth += 3; // 3 pixels between icon and text\r
- }\r
- }\r
- if (cx < linewidth)\r
- cx = linewidth;\r
- }\r
- // Adjust columns "Actions" containing icons\r
- if (col == this->LOGLIST_ACTION)\r
+ // get width for this col last time from registry\r
+ CString regentry;\r
+ regentry.Format( _T("Software\\TortoiseGit\\log\\ColWidth%d"), col);\r
+ CRegDWORD regwidth(regentry, 0);\r
+ int cx = regwidth;\r
+ if (cx < nMinimumWidth)\r
{\r
- if (cx < nMinimumWidth)\r
- {\r
- cx = nMinimumWidth;\r
- }\r
- }\r
- \r
- if (col == this->LOGLIST_MESSAGE)\r
- {\r
- if (cx > LOGLIST_MESSAGE_MAX)\r
- {\r
- cx = LOGLIST_MESSAGE_MAX;\r
- }\r
- if (cx < LOGLIST_MESSAGE_MIN)\r
- {\r
- cx = LOGLIST_MESSAGE_MIN;\r
- }\r
-\r
- }\r
- // keep the bug id column small\r
- if ((col == 4)&&(m_bShowBugtraqColumn))\r
+ cx = nMinimumWidth;\r
+ } else if (cx > nMaximumWidth)\r
{\r
- if (cx > (int)(DWORD)m_regMaxBugIDColWidth)\r
- {\r
- cx = (int)(DWORD)m_regMaxBugIDColWidth;\r
- }\r
+ cx = nMaximumWidth;\r
}\r
\r
SetColumnWidth(col, cx);\r
rItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED;\r
GetItem(&rItem);\r
\r
- for(int i=0;i<m_HashMap[data->m_CommitHash].size();i++)\r
+ for(unsigned int i=0;i<m_HashMap[data->m_CommitHash].size();i++)\r
{\r
CString str;\r
str=m_HashMap[data->m_CommitHash][i];\r
shortname=_T("");\r
if(GetShortName(str,shortname,_T("refs/heads/")))\r
{\r
- brush = ::CreateSolidBrush(RGB(0xff, 0, 0));\r
+ if( shortname == m_CurrentBranch )\r
+ brush = ::CreateSolidBrush(m_Colors.GetColor(CColors::CurrentBranch));\r
+ else\r
+ brush = ::CreateSolidBrush(m_Colors.GetColor(CColors::LocalBranch));\r
+\r
}else if(GetShortName(str,shortname,_T("refs/remotes/")))\r
{\r
- brush = ::CreateSolidBrush(RGB(0xff, 0xff, 0));\r
+ brush = ::CreateSolidBrush(m_Colors.GetColor(CColors::RemoteBranch));\r
}\r
else if(GetShortName(str,shortname,_T("refs/tags/")))\r
{\r
- brush = ::CreateSolidBrush(RGB(0, 0, 0xff));\r
+ brush = ::CreateSolidBrush(m_Colors.GetColor(CColors::Tag));\r
}\r
\r
if(!shortname.IsEmpty())\r
rItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED;\r
GetItem(&rItem);\r
\r
- static const COLORREF colors[Lanes::COLORS_NUM] = { RGB(0,0,0), RGB(0xFF,0,0), RGB(0,0xFF,0),\r
- RGB(0,0,0xFF), RGB(128,128,128), RGB(128,128,0),\r
- RGB(0,128,128), RGB(128,0,128) };\r
-\r
-\r
+ \r
// p->translate(QPoint(opt.rect.left(), opt.rect.top()));\r
\r
\r
|| ln ==Lanes:: CROSS_EMPTY) ? mergeLane : i;\r
\r
if (ln == Lanes::CROSS) {\r
- paintGraphLane(hdc, rect.Height(),Lanes::NOT_ACTIVE, x1, x2, colors[col % Lanes::COLORS_NUM],rect.top);\r
- paintGraphLane(hdc, rect.Height(),Lanes::CROSS, x1, x2, colors[mergeLane % Lanes::COLORS_NUM],rect.top);\r
+ paintGraphLane(hdc, rect.Height(),Lanes::NOT_ACTIVE, x1, x2, m_LineColors[col % Lanes::COLORS_NUM],rect.top);\r
+ paintGraphLane(hdc, rect.Height(),Lanes::CROSS, x1, x2, m_LineColors[mergeLane % Lanes::COLORS_NUM],rect.top);\r
} else\r
- paintGraphLane(hdc, rect.Height(),ln, x1, x2, colors[col % Lanes::COLORS_NUM],rect.top);\r
+ paintGraphLane(hdc, rect.Height(),ln, x1, x2, m_LineColors[col % Lanes::COLORS_NUM],rect.top);\r
}\r
\r
TRACE(_T("index %d %d\r\n"),index,data->m_Lanes.size());\r
if (m_arShownList.GetCount() > (INT_PTR)pLVCD->nmcd.dwItemSpec)\r
{\r
GitRev* data = (GitRev*)m_arShownList.GetAt(pLVCD->nmcd.dwItemSpec);\r
- if(!data->m_IsFull)\r
- {\r
- if(data->SafeFetchFullInfo(&g_Git))\r
- this->Invalidate();\r
- TRACE(_T("Update ... %d\r\n"),pLVCD->nmcd.dwItemSpec);\r
- }\r
+ //if(!data->m_IsFull)\r
+ //{\r
+ //if(data->SafeFetchFullInfo(&g_Git))\r
+ // this->Invalidate();\r
+ //TRACE(_T("Update ... %d\r\n"),pLVCD->nmcd.dwItemSpec);\r
+ //}\r
\r
if(m_HashMap[data->m_CommitHash].size()!=0)\r
{\r
break;\r
case this->LOGLIST_DATE: //Date\r
if (pLogEntry)\r
- lstrcpyn(pItem->pszText, (LPCTSTR)pLogEntry->m_AuthorDate.Format(_T("%Y-%m-%d %H:%M")), pItem->cchTextMax);\r
+ lstrcpyn(pItem->pszText,\r
+ CAppUtils::FormatDateAndTime( pLogEntry->m_AuthorDate, m_DateFormat, true, true ), \r
+ pItem->cchTextMax);\r
break;\r
\r
case 5:\r
//if (m_hasWC)\r
// popup.AppendMenuIcon(ID_MERGEREV, IDS_LOG_POPUP_MERGEREV, IDI_MERGE);\r
\r
+ CString str;\r
+ str.Format(_T("Reset %s to this"),g_Git.GetCurrentBranch());\r
+ popup.AppendMenuIcon(ID_RESET,str,IDI_REVERT);\r
popup.AppendMenuIcon(ID_SWITCHTOREV, _T("Switch/Checkout to this") , IDI_SWITCH);\r
popup.AppendMenuIcon(ID_CREATE_BRANCH, _T("Create Branch at this version") , IDI_COPY);\r
popup.AppendMenuIcon(ID_CREATE_TAG, _T("Create Tag at this version"), IDI_COPY);\r
sLogCopyText.Format(_T("%s: %s\r\n%s: %s\r\n%s: %s\r\n%s:\r\n%s\r\n----\r\n%s\r\n\r\n"),\r
(LPCTSTR)sRev, pLogEntry->m_CommitHash,\r
(LPCTSTR)sAuthor, (LPCTSTR)pLogEntry->m_AuthorName,\r
- (LPCTSTR)sDate, (LPCTSTR)pLogEntry->m_AuthorDate.Format(_T("%Y-%m-%d %H:%M")),\r
+ (LPCTSTR)sDate, (LPCTSTR)CAppUtils::FormatDateAndTime( pLogEntry->m_AuthorDate, m_DateFormat ),\r
(LPCTSTR)sMessage, pLogEntry->m_Subject+_T("\r\n")+pLogEntry->m_Body,\r
(LPCTSTR)sPaths);\r
sClipdata += sLogCopyText;\r
\r
this->m_arShownList.RemoveAll();\r
\r
- for(int i=0;i<m_logEntries.size();i++)\r
+ for(unsigned int i=0;i<m_logEntries.size();i++)\r
{\r
m_logEntries[i].m_IsFull=TRUE;\r
this->m_arShownList.Add(&m_logEntries[i]);\r
ClearText();\r
\r
this->m_logEntries.ClearAll();\r
+\r
+ m_LogCache.FetchCacheIndex(g_Git.m_CurrentDir);\r
+\r
CTGitPath *path;\r
if(this->m_Path.IsEmpty())\r
path=NULL;\r
else\r
path=&this->m_Path;\r
\r
- this->m_logEntries.ParserShortLog(path,-1);\r
+ CString hash;\r
+ int mask;\r
+ mask = CGit::LOG_INFO_ONLY_HASH | CGit::LOG_INFO_BOUNDARY;\r
+// if(this->m_bAllBranch)\r
+ mask |= m_ShowMask;\r
+\r
+ this->m_logEntries.ParserShortLog(path,hash,-1,mask);\r
+ \r
\r
//this->m_logEntries.ParserFromLog();\r
- SetItemCountEx(this->m_logEntries.size());\r
+ if(IsInWorkingThread())\r
+ PostMessage(LVM_SETITEMCOUNT, (WPARAM) this->m_logEntries.size(),(LPARAM) LVSICF_NOINVALIDATEALL);\r
+ else\r
+ SetItemCountEx(this->m_logEntries.size());\r
\r
this->m_arShownList.RemoveAll();\r
\r
- for(int i=0;i<m_logEntries.size();i++)\r
+ for(unsigned int i=0;i<m_logEntries.size();i++)\r
this->m_arShownList.Add(&m_logEntries[i]);\r
\r
return 0;\r
DiffSelectedRevWithPrevious();\r
}\r
\r
-int CGitLogListBase::FetchLogAsync(CALLBACK_PROCESS *proc,void * data)\r
+int CGitLogListBase::FetchLogAsync(void * data)\r
{\r
- m_ProcCallBack=proc;\r
m_ProcData=data;\r
-\r
+ m_bExitThread=FALSE;\r
InterlockedExchange(&m_bThreadRunning, TRUE);\r
InterlockedExchange(&m_bNoDispUpdates, TRUE);\r
- if (AfxBeginThread(LogThreadEntry, this)==NULL)\r
+ m_LoadingThread = AfxBeginThread(LogThreadEntry, this);\r
+ if (m_LoadingThread ==NULL)\r
{\r
InterlockedExchange(&m_bThreadRunning, FALSE);\r
InterlockedExchange(&m_bNoDispUpdates, FALSE);\r
//CTime time;\r
oldest=CTime::GetCurrentTime();\r
latest=CTime(1971,1,2,0,0,0);\r
- for(int i=0;i<m_logEntries.size();i++)\r
+ for(unsigned int i=0;i<m_logEntries.size();i++)\r
{\r
if(m_logEntries[i].m_AuthorDate.GetTime() < oldest.GetTime())\r
oldest = m_logEntries[i].m_AuthorDate.GetTime();\r
UINT CGitLogListBase::LogThread()\r
{\r
\r
- if(m_ProcCallBack)\r
- m_ProcCallBack(m_ProcData,GITLOG_START);\r
+// if(m_ProcCallBack)\r
+// m_ProcCallBack(m_ProcData,GITLOG_START);\r
+ ::PostMessage(this->GetParent()->m_hWnd,MSG_LOAD_PERCENTAGE,(WPARAM) GITLOG_START,0);\r
\r
InterlockedExchange(&m_bThreadRunning, TRUE);\r
InterlockedExchange(&m_bNoDispUpdates, TRUE);\r
//disable the "Get All" button while we're receiving\r
//log messages.\r
\r
- CString temp;\r
- temp.LoadString(IDS_PROGRESSWAIT);\r
- ShowText(temp, true);\r
-\r
FillGitShortLog();\r
\r
- \r
-\r
+ if(this->m_bExitThread)\r
+ return 0;\r
+#if 0\r
RedrawItems(0, m_arShownList.GetCount());\r
- SetRedraw(false);\r
- ResizeAllListCtrlCols();\r
- SetRedraw(true);\r
+// SetRedraw(false);\r
+// ResizeAllListCtrlCols();\r
+// SetRedraw(true);\r
\r
if ( m_pStoreSelection )\r
{\r
SetItemState(0, LVIS_SELECTED, LVIS_SELECTED);\r
}\r
}\r
+#endif\r
InterlockedExchange(&m_bNoDispUpdates, FALSE);\r
\r
- int index=0;\r
- int updated=0;\r
+ unsigned int updated=0;\r
int percent=0;\r
+ CRect rect;\r
while(1)\r
{\r
- for(int i=0;i<m_logEntries.size();i++)\r
+ for(unsigned int i=0;i<m_logEntries.size();i++)\r
{\r
- if(!m_logEntries.FetchFullInfo(i))\r
+ if(m_LogCache.GetCacheData(m_logEntries[i]))\r
+ {\r
+ if(!m_logEntries.FetchFullInfo(i))\r
+ {\r
+ updated++;\r
+ }\r
+ m_LogCache.AddCacheEntry(m_logEntries[i]);\r
+\r
+ }else\r
{\r
updated++;\r
+ InterlockedExchange(&m_logEntries[i].m_IsUpdateing,FALSE);\r
+ InterlockedExchange(&m_logEntries[i].m_IsFull,TRUE);\r
}\r
\r
+ ::PostMessage(m_hWnd,MSG_LOADED,(WPARAM)i,0);\r
+\r
+ if(m_bExitThread)\r
+ return 0;\r
+\r
percent=updated*98/m_logEntries.size() + GITLOG_START+1;\r
if(percent == GITLOG_END)\r
- percent == GITLOG_END -1;\r
+ percent = GITLOG_END -1;\r
+ \r
+ ::PostMessage(this->GetParent()->m_hWnd,MSG_LOAD_PERCENTAGE,(WPARAM) percent,0);\r
+\r
\r
- if(m_ProcCallBack)\r
- m_ProcCallBack(m_ProcData,percent);\r
}\r
if(updated==m_logEntries.size())\r
break;\r
// make sure the filter is applied (if any) now, after we refreshed/fetched\r
// the log messages\r
\r
- \r
-\r
- if(m_ProcCallBack)\r
- m_ProcCallBack(m_ProcData,GITLOG_END);\r
+ ::PostMessage(this->GetParent()->m_hWnd,MSG_LOAD_PERCENTAGE,(WPARAM) GITLOG_END,0);\r
\r
InterlockedExchange(&m_bThreadRunning, FALSE);\r
\r
//ResizeAllListCtrlCols();\r
SetRedraw(true);\r
Invalidate();\r
+\r
}\r
void CGitLogListBase::RemoveFilter()\r
{\r
DeleteAllItems();\r
SetItemCountEx(ShownCountWithStopped());\r
RedrawItems(0, ShownCountWithStopped());\r
- SetRedraw(false);\r
- ResizeAllListCtrlCols();\r
- SetRedraw(true);\r
+// SetRedraw(false);\r
+// ResizeAllListCtrlCols();\r
+// SetRedraw(true);\r
\r
InterlockedExchange(&m_bNoDispUpdates, FALSE);\r
}\r
m_logEntries.m_FirstFreeLane=0;\r
m_logEntries.m_Lns.clear();\r
\r
-}
\ No newline at end of file
+}\r
+\r
+void CGitLogListBase::OnDestroy()\r
+{\r
+ // save the column widths to the registry\r
+ SaveColumnWidths();\r
+\r
+ if(this->m_bThreadRunning)\r
+ {\r
+ this->m_bExitThread=true;\r
+ DWORD ret =::WaitForSingleObject(m_LoadingThread->m_hThread,20000);\r
+ if(ret == WAIT_TIMEOUT)\r
+ TerminateThread();\r
+ }\r
+ while(m_LogCache.SaveCache())\r
+ {\r
+ if(CMessageBox::Show(NULL,_T("Cannot Save Log Cache to Disk. To retry click yes. To give up click no."),_T("TortoiseGit"),\r
+ MB_YESNO) == IDNO)\r
+ break;\r
+ }\r
+ CHintListCtrl::OnDestroy();\r
+}\r
+\r
+LRESULT CGitLogListBase::OnLoad(WPARAM wParam,LPARAM lParam)\r
+{\r
+ CRect rect;\r
+ int i=(int)wParam;\r
+ this->GetItemRect(i,&rect,LVIR_BOUNDS);\r
+ this->InvalidateRect(rect);\r
+ return 0;\r
+}\r
+\r
+/**\r
+ * Save column widths to the registry\r
+ */\r
+void CGitLogListBase::SaveColumnWidths()\r
+{\r
+ CHeaderCtrl* pHdrCtrl = (CHeaderCtrl*)(GetDlgItem(0));\r
+ if (pHdrCtrl)\r
+ {\r
+ int numcols = pHdrCtrl->GetItemCount();\r
+ for (int col = 0; col < numcols; col++)\r
+ {\r
+ int width = GetColumnWidth( col );\r
+ CString regentry;\r
+ regentry.Format( _T("Software\\TortoiseGit\\log\\ColWidth%d"), col);\r
+ CRegDWORD regwidth(regentry, 0);\r
+ regwidth = width; // this writes it to reg\r
+ }\r
+ }\r
+}\r