, m_bStrictStopped(false)\r
, m_pStoreSelection(NULL)\r
, m_nSelectedFilter(LOGFILTER_ALL)\r
+ , m_bVista(false)\r
+ , m_bShowWC(false)\r
+ , m_logEntries(&m_LogCache)\r
{\r
// use the default GUI font, create a copy of it and\r
// change the copy to BOLD (leave the rest of the font\r
\r
m_IsIDReplaceAction=FALSE;\r
\r
- m_wcRev.m_CommitHash=GIT_REV_ZERO;\r
- m_wcRev.m_Subject=_T("Working Copy");\r
+ this->m_critSec.Init();\r
+ m_wcRev.m_CommitHash.Empty();\r
+ m_wcRev.m_Subject=_T("Working dir changes");\r
+ m_wcRev.m_ParentHash.clear();\r
+ m_wcRev.m_Mark=_T('-');\r
+ m_wcRev.m_IsUpdateing=FALSE;\r
+ m_wcRev.m_IsFull = TRUE;\r
\r
m_hModifiedIcon = (HICON)LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(IDI_ACTIONMODIFIED), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE);\r
m_hReplacedIcon = (HICON)LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(IDI_ACTIONREPLACED), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE);\r
m_ContextMenuMask &= ~GetContextMenuBit(ID_REBASE_SQUASH);\r
m_ContextMenuMask &= ~GetContextMenuBit(ID_REBASE_EDIT);\r
m_ContextMenuMask &= ~GetContextMenuBit(ID_REBASE_SKIP);\r
+\r
+ OSVERSIONINFOEX inf;\r
+ SecureZeroMemory(&inf, sizeof(OSVERSIONINFOEX));\r
+ inf.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);\r
+ GetVersionEx((OSVERSIONINFO *)&inf);\r
+ WORD fullver = MAKEWORD(inf.dwMinorVersion, inf.dwMajorVersion);\r
+ m_bVista = (fullver >= 0x0600);\r
+\r
+ m_ColumnRegKey=_T("log");\r
}\r
\r
CGitLogListBase::~CGitLogListBase()\r
ON_WM_CREATE()\r
ON_WM_DESTROY()\r
ON_MESSAGE(MSG_LOADED,OnLoad)\r
+ ON_WM_MEASUREITEM()\r
+ ON_WM_MEASUREITEM_REFLECT()\r
END_MESSAGE_MAP()\r
\r
+void CGitLogListBase::OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct)\r
+{\r
+ // TODO: ÔÚ´ËÌí¼ÓÏûÏ¢´¦Àí³ÌÐò´úÂëºÍ/»òµ÷ÓÃĬÈÏÖµ\r
+\r
+ CListCtrl::OnMeasureItem(nIDCtl, lpMeasureItemStruct);\r
+}\r
+\r
+void CGitLogListBase::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct)\r
+{\r
+ //if (m_nRowHeight>0)\r
+ {\r
+ lpMeasureItemStruct->itemHeight = 50;\r
+ }\r
+}\r
+\r
int CGitLogListBase:: OnCreate(LPCREATESTRUCT lpCreateStruct)\r
{\r
PreSubclassWindow();\r
{\r
SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_SUBITEMIMAGES);\r
// load the icons for the action columns\r
- m_Theme.SetWindowTheme(GetSafeHwnd(), L"Explorer", NULL);\r
+// m_Theme.Open(m_hWnd, L"ListView");\r
+ m_Theme.Open(m_hWnd, L"Explorer::ListView;ListView");\r
+ m_Theme.SetWindowTheme(m_hWnd, L"Explorer", NULL);\r
CHintListCtrl::PreSubclassWindow();\r
}\r
\r
{\r
CString temp;\r
\r
- int c = ((CHeaderCtrl*)(GetDlgItem(0)))->GetItemCount()-1;\r
+ int c = GetHeaderCtrl()->GetItemCount()-1;\r
\r
while (c>=0)\r
DeleteColumn(c--);\r
{\r
// get width for this col last time from registry\r
CString regentry;\r
- regentry.Format( _T("Software\\TortoiseGit\\log\\ColWidth%d"), col);\r
+ regentry.Format( _T("Software\\TortoiseGit\\%s\\ColWidth%d"),m_ColumnRegKey, col);\r
CRegDWORD regwidth(regentry, 0);\r
int cx = regwidth;\r
if ( cx == 0 )\r
\r
BOOL CGitLogListBase::GetShortName(CString ref, CString &shortname,CString prefix)\r
{\r
- TRACE(_T("%s %s\r\n"),ref,prefix);\r
+ //TRACE(_T("%s %s\r\n"),ref,prefix);\r
if(ref.Left(prefix.GetLength()) == prefix)\r
{\r
shortname = ref.Right(ref.GetLength()-prefix.GetLength());\r
}\r
return FALSE;\r
}\r
+\r
void CGitLogListBase::FillBackGround(HDC hdc, int Index,CRect &rect)\r
{ \r
// HBRUSH brush;\r
GetItem(&rItem);\r
\r
GitRev* pLogEntry = (GitRev*)m_arShownList.GetAt(Index);\r
+ HBRUSH brush = NULL;\r
\r
+ \r
if (m_Theme.IsAppThemed() && m_bVista)\r
{\r
- m_Theme.Open(m_hWnd, L"Explorer");\r
int state = LISS_NORMAL;\r
if (rItem.state & LVIS_SELECTED)\r
{\r
}\r
else\r
{\r
-#if 0\r
- if (pLogEntry->bCopiedSelf)\r
- {\r
- // unfortunately, the pLVCD->nmcd.uItemState does not contain valid\r
- // information at this drawing stage. But we can check the whether the\r
- // previous stage changed the background color of the item\r
- if (pLVCD->clrTextBk == GetSysColor(COLOR_MENU))\r
- {\r
- HBRUSH brush;\r
- brush = ::CreateSolidBrush(::GetSysColor(COLOR_MENU));\r
- if (brush)\r
- {\r
- ::FillRect(pLVCD->nmcd.hdc, &rect, brush);\r
- ::DeleteObject(brush);\r
- }\r
- }\r
- }\r
-#endif\r
+ if(pLogEntry->m_Action&CTGitPath::LOGACTIONS_REBASE_SQUASH)\r
+ brush = ::CreateSolidBrush(RGB(156,156,156));\r
+ else if(pLogEntry->m_Action&CTGitPath::LOGACTIONS_REBASE_EDIT)\r
+ brush = ::CreateSolidBrush(RGB(200,200,128));\r
+ }\r
+\r
+ if (brush != NULL)\r
+ {\r
+ ::FillRect(hdc, &rect, brush);\r
+ ::DeleteObject(brush);\r
}\r
+ else\r
+ {\r
+ if (m_Theme.IsBackgroundPartiallyTransparent(LVP_LISTITEM, state))\r
+ m_Theme.DrawParentBackground(m_hWnd, hdc, &rect);\r
\r
- if (m_Theme.IsBackgroundPartiallyTransparent(LVP_LISTDETAIL, state))\r
- m_Theme.DrawParentBackground(m_hWnd, hdc, &rect);\r
+ CRect rectDraw = rect;\r
+ if(rItem.state & LVIS_SELECTED)\r
+ rectDraw.InflateRect(1,0);\r
+ else\r
+ rectDraw.InflateRect(1,1);\r
\r
- m_Theme.DrawBackground(hdc, LVP_LISTDETAIL, state, &rect, NULL);\r
+ m_Theme.DrawBackground(hdc, LVP_LISTITEM, state, rectDraw, &rect);\r
+ }\r
}\r
else\r
{\r
- HBRUSH brush;\r
+ \r
if (rItem.state & LVIS_SELECTED)\r
{\r
if (::GetFocus() == m_hWnd)\r
brush = ::CreateSolidBrush(RGB(156,156,156));\r
else if(pLogEntry->m_Action&CTGitPath::LOGACTIONS_REBASE_EDIT)\r
brush = ::CreateSolidBrush(RGB(200,200,128));\r
- else \r
+ else\r
brush = ::CreateSolidBrush(::GetSysColor(COLOR_WINDOW));\r
}\r
if (brush == NULL)\r
str=m_HashMap[data->m_CommitHash][i];\r
\r
CString shortname;\r
- HBRUSH brush=0;\r
- shortname=_T("");\r
+ HBRUSH brush = 0;\r
+ shortname = _T("");\r
+ COLORREF colRef = 0;\r
+\r
+ //Determine label color\r
if(GetShortName(str,shortname,_T("refs/heads/")))\r
{\r
if( shortname == m_CurrentBranch )\r
- brush = ::CreateSolidBrush(m_Colors.GetColor(CColors::CurrentBranch));\r
+ colRef = m_Colors.GetColor(CColors::CurrentBranch);\r
else\r
- brush = ::CreateSolidBrush(m_Colors.GetColor(CColors::LocalBranch));\r
+ colRef = m_Colors.GetColor(CColors::LocalBranch);\r
\r
}else if(GetShortName(str,shortname,_T("refs/remotes/")))\r
{\r
- brush = ::CreateSolidBrush(m_Colors.GetColor(CColors::RemoteBranch));\r
+ colRef = m_Colors.GetColor(CColors::RemoteBranch);\r
}\r
else if(GetShortName(str,shortname,_T("refs/tags/")))\r
{\r
- brush = ::CreateSolidBrush(m_Colors.GetColor(CColors::Tag));\r
+ colRef = m_Colors.GetColor(CColors::Tag);\r
+ }\r
+ else if(GetShortName(str,shortname,_T("refs/stash")))\r
+ {\r
+ colRef = m_Colors.GetColor(CColors::Stash);\r
+ shortname=_T("stash");\r
}\r
\r
+ //When row selected, ajust label color\r
+ if (!(m_Theme.IsAppThemed() && m_bVista))\r
+ if (rItem.state & LVIS_SELECTED)\r
+ colRef = CColors::MixColors(colRef, ::GetSysColor(COLOR_HIGHLIGHT), 150);\r
+\r
+ brush = ::CreateSolidBrush(colRef);\r
+ \r
+\r
if(!shortname.IsEmpty())\r
{\r
SIZE size;\r
GetTextExtentPoint32(hdc, shortname,shortname.GetLength(),&size);\r
\r
rt.SetRect(rt.left,rt.top,rt.left+size.cx,rt.bottom);\r
- rt.right+=4;\r
+ rt.right+=8;\r
+\r
+ //Fill interior of ref label\r
::FillRect(hdc, &rt, brush);\r
- if (rItem.state & LVIS_SELECTED)\r
+\r
+ //Draw edge of label\r
+ CDC W_Dc;\r
+ W_Dc.Attach(hdc);\r
+\r
+ CRect rectEdge = rt;\r
+\r
+ W_Dc.Draw3dRect(rectEdge, m_Colors.Lighten(colRef,100), m_Colors.Darken(colRef,100));\r
+ rectEdge.DeflateRect(1,1);\r
+ W_Dc.Draw3dRect(rectEdge, m_Colors.Lighten(colRef,50), m_Colors.Darken(colRef,50));\r
+\r
+ W_Dc.Detach();\r
+\r
+ //Draw text inside label\r
+ if (m_Theme.IsAppThemed() && m_bVista)\r
{\r
- COLORREF clrOld = ::SetTextColor(hdc,::GetSysColor(COLOR_HIGHLIGHTTEXT)); \r
- ::DrawText(hdc,shortname,shortname.GetLength(),&rt,DT_CENTER);\r
- ::SetTextColor(hdc,clrOld); \r
- }else\r
+ int txtState = LISS_NORMAL;\r
+ if (rItem.state & LVIS_SELECTED)\r
+ txtState = LISS_SELECTED;\r
+\r
+ m_Theme.DrawText(hdc, LVP_LISTITEM, txtState, shortname, -1, DT_CENTER | DT_SINGLELINE | DT_VCENTER, 0, &rt);\r
+ }\r
+ else\r
{\r
- ::DrawText(hdc,shortname,shortname.GetLength(),&rt,DT_CENTER);\r
+ if (rItem.state & LVIS_SELECTED)\r
+ {\r
+ COLORREF clrNew = ::GetSysColor(COLOR_HIGHLIGHTTEXT);\r
+ COLORREF clrOld = ::SetTextColor(hdc,clrNew); \r
+ ::DrawText(hdc,shortname,shortname.GetLength(),&rt,DT_CENTER | DT_SINGLELINE | DT_VCENTER);\r
+ ::SetTextColor(hdc,clrOld);\r
+ }else\r
+ {\r
+ ::DrawText(hdc,shortname,shortname.GetLength(),&rt,DT_CENTER | DT_SINGLELINE | DT_VCENTER);\r
+ }\r
}\r
\r
\r
- ::MoveToEx(hdc,rt.left,rt.top,NULL);\r
- ::LineTo(hdc,rt.right,rt.top);\r
- ::LineTo(hdc,rt.right,rt.bottom);\r
- ::LineTo(hdc,rt.left,rt.bottom);\r
- ::LineTo(hdc,rt.left,rt.top);\r
+ //::MoveToEx(hdc,rt.left,rt.top,NULL);\r
+ //::LineTo(hdc,rt.right,rt.top);\r
+ //::LineTo(hdc,rt.right,rt.bottom);\r
+ //::LineTo(hdc,rt.left,rt.bottom);\r
+ //::LineTo(hdc,rt.left,rt.top);\r
+\r
\r
- rt.left=rt.right+3;\r
+ rt.left=rt.right+1;\r
}\r
if(brush)\r
::DeleteObject(brush);\r
} \r
rt.right=rect.right;\r
\r
- if (rItem.state & LVIS_SELECTED)\r
+ if (m_Theme.IsAppThemed() && m_bVista)\r
{\r
- COLORREF clrOld = ::SetTextColor(hdc,::GetSysColor(COLOR_HIGHLIGHTTEXT)); \r
- ::DrawText(hdc,data->m_Subject,data->m_Subject.GetLength(),&rt,DT_LEFT);\r
- ::SetTextColor(hdc,clrOld); \r
- }else\r
+ int txtState = LISS_NORMAL;\r
+ if (rItem.state & LVIS_SELECTED)\r
+ txtState = LISS_SELECTED;\r
+\r
+ m_Theme.DrawText(hdc, LVP_LISTITEM, txtState, data->m_Subject, -1, DT_LEFT | DT_SINGLELINE | DT_VCENTER, 0, &rt);\r
+ }\r
+ else\r
{\r
- ::DrawText(hdc,data->m_Subject,data->m_Subject.GetLength(),&rt,DT_LEFT);\r
+ if (rItem.state & LVIS_SELECTED)\r
+ {\r
+ COLORREF clrOld = ::SetTextColor(hdc,::GetSysColor(COLOR_HIGHLIGHTTEXT)); \r
+ ::DrawText(hdc,data->m_Subject,data->m_Subject.GetLength(),&rt,DT_LEFT | DT_SINGLELINE | DT_VCENTER);\r
+ ::SetTextColor(hdc,clrOld); \r
+ }else\r
+ {\r
+ ::DrawText(hdc,data->m_Subject,data->m_Subject.GetLength(),&rt,DT_LEFT | DT_SINGLELINE | DT_VCENTER);\r
+ }\r
}\r
- \r
}\r
\r
+static COLORREF blend(const COLORREF& col1, const COLORREF& col2, int amount = 128) {\r
+\r
+ // Returns ((256 - amount)*col1 + amount*col2) / 256;\r
+ return RGB(((256 - amount)*GetRValue(col1) + amount*GetRValue(col2) ) / 256,\r
+ ((256 - amount)*GetGValue(col1) + amount*GetGValue(col2) ) / 256,\r
+ ((256 - amount)*GetBValue(col1) + amount*GetBValue(col2) ) / 256);\r
+}\r
+\r
+Gdiplus::Color GetGdiColor(COLORREF col)\r
+{\r
+ return Gdiplus::Color(GetRValue(col),GetGValue(col),GetBValue(col));\r
+}\r
void CGitLogListBase::paintGraphLane(HDC hdc, int laneHeight,int type, int x1, int x2,\r
- const COLORREF& col,int top\r
+ const COLORREF& col,const COLORREF& activeColor, int top\r
) \r
{\r
int h = laneHeight / 2;\r
#define P_270 m , 2 * h+top\r
#define R_CENTER m - r, h - r+top, m - r+d, h - r+top+d\r
\r
+\r
+ #define DELTA_UR_B 2*(x1 - m), 2*h +top \r
+ #define DELTA_UR_E 0*16, 90*16 +top // -,\r
+\r
+ #define DELTA_DR_B 2*(x1 - m), 2*-h +top\r
+ #define DELTA_DR_E 270*16, 90*16 +top // -'\r
+\r
+ #define DELTA_UL_B 2*(x2 - m), 2*h +top\r
+ #define DELTA_UL_E 90*16, 90*16 +top // ,-\r
+\r
+ #define DELTA_DL_B 2*(x2 - m),2*-h +top \r
+ #define DELTA_DL_E 180*16, 90*16 // '-\r
+\r
+ #define CENTER_UR x1, 2*h, 225\r
+ #define CENTER_DR x1, 0 , 135\r
+ #define CENTER_UL x2, 2*h, 315\r
+ #define CENTER_DL x2, 0 , 45\r
+\r
+\r
+ Gdiplus::Graphics graphics( hdc );\r
+\r
+ // arc\r
+ switch (type) {\r
+ case Lanes::JOIN:\r
+ case Lanes::JOIN_R:\r
+ case Lanes::HEAD:\r
+ case Lanes::HEAD_R: \r
+ {\r
+ Gdiplus::LinearGradientBrush gradient(\r
+ Gdiplus::Point(x1-2, h+top-2),\r
+ Gdiplus::Point(P_270),\r
+ GetGdiColor(activeColor),GetGdiColor(col));\r
+\r
+ \r
+ Gdiplus::Pen mypen(&gradient,2);\r
+ //Gdiplus::Pen mypen(Gdiplus::Color(0,0,0),2);\r
+ \r
+ //graphics.DrawRectangle(&mypen,x1-(x2-x1)/2,top+h, x2-x1,laneHeight);\r
+ graphics.DrawArc(&mypen,x1-(x2-x1)/2-1,top+h-1, x2-x1+1,laneHeight+1,270,90);\r
+ //graphics.DrawLine(&mypen,x1-1,h+top,P_270);\r
+\r
+ break;\r
+ }\r
+ case Lanes::JOIN_L: \r
+ {\r
+ \r
+ Gdiplus::Pen mypen(Gdiplus::Color(0,0,0),2);\r
+\r
+ \r
+ graphics.DrawArc(&mypen,x1,top+h, x2-x1,laneHeight,270,90);\r
+\r
+ break;\r
+ }\r
+ case Lanes::TAIL:\r
+ case Lanes::TAIL_R: \r
+ {\r
+ \r
+ Gdiplus::LinearGradientBrush gradient(\r
+ Gdiplus::Point(x1-2, h+top-2),\r
+ Gdiplus::Point(P_90),\r
+ GetGdiColor(activeColor),GetGdiColor(col));\r
+\r
+ \r
+ Gdiplus::Pen mypen(&gradient,2);\r
+\r
+ graphics.DrawArc(&mypen,x1-(x2-x1)/2-1,top-h-1, x2-x1+1,laneHeight+1,0,90);\r
+\r
+\r
+#if 0\r
+ QConicalGradient gradient(CENTER_DR);\r
+ gradient.setColorAt(0.375, activeCol);\r
+ gradient.setColorAt(0.625, col);\r
+ myPen.setBrush(gradient);\r
+ p->setPen(myPen);\r
+ p->drawArc(P_CENTER, DELTA_DR);\r
+#endif\r
+ break;\r
+ }\r
+ default:\r
+ break;\r
+ }\r
+\r
+\r
//static QPen myPen(Qt::black, 2); // fast path here\r
CPen pen;\r
pen.CreatePen(PS_SOLID,2,col);\r
//myPen.setColor(col);\r
HPEN oldpen=(HPEN)::SelectObject(hdc,(HPEN)pen);\r
\r
+ Gdiplus::Pen myPen(GetGdiColor(col),2);\r
+\r
//p->setPen(myPen);\r
\r
// vertical line\r
case Lanes::JOIN:\r
case Lanes::JOIN_R:\r
case Lanes::JOIN_L:\r
- DrawLine(hdc,P_90,P_270);\r
+ case Lanes::CROSS:\r
+ //DrawLine(hdc,P_90,P_270);\r
+ graphics.DrawLine(&myPen,P_90,P_270);\r
//p->drawLine(P_90, P_270);\r
break;\r
- case Lanes::HEAD:\r
- case Lanes::HEAD_R:\r
case Lanes::HEAD_L:\r
case Lanes::BRANCH:\r
- DrawLine(hdc,P_CENTER,P_270);\r
+ //DrawLine(hdc,P_CENTER,P_270);\r
+ graphics.DrawLine(&myPen,P_CENTER,P_270);\r
//p->drawLine(P_CENTER, P_270);\r
break;\r
- case Lanes::TAIL:\r
- case Lanes::TAIL_R:\r
case Lanes::TAIL_L:\r
case Lanes::INITIAL:\r
case Lanes::BOUNDARY:\r
case Lanes::BOUNDARY_C:\r
case Lanes::BOUNDARY_R:\r
case Lanes::BOUNDARY_L:\r
- DrawLine(hdc,P_90, P_CENTER);\r
+ //DrawLine(hdc,P_90, P_CENTER);\r
+ graphics.DrawLine(&myPen,P_90,P_CENTER);\r
//p->drawLine(P_90, P_CENTER);\r
break;\r
default:\r
break;\r
}\r
\r
+ myPen.SetColor(GetGdiColor(activeColor));\r
+\r
// horizontal line\r
switch (type) {\r
case Lanes::MERGE_FORK:\r
case Lanes::CROSS:\r
case Lanes::CROSS_EMPTY:\r
case Lanes::BOUNDARY_C:\r
- DrawLine(hdc,P_180,P_0);\r
+ //DrawLine(hdc,P_180,P_0);\r
+ graphics.DrawLine(&myPen,P_180,P_0);\r
//p->drawLine(P_180, P_0);\r
break;\r
case Lanes::MERGE_FORK_R:\r
- case Lanes::JOIN_R:\r
- case Lanes::HEAD_R:\r
- case Lanes::TAIL_R:\r
case Lanes::BOUNDARY_R:\r
- DrawLine(hdc,P_180,P_CENTER);\r
+ //DrawLine(hdc,P_180,P_CENTER);\r
+ graphics.DrawLine(&myPen,P_180,P_CENTER);\r
//p->drawLine(P_180, P_CENTER);\r
break;\r
case Lanes::MERGE_FORK_L:\r
- case Lanes::JOIN_L:\r
case Lanes::HEAD_L:\r
case Lanes::TAIL_L:\r
case Lanes::BOUNDARY_L:\r
- DrawLine(hdc,P_CENTER,P_0);\r
+ //DrawLine(hdc,P_CENTER,P_0);\r
+ graphics.DrawLine(&myPen,P_CENTER,P_0);\r
//p->drawLine(P_CENTER, P_0);\r
break;\r
default:\r
//todo unfinished\r
// return;\r
GitRev* data = (GitRev*)m_arShownList.GetAt(index);\r
+ if(data->m_CommitHash.IsEmpty())\r
+ return;\r
+\r
CRect rt=rect;\r
LVITEM rItem;\r
SecureZeroMemory(&rItem, sizeof(LVITEM));\r
\r
std::vector<int>& lanes=data->m_Lanes;\r
UINT laneNum = lanes.size();\r
- UINT mergeLane = 0;\r
+ UINT activeLane = 0;\r
for (UINT i = 0; i < laneNum; i++)\r
if (Lanes::isMerge(lanes[i])) {\r
- mergeLane = i;\r
+ activeLane = i;\r
break;\r
}\r
\r
int x1 = 0, x2 = 0;\r
int maxWidth = rect.Width();\r
int lw = 3 * rect.Height() / 4; //laneWidth() \r
+\r
+ COLORREF activeColor = m_LineColors[activeLane % Lanes::COLORS_NUM];\r
+ //if (opt.state & QStyle::State_Selected)\r
+ // activeColor = blend(activeColor, opt.palette.highlightedText().color(), 208);\r
+ \r
+\r
+ for (unsigned int i = 0; i < laneNum && x2 < maxWidth; i++) \r
+ {\r
+\r
+ x1 = x2;\r
+ x2 += lw;\r
+\r
+ int ln = lanes[i];\r
+ if (ln == Lanes::EMPTY)\r
+ continue;\r
+\r
+ COLORREF color = i == activeLane ? activeColor : m_LineColors[i % Lanes::COLORS_NUM];\r
+ paintGraphLane(hdc, rect.Height(),ln, x1+rect.left, x2+rect.left, color,activeColor, rect.top);\r
+ }\r
+\r
+#if 0\r
for (UINT i = 0; i < laneNum && x2 < maxWidth; i++) {\r
\r
x1 = x2;\r
continue;\r
\r
UINT col = ( Lanes:: isHead(ln) ||Lanes:: isTail(ln) || Lanes::isJoin(ln)\r
- || ln ==Lanes:: CROSS_EMPTY) ? mergeLane : i;\r
+ || ln ==Lanes:: CROSS_EMPTY) ? activeLane : i;\r
\r
if (ln == Lanes::CROSS) {\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
+ paintGraphLane(hdc, rect.Height(),Lanes::CROSS, x1, x2, m_LineColors[activeLane % Lanes::COLORS_NUM],rect.top);\r
} else\r
paintGraphLane(hdc, rect.Height(),ln, x1, x2, m_LineColors[col % Lanes::COLORS_NUM],rect.top);\r
}\r
+#endif\r
\r
- TRACE(_T("index %d %d\r\n"),index,data->m_Lanes.size());\r
}\r
\r
void CGitLogListBase::OnNMCustomdrawLoglist(NMHDR *pNMHDR, LRESULT *pResult)\r
pLVCD->clrTextBk = RGB(156,156,156);\r
else if(data->m_Action&CTGitPath::LOGACTIONS_REBASE_EDIT)\r
pLVCD->clrTextBk = RGB(200,200,128);\r
- else \r
+ else\r
pLVCD->clrTextBk = ::GetSysColor(COLOR_WINDOW);\r
\r
if(data->m_Action&CTGitPath::LOGACTIONS_REBASE_CURRENT)\r
*pResult = CDRF_NOTIFYSUBITEMDRAW | CDRF_NEWFONT;\r
}\r
\r
- if(data->m_CommitHash == m_HeadHash)\r
+ if(data->m_CommitHash.ToString() == m_HeadHash)\r
{\r
SelectObject(pLVCD->nmcd.hdc, m_boldFont);\r
*pResult = CDRF_NOTIFYSUBITEMDRAW | CDRF_NEWFONT;\r
\r
// if ((data->childStackDepth)||(m_mergedRevs.find(data->Rev) != m_mergedRevs.end()))\r
// crText = GetSysColor(COLOR_GRAYTEXT);\r
-// if (data->Rev == m_wcRev)\r
-// {\r
-// SelectObject(pLVCD->nmcd.hdc, m_boldFont);\r
+// \r
+ if (data->m_CommitHash.IsEmpty())\r
+ {\r
+ //crText = GetSysColor(RGB(200,200,0));\r
+ //SelectObject(pLVCD->nmcd.hdc, m_boldFont);\r
// We changed the font, so we're returning CDRF_NEWFONT. This\r
// tells the control to recalculate the extent of the text.\r
-// *pResult = CDRF_NOTIFYSUBITEMDRAW | CDRF_NEWFONT;\r
-// }\r
+ *pResult = CDRF_NOTIFYSUBITEMDRAW | CDRF_NEWFONT;\r
+ }\r
}\r
}\r
if (m_arShownList.GetCount() == (INT_PTR)pLVCD->nmcd.dwItemSpec)\r
{\r
CRect rect;\r
GetSubItemRect(pLVCD->nmcd.dwItemSpec, pLVCD->iSubItem, LVIR_BOUNDS, rect);\r
+ if(pLVCD->iSubItem == 0)\r
+ {\r
+ CRect second;\r
+ GetSubItemRect(pLVCD->nmcd.dwItemSpec, pLVCD->iSubItem+1, LVIR_BOUNDS, second);\r
+ rect.right=second.left;\r
+ }\r
\r
+ //TRACE(_T("A Graphic left %d right %d\r\n"),rect.left,rect.right);\r
FillBackGround(pLVCD->nmcd.hdc, (INT_PTR)pLVCD->nmcd.dwItemSpec,rect);\r
- DrawGraph(pLVCD->nmcd.hdc,rect,pLVCD->nmcd.dwItemSpec);\r
+ \r
+ GitRev* data = (GitRev*)m_arShownList.GetAt(pLVCD->nmcd.dwItemSpec);\r
+ if( !data ->m_CommitHash.IsEmpty())\r
+ DrawGraph(pLVCD->nmcd.hdc,rect,pLVCD->nmcd.dwItemSpec);\r
\r
*pResult = CDRF_SKIPDEFAULT;\r
return;\r
return;\r
\r
}\r
- }\r
+\r
+ } \r
}\r
\r
if (pLVCD->iSubItem == 1)\r
GitRev* pLogEntry = reinterpret_cast<GitRev *>(m_arShownList.GetAt(pLVCD->nmcd.dwItemSpec));\r
CRect rect;\r
GetSubItemRect(pLVCD->nmcd.dwItemSpec, pLVCD->iSubItem, LVIR_BOUNDS, rect);\r
+ //TRACE(_T("Action left %d right %d\r\n"),rect.left,rect.right);\r
// Get the selected state of the\r
// item being drawn. \r
\r
lstrcpyn(pItem->pszText, (LPCTSTR)pLogEntry->m_AuthorName, pItem->cchTextMax);\r
break;\r
case this->LOGLIST_DATE: //Date\r
- if (pLogEntry)\r
+ if ( pLogEntry && (!pLogEntry->m_CommitHash.IsEmpty()) )\r
lstrcpyn(pItem->pszText,\r
CAppUtils::FormatDateAndTime( pLogEntry->m_AuthorDate, m_DateFormat, true, m_bRelativeTimes ), \r
pItem->cchTextMax);\r
}\r
//entry is selected, now show the popup menu\r
CIconMenu popup;\r
+ CIconMenu submenu;\r
if (popup.CreatePopupMenu())\r
{\r
\r
if(m_ContextMenuMask&GetContextMenuBit(ID_REBASE_PICK))\r
- popup.AppendMenuIcon(ID_REBASE_PICK, _T("Pick"), IDI_OPEN);\r
+ popup.AppendMenuIcon(ID_REBASE_PICK, IDS_REBASE_PICK, IDI_PICK);\r
\r
if(m_ContextMenuMask&GetContextMenuBit(ID_REBASE_SQUASH))\r
- popup.AppendMenuIcon(ID_REBASE_SQUASH, _T("Squash"), IDI_OPEN);\r
+ popup.AppendMenuIcon(ID_REBASE_SQUASH,IDS_REBASE_SQUASH, IDI_SQUASH);\r
\r
if(m_ContextMenuMask&GetContextMenuBit(ID_REBASE_EDIT))\r
- popup.AppendMenuIcon(ID_REBASE_EDIT, _T("Edit"), IDI_OPEN);\r
+ popup.AppendMenuIcon(ID_REBASE_EDIT, IDS_REBASE_EDIT, IDI_EDIT);\r
\r
if(m_ContextMenuMask&GetContextMenuBit(ID_REBASE_SKIP))\r
- popup.AppendMenuIcon(ID_REBASE_SKIP, _T("SKIP"), IDI_OPEN);\r
+ popup.AppendMenuIcon(ID_REBASE_SKIP, IDS_REBASE_SKIP, IDI_SKIP);\r
\r
if(m_ContextMenuMask&(GetContextMenuBit(ID_REBASE_SKIP)|GetContextMenuBit(ID_REBASE_EDIT)|\r
GetContextMenuBit(ID_REBASE_SQUASH)|GetContextMenuBit(ID_REBASE_PICK)))\r
\r
if (GetSelectedCount() == 1)\r
{\r
-#if 0\r
- if (!m_path.IsDirectory())\r
- {\r
- if (m_hasWC)\r
- {\r
- popup.AppendMenuIcon(ID_COMPARE, IDS_LOG_POPUP_COMPARE, IDI_DIFF);\r
- popup.AppendMenuIcon(ID_BLAMECOMPARE, IDS_LOG_POPUP_BLAMECOMPARE, IDI_BLAME);\r
- }\r
- popup.AppendMenuIcon(ID_GNUDIFF1, IDS_LOG_POPUP_GNUDIFF_CH, IDI_DIFF);\r
- popup.AppendMenuIcon(ID_COMPAREWITHPREVIOUS, IDS_LOG_POPUP_COMPAREWITHPREVIOUS, IDI_DIFF);\r
- popup.AppendMenu(MF_SEPARATOR, NULL);\r
- popup.AppendMenuIcon(ID_SAVEAS, IDS_LOG_POPUP_SAVE, IDI_SAVEAS);\r
- popup.AppendMenuIcon(ID_OPEN, IDS_LOG_POPUP_OPEN, IDI_OPEN);\r
- popup.AppendMenuIcon(ID_OPENWITH, IDS_LOG_POPUP_OPENWITH, IDI_OPEN);\r
- popup.AppendMenuIcon(ID_BLAME, IDS_LOG_POPUP_BLAME, IDI_BLAME);\r
- popup.AppendMenu(MF_SEPARATOR, NULL);\r
- }\r
- else\r
-#endif \r
+ \r
{\r
- if (m_hasWC)\r
+ if( !pSelLogEntry->m_CommitHash.IsEmpty())\r
{\r
if(m_ContextMenuMask&GetContextMenuBit(ID_COMPARE))\r
popup.AppendMenuIcon(ID_COMPARE, IDS_LOG_POPUP_COMPARE, IDI_DIFF);\r
// But until that's implemented, the context menu entry for\r
// this feature is commented out.\r
//popup.AppendMenu(ID_BLAMECOMPARE, IDS_LOG_POPUP_BLAMECOMPARE, IDI_BLAME);\r
+ }else\r
+ {\r
+ if(m_ContextMenuMask&GetContextMenuBit(ID_COMMIT))\r
+ popup.AppendMenuIcon(ID_COMMIT, IDS_LOG_POPUP_COMMIT, IDI_COMMIT);\r
}\r
if(m_ContextMenuMask&GetContextMenuBit(ID_GNUDIFF1))\r
popup.AppendMenuIcon(ID_GNUDIFF1, IDS_LOG_POPUP_GNUDIFF_CH, IDI_DIFF);\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
+ CString str,format;\r
+ format.LoadString(IDS_RESET_TO_THIS_FORMAT);\r
+ str.Format(format,g_Git.GetCurrentBranch());\r
\r
- if(m_ContextMenuMask&GetContextMenuBit(ID_RESET))\r
- popup.AppendMenuIcon(ID_RESET,str,IDI_REVERT);\r
+ if(!pSelLogEntry->m_CommitHash.IsEmpty())\r
+ {\r
+ if(m_ContextMenuMask&GetContextMenuBit(ID_RESET))\r
+ popup.AppendMenuIcon(ID_RESET,str,IDI_REVERT);\r
\r
- if(m_ContextMenuMask&GetContextMenuBit(ID_SWITCHTOREV))\r
- popup.AppendMenuIcon(ID_SWITCHTOREV, _T("Switch/Checkout to this") , IDI_SWITCH);\r
+ if(m_ContextMenuMask&GetContextMenuBit(ID_SWITCHTOREV))\r
+ popup.AppendMenuIcon(ID_SWITCHTOREV, IDS_SWITCH_TO_THIS , IDI_SWITCH);\r
\r
- if(m_ContextMenuMask&GetContextMenuBit(ID_CREATE_BRANCH))\r
- popup.AppendMenuIcon(ID_CREATE_BRANCH, _T("Create Branch at this version") , IDI_COPY);\r
+ if(m_ContextMenuMask&GetContextMenuBit(ID_CREATE_BRANCH))\r
+ popup.AppendMenuIcon(ID_CREATE_BRANCH, IDS_CREATE_BRANCH_AT_THIS , IDI_COPY);\r
\r
- if(m_ContextMenuMask&GetContextMenuBit(ID_CREATE_TAG))\r
- popup.AppendMenuIcon(ID_CREATE_TAG, _T("Create Tag at this version"), IDI_COPY);\r
+ if(m_ContextMenuMask&GetContextMenuBit(ID_CREATE_TAG))\r
+ popup.AppendMenuIcon(ID_CREATE_TAG,IDS_CREATE_TAG_AT_THIS , IDI_COPY);\r
+ \r
+ format.LoadString(IDS_REBASE_THIS_FORMAT);\r
+ str.Format(format,g_Git.GetCurrentBranch());\r
\r
- if(m_ContextMenuMask&GetContextMenuBit(ID_CHERRY_PICK))\r
- popup.AppendMenuIcon(ID_CHERRY_PICK, _T("Cherry Pick this version"), IDI_EXPORT);\r
+ if(pSelLogEntry->m_CommitHash != m_HeadHash)\r
+ if(m_ContextMenuMask&GetContextMenuBit(ID_REBASE_TO_VERSION))\r
+ popup.AppendMenuIcon(ID_REBASE_TO_VERSION, str , IDI_REBASE); \r
\r
- str.Format(_T("Rebase %s to this"),g_Git.GetCurrentBranch());\r
+ if(m_ContextMenuMask&GetContextMenuBit(ID_EXPORT))\r
+ popup.AppendMenuIcon(ID_EXPORT,IDS_EXPORT_TO_THIS, IDI_EXPORT); \r
+ \r
\r
- if(m_ContextMenuMask&GetContextMenuBit(ID_REBASE_TO_VERSION))\r
- popup.AppendMenuIcon(ID_REBASE_TO_VERSION, str , IDI_EXPORT); \r
+ popup.AppendMenu(MF_SEPARATOR, NULL);\r
+ }\r
\r
- if(m_ContextMenuMask&GetContextMenuBit(ID_EXPORT))\r
- popup.AppendMenuIcon(ID_EXPORT, _T("Export this version"), IDI_EXPORT); \r
- \r
+ }\r
\r
+ if(!pSelLogEntry->m_Ref.IsEmpty() && GetSelectedCount() == 1)\r
+ {\r
+ popup.AppendMenuIcon(ID_REFLOG_DEL, IDS_REFLOG_DEL, IDI_DELETE); \r
+ popup.AppendMenuIcon(ID_STASH_APPLY,IDS_MENUSTASHAPPLY, IDI_RELOCATE); \r
popup.AppendMenu(MF_SEPARATOR, NULL);\r
}\r
- else if (GetSelectedCount() >= 2)\r
+ \r
+ if (GetSelectedCount() >= 2)\r
{\r
bool bAddSeparator = false;\r
if (IsSelectionContinuous() || (GetSelectedCount() == 2))\r
bAddSeparator = true;\r
}\r
\r
- if ( IsSelectionContinuous() )\r
- {\r
- if(m_ContextMenuMask&GetContextMenuBit(ID_COMBINE_COMMIT))\r
- {\r
- CString head;\r
- head.Format(_T("HEAD~%d"),LastSelect);\r
- CString hash=g_Git.GetHash(head);\r
- hash=hash.Left(40);\r
- GitRev* pLastEntry = reinterpret_cast<GitRev*>(m_arShownList.GetAt(LastSelect));\r
- if(pLastEntry->m_CommitHash == hash)\r
- popup.AppendMenuIcon(ID_COMBINE_COMMIT,_T("Combine to one commit"),IDI_MERGE);\r
- }\r
- }\r
if (m_hasWC)\r
{\r
//popup.AppendMenuIcon(ID_REVERTREV, IDS_LOG_POPUP_REVERTREVS, IDI_REVERT);\r
if (bAddSeparator)\r
popup.AppendMenu(MF_SEPARATOR, NULL);\r
}\r
+\r
+ if ( GetSelectedCount() >0 && (!pSelLogEntry->m_CommitHash.IsEmpty()))\r
+ {\r
+ if ( IsSelectionContinuous() && GetSelectedCount() >= 2 )\r
+ {\r
+ if(m_ContextMenuMask&GetContextMenuBit(ID_COMBINE_COMMIT))\r
+ {\r
+ CString head;\r
+ int headindex;\r
+ headindex = this->GetHeadIndex();\r
+ if(headindex>=0)\r
+ {\r
+ head.Format(_T("HEAD~%d"),LastSelect-headindex);\r
+ CString hash=g_Git.GetHash(head);\r
+ hash=hash.Left(40);\r
+ GitRev* pLastEntry = reinterpret_cast<GitRev*>(m_arShownList.GetAt(LastSelect));\r
+ if(pLastEntry->m_CommitHash.ToString() == hash)\r
+ popup.AppendMenuIcon(ID_COMBINE_COMMIT,IDS_COMBINE_TO_ONE,IDI_COMBINE);\r
+ }\r
+ }\r
+ }\r
+ if(m_ContextMenuMask&GetContextMenuBit(ID_CHERRY_PICK))\r
+ popup.AppendMenuIcon(ID_CHERRY_PICK, IDS_CHERRY_PICK_VERSION, IDI_EXPORT);\r
+\r
+ if(GetSelectedCount()<=2 || (IsSelectionContinuous() && GetSelectedCount() > 0))\r
+ if(m_ContextMenuMask&GetContextMenuBit(ID_CREATE_PATCH))\r
+ popup.AppendMenuIcon(ID_CREATE_PATCH, IDS_CREATE_PATCH, IDI_PATCH);\r
+ \r
+ popup.AppendMenu(MF_SEPARATOR, NULL);\r
+ \r
+ }\r
+\r
+ \r
#if 0\r
// if ((selEntries.size() > 0)&&(bAllFromTheSameAuthor))\r
// {\r
if (GetSelectedCount() == 1)\r
{\r
if(m_ContextMenuMask&GetContextMenuBit(ID_COPYHASH))\r
- popup.AppendMenuIcon(ID_COPYHASH, _T("Copy Commit Hash"));\r
+ popup.AppendMenuIcon(ID_COPYHASH, IDS_COPY_COMMIT_HASH);\r
}\r
if (GetSelectedCount() != 0)\r
{\r
if(m_ContextMenuMask&GetContextMenuBit(ID_FINDENTRY))\r
popup.AppendMenuIcon(ID_FINDENTRY, IDS_LOG_POPUP_FIND);\r
\r
+\r
+ if (GetSelectedCount() == 1)\r
+ {\r
+ if(m_ContextMenuMask &GetContextMenuBit(ID_DELETE))\r
+ {\r
+ if( this->m_HashMap.find(pSelLogEntry->m_CommitHash) != m_HashMap.end() )\r
+ {\r
+ CString str;\r
+ str.LoadString(IDS_DELETE_BRANCHTAG);\r
+ if( m_HashMap[pSelLogEntry->m_CommitHash].size() == 1 )\r
+ {\r
+ str+=_T(" ");\r
+ str+=m_HashMap[pSelLogEntry->m_CommitHash].at(0);\r
+ popup.AppendMenuIcon(ID_DELETE,str+_T("..."),IDI_DELETE);\r
+ }\r
+ else if( m_HashMap[pSelLogEntry->m_CommitHash].size() > 1 )\r
+ {\r
+ \r
+ submenu.CreatePopupMenu();\r
+ for(int i=0;i<m_HashMap[pSelLogEntry->m_CommitHash].size();i++)\r
+ {\r
+ submenu.AppendMenuIcon(ID_DELETE+(i<<16),m_HashMap[pSelLogEntry->m_CommitHash][i]+_T("..."));\r
+ }\r
+\r
+ popup.AppendMenu(MF_BYPOSITION|MF_POPUP|MF_STRING,(UINT) submenu.m_hMenu,str); \r
+\r
+ }\r
+ \r
+ }\r
+ }\r
+ }\r
+\r
int cmd = popup.TrackPopupMenu(TPM_RETURNCMD | TPM_LEFTALIGN | TPM_NONOTIFY, point.x, point.y, this, 0);\r
// DialogEnableWindow(IDOK, FALSE);\r
// SetPromptApp(&theApp);\r
\r
void CGitLogListBase::DiffSelectedRevWithPrevious()\r
{\r
-#if 0\r
if (m_bThreadRunning)\r
return;\r
+\r
+ int FirstSelect=-1, LastSelect=-1;\r
+ POSITION pos = GetFirstSelectedItemPosition();\r
+ FirstSelect = GetNextSelectedItem(pos);\r
+ while(pos)\r
+ {\r
+ LastSelect = GetNextSelectedItem(pos);\r
+ }\r
+\r
+ ContextMenuAction(ID_COMPAREWITHPREVIOUS,FirstSelect,LastSelect);\r
+\r
+#if 0\r
UpdateLogInfoLabel();\r
int selIndex = m_LogList.GetSelectionMark();\r
if (selIndex < 0)\r
{\r
if(m_IsOldFirst)\r
{\r
- m_logEntries[m_logEntries.size()-i-1].m_IsFull=TRUE;\r
+ m_logEntries.GetGitRevAt(m_logEntries.size()-i-1).m_IsFull=TRUE;\r
this->m_arShownList.Add(&m_logEntries[m_logEntries.size()-i-1]);\r
\r
}else\r
{\r
- m_logEntries[i].m_IsFull=TRUE;\r
+ m_logEntries.GetGitRevAt(i).m_IsFull=TRUE;\r
this->m_arShownList.Add(&m_logEntries[i]);\r
}\r
}\r
\r
}\r
\r
-int CGitLogListBase::FillGitShortLog()\r
+int CGitLogListBase::BeginFetchLog()\r
{\r
ClearText();\r
\r
this->m_logEntries.ClearAll();\r
+ git_init();\r
+\r
+ this->m_LogCache.ClearAllParent();\r
\r
m_LogCache.FetchCacheIndex(g_Git.m_CurrentDir);\r
\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
+ mask |= m_ShowMask ;\r
\r
+ this->m_arShownList.RemoveAll();\r
+\r
+ if(m_bShowWC)\r
+ {\r
+ this->m_logEntries.insert(m_logEntries.begin(),this->m_wcRev.m_CommitHash);\r
+ this->m_LogCache.m_HashMap[m_wcRev.m_CommitHash]=m_wcRev;\r
+ }\r
+\r
+ CString cmd=g_Git.GetLogCmd(m_StartRef,path,-1,mask,NULL,NULL,true);\r
\r
//this->m_logEntries.ParserFromLog();\r
if(IsInWorkingThread())\r
+ {\r
PostMessage(LVM_SETITEMCOUNT, (WPARAM) this->m_logEntries.size(),(LPARAM) LVSICF_NOINVALIDATEALL);\r
+ }\r
else\r
+ {\r
SetItemCountEx(this->m_logEntries.size());\r
-\r
- this->m_arShownList.RemoveAll();\r
-\r
- for(unsigned int i=0;i<m_logEntries.size();i++)\r
+ }\r
+ \r
+ if(git_open_log(&m_DllGitLog,CUnicodeUtils::GetMulti(cmd,CP_ACP).GetBuffer()))\r
{\r
- if(this->m_IsOldFirst)\r
- {\r
- this->m_arShownList.Add(&m_logEntries[m_logEntries.size()-1-i]);\r
-\r
- }else\r
- {\r
- this->m_arShownList.Add(&m_logEntries[i]);\r
- }\r
+ return -1;\r
}\r
+\r
return 0;\r
}\r
\r
// a double click on an entry in the revision list has happened\r
*pResult = 0;\r
\r
- if (CRegDWORD(_T("Software\\TortoiseGit\\DiffByDoubleClickInLog"), FALSE))\r
- DiffSelectedRevWithPrevious();\r
+ if (CRegDWORD(_T("Software\\TortoiseGit\\DiffByDoubleClickInLog"), FALSE))\r
+ DiffSelectedRevWithPrevious();\r
}\r
\r
int CGitLogListBase::FetchLogAsync(void * data)\r
latest=CTime(1971,1,2,0,0,0);\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
+ if(m_logEntries[i].IsEmpty())\r
+ continue;\r
\r
- if(m_logEntries[i].m_AuthorDate.GetTime() > latest.GetTime())\r
- latest = m_logEntries[i].m_AuthorDate.GetTime();\r
+ if(m_logEntries.GetGitRevAt(i).m_AuthorDate.GetTime() < oldest.GetTime())\r
+ oldest = m_logEntries.GetGitRevAt(i).m_AuthorDate.GetTime();\r
+\r
+ if(m_logEntries.GetGitRevAt(i).m_AuthorDate.GetTime() > latest.GetTime())\r
+ latest = m_logEntries.GetGitRevAt(i).m_AuthorDate.GetTime();\r
\r
}\r
}\r
m_ByteCollector.append(data,size);\r
\r
//Find loginfo endmarker\r
- static const BYTE dataToFind[]={0,0};\r
- int found=m_ByteCollector.findData(dataToFind,2);\r
+ static const BYTE dataToFind[]={0,0,'#','<'};\r
+ int found=m_ByteCollector.findData(dataToFind,4);\r
if(found<0)\r
return m_ploglist->m_bExitThread;//Not found\r
found+=2;//Position after loginfo end-marker\r
}\r
//Set updating\r
int rev=itRev->second;\r
- GitRev* revInVector=&m_ploglist->m_logEntries[rev];\r
+ GitRev* revInVector=&m_ploglist->m_logEntries.GetGitRevAt(rev);\r
+\r
\r
+ if(revInVector->m_IsFull)\r
+ return;\r
+\r
+ GitRev *pRev= m_ploglist->m_LogCache.GetCacheData(m_ploglist->m_logEntries[rev]);\r
+ if(pRev)\r
+ {\r
+ ++m_CollectedCount;\r
+ InterlockedExchange(&pRev->m_IsUpdateing,FALSE);\r
+ InterlockedExchange(&pRev->m_IsFull,TRUE);\r
+ ::PostMessage(m_ploglist->m_hWnd,MSG_LOADED,(WPARAM)rev,0);\r
+ return;\r
+ }\r
\r
// fullRev.m_IsUpdateing=TRUE;\r
// fullRev.m_IsFull=TRUE;\r
-\r
+ \r
\r
if(InterlockedExchange(&revInVector->m_IsUpdateing,TRUE))\r
return;//Cannot update this row now. Ignore.\r
//So we need keep old bound mark.\r
revInVector->m_ParentHash=oldlist;\r
\r
+ //update cache\r
+ m_ploglist->m_LogCache.AddCacheEntry(*revInVector);\r
+\r
//Reset updating\r
InterlockedExchange(&revInVector->m_IsFull,TRUE);\r
InterlockedExchange(&revInVector->m_IsUpdateing,FALSE);\r
\r
::PostMessage(m_ploglist->m_hWnd,MSG_LOADED,(WPARAM)rev,0);\r
\r
- DWORD percent=m_CollectedCount*98/m_ploglist->m_logEntries.size() + GITLOG_START+1;\r
+ DWORD percent=m_CollectedCount*68/m_ploglist->m_logEntries.size() + GITLOG_START+1+30;\r
if(percent == GITLOG_END)\r
percent = GITLOG_END -1;\r
\r
\r
};\r
\r
-void CGitLogListBase::FetchFullLogInfo()\r
+void CGitLogListBase::FetchFullLogInfo(CString &from, CString &to)\r
{\r
CGitCall_FetchFullLogInfo fetcher(this);\r
int mask=\r
+ CGit::LOG_INFO_FULL_DIFF|\r
CGit::LOG_INFO_STAT|\r
CGit::LOG_INFO_FILESTATE|\r
CGit::LOG_INFO_DETECT_COPYRENAME|\r
+ CGit::LOG_INFO_SHOW_MERGEDFILE |\r
m_ShowMask;\r
- g_Git.GetLog(&fetcher,CString(),NULL,-1,mask);\r
+\r
+ CTGitPath *path;\r
+ if(this->m_Path.IsEmpty())\r
+ path=NULL;\r
+ else\r
+ path=&this->m_Path;\r
+\r
+ g_Git.GetLog(&fetcher,CString(),path,-1,mask,&from,&to);\r
}\r
\r
-void CGitLogListBase::FetchFullLogInfoOrig()\r
+void CGitLogListBase::FetchLastLogInfo()\r
{\r
unsigned int updated=0;\r
int percent=0;\r
CRect rect;\r
- while(1)\r
{\r
for(unsigned int i=0;i<m_logEntries.size();i++)\r
{\r
- if(m_LogCache.GetCacheData(m_logEntries[i]))\r
+ if(m_logEntries.GetGitRevAt(i).m_IsFull)\r
+ continue;\r
+\r
+ GitRev *pRev = m_LogCache.GetCacheData(m_logEntries[i]);\r
+ if(pRev == NULL)\r
{\r
if(!m_logEntries.FetchFullInfo(i))\r
{\r
updated++;\r
}\r
- m_LogCache.AddCacheEntry(m_logEntries[i]);\r
+ m_LogCache.AddCacheEntry(m_logEntries.GetGitRevAt(i));\r
\r
}else\r
{\r
updated++;\r
- InterlockedExchange(&m_logEntries[i].m_IsUpdateing,FALSE);\r
- InterlockedExchange(&m_logEntries[i].m_IsFull,TRUE);\r
+ InterlockedExchange(&pRev->m_IsUpdateing,FALSE);\r
+ InterlockedExchange(&pRev->m_IsFull,TRUE);\r
}\r
\r
::PostMessage(m_hWnd,MSG_LOADED,(WPARAM)i,0);\r
InterlockedExchange(&m_bThreadRunning, FALSE);\r
InterlockedExchange(&m_bNoDispUpdates, FALSE);\r
return;\r
- }\r
+ } \r
+ }\r
+ }\r
+}\r
\r
- percent=updated*98/m_logEntries.size() + GITLOG_START+1;\r
- if(percent == GITLOG_END)\r
- percent = GITLOG_END -1;\r
- \r
- ::PostMessage(this->GetParent()->m_hWnd,MSG_LOAD_PERCENTAGE,(WPARAM) percent,0);\r
+UINT CGitLogListBase::LogThread()\r
+{\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
+\r
+ ULONGLONG t1,t2;\r
+ \r
+ if(BeginFetchLog())\r
+ return -1;\r
\r
+ TRACE(_T("\n===Begin===\n"));\r
+ //Update work copy item;\r
+ if( m_logEntries.size() > 0)\r
+ {\r
+ GitRev *pRev = &m_logEntries.GetGitRevAt(0);\r
+ \r
+ m_arShownList.Add(pRev);\r
+\r
+ if( pRev->m_CommitHash.IsEmpty() )\r
+ {\r
+ pRev->m_Files.Clear();\r
+ pRev->m_ParentHash.clear();\r
+ pRev->m_ParentHash.push_back(m_HeadHash);\r
+ g_Git.GetCommitDiffList(pRev->m_CommitHash.ToString(),this->m_HeadHash, pRev->m_Files);\r
+ pRev->m_Action =0;\r
+ \r
+ for(int j=0;j< pRev->m_Files.GetCount();j++)\r
+ pRev->m_Action |= pRev->m_Files[j].m_Action;\r
\r
+ pRev->m_Body.Format(_T("%d files changed"),m_logEntries.GetGitRevAt(0).m_Files.GetCount());\r
+ ::PostMessage(m_hWnd,MSG_LOADED,(WPARAM)0,0);\r
}\r
- if(updated==m_logEntries.size())\r
+ }\r
+\r
+ InterlockedExchange(&m_bNoDispUpdates, FALSE);\r
+\r
+ git_get_log_firstcommit(m_DllGitLog);\r
+ int total = git_get_log_estimate_commit_count(m_DllGitLog);\r
+ GIT_COMMIT commit;\r
+ t1=GetTickCount();\r
+\r
+ int oldsize=m_logEntries.size();\r
+ while( git_get_log_nextcommit(this->m_DllGitLog,&commit) == 0)\r
+ {\r
+ //printf("%s\r\n",commit.m_Subject);\r
+ if(m_bExitThread)\r
break;\r
+\r
+ CGitHash hash = (char*)commit.m_hash ;\r
+ \r
+ GitRev *pRev = m_LogCache.GetCacheData(hash);\r
+ \r
+ if(pRev == NULL || !pRev->m_IsFull)\r
+ {\r
+ pRev->ParserFromCommit(&commit);\r
+ pRev->ParserParentFromCommit(&commit);\r
+ pRev->SafeFetchFullInfo(&g_Git);\r
+ \r
+ }else\r
+ {\r
+ ASSERT(pRev->m_CommitHash == hash);\r
+ pRev->ParserParentFromCommit(&commit);\r
+ }\r
+#ifdef DEBUG \r
+ pRev->DbgPrint();\r
+ TRACE(_T("\n"));\r
+#endif\r
+ git_free_commit(&commit);\r
+\r
+ this->m_critSec.Lock();\r
+ m_logEntries.push_back(hash);\r
+ m_arShownList.Add(pRev);\r
+ this->m_critSec.Unlock();\r
+\r
+ if(t2-t1>500 || (m_logEntries.size()-oldsize >100))\r
+ {\r
+ //update UI\r
+ int percent=m_logEntries.size()*100/total + GITLOG_START+1;\r
+ if(percent > 99)\r
+ percent =99;\r
+ if(percent < GITLOG_START)\r
+ percent = GITLOG_START +1;\r
+\r
+ oldsize = m_logEntries.size();\r
+ PostMessage(LVM_SETITEMCOUNT, (WPARAM) this->m_logEntries.size(),(LPARAM) LVSICF_NOINVALIDATEALL|LVSICF_NOSCROLL);\r
+ ::PostMessage(this->GetParent()->m_hWnd,MSG_LOAD_PERCENTAGE,(WPARAM) percent,0);\r
+ } \r
}\r
-}\r
+ \r
+ //Update UI;\r
+ PostMessage(LVM_SETITEMCOUNT, (WPARAM) this->m_logEntries.size(),(LPARAM) LVSICF_NOINVALIDATEALL|LVSICF_NOSCROLL);\r
+ ::PostMessage(this->GetParent()->m_hWnd,MSG_LOAD_PERCENTAGE,(WPARAM) GITLOG_END,0);\r
\r
-UINT CGitLogListBase::LogThread()\r
-{\r
+ InterlockedExchange(&m_bThreadRunning, FALSE);\r
\r
+#if 0\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
InterlockedExchange(&m_bNoDispUpdates, FALSE);\r
return 0;\r
}\r
+ InterlockedExchange(&m_bNoDispUpdates, FALSE);\r
+ ::PostMessage(GetParent()->m_hWnd,MSG_LOAD_PERCENTAGE,(WPARAM) GITLOG_START_ALL, 0);\r
+\r
+ int start=0; CString firstcommit,lastcommit;\r
+ int update=0;\r
+ for(int i=0;i<m_logEntries.size();i++)\r
+ {\r
+ if( i==0 && m_logEntries.GetGitRevAt(i).m_CommitHash.IsEmpty() )\r
+ {\r
+ m_logEntries.GetGitRevAt(i).m_Files.Clear();\r
+ m_logEntries.GetGitRevAt(i).m_ParentHash.clear();\r
+ m_logEntries.GetGitRevAt(i).m_ParentHash.push_back(m_HeadHash);\r
+ g_Git.GetCommitDiffList(m_logEntries.GetGitRevAt(i).m_CommitHash.ToString(),this->m_HeadHash,m_logEntries.GetGitRevAt(i).m_Files);\r
+ m_logEntries.GetGitRevAt(i).m_Action =0;\r
+ for(int j=0;j< m_logEntries.GetGitRevAt(i).m_Files.GetCount();j++)\r
+ m_logEntries.GetGitRevAt(i).m_Action |= m_logEntries.GetGitRevAt(i).m_Files[j].m_Action;\r
+ \r
+ m_logEntries.GetGitRevAt(i).m_Body.Format(_T("%d files changed"),m_logEntries.GetGitRevAt(i).m_Files.GetCount());\r
+ ::PostMessage(m_hWnd,MSG_LOADED,(WPARAM)0,0);\r
+ continue;\r
+ }\r
+\r
+ start=this->m_logEntries.GetGitRevAt(i).ParserFromLog(m_logEntries.m_RawlogData,start);\r
+ m_logEntries.m_HashMap[m_logEntries.GetGitRevAt(i).m_CommitHash.ToString()]=i;\r
+\r
+ if(m_LogCache.GetCacheData(m_logEntries.GetGitRevAt(i)))\r
+ {\r
+ if(firstcommit.IsEmpty())\r
+ firstcommit=m_logEntries.GetGitRevAt(i).m_CommitHash.ToString();\r
+ lastcommit=m_logEntries.GetGitRevAt(i).m_CommitHash.ToString();\r
+\r
+ }else\r
+ {\r
+ InterlockedExchange(&m_logEntries.GetGitRevAt(i).m_IsUpdateing,FALSE);\r
+ InterlockedExchange(&m_logEntries.GetGitRevAt(i).m_IsFull,TRUE);\r
+ update++;\r
+ }\r
+ ::PostMessage(m_hWnd,MSG_LOADED,(WPARAM) i, 0);\r
+\r
+ if(start<0)\r
+ break;\r
+ if(start>=m_logEntries.m_RawlogData.size())\r
+ break;\r
+\r
+ int percent=i*30/m_logEntries.size() + GITLOG_START+1;\r
+\r
+ ::PostMessage(GetParent()->m_hWnd,MSG_LOAD_PERCENTAGE,(WPARAM) percent, 0);\r
+\r
+ if(this->m_bExitThread)\r
+ { \r
+ InterlockedExchange(&m_bThreadRunning, FALSE);\r
+ InterlockedExchange(&m_bNoDispUpdates, FALSE);\r
+ return 0;\r
+ }\r
+ }\r
+ if(!lastcommit.IsEmpty())\r
+ FetchFullLogInfo(lastcommit,firstcommit);\r
+ \r
+ this->FetchLastLogInfo();\r
+ \r
#if 0\r
RedrawItems(0, m_arShownList.GetCount());\r
// SetRedraw(false);\r
}\r
}\r
#endif\r
- InterlockedExchange(&m_bNoDispUpdates, FALSE);\r
+\r
\r
\r
//FetchFullLogInfo();\r
- FetchFullLogInfoOrig();\r
+ //FetchFullLogInfoOrig();\r
//RefreshCursor();\r
// make sure the filter is applied (if any) now, after we refreshed/fetched\r
// the log messages\r
::PostMessage(this->GetParent()->m_hWnd,MSG_LOAD_PERCENTAGE,(WPARAM) GITLOG_END,0);\r
\r
InterlockedExchange(&m_bThreadRunning, FALSE);\r
-\r
+#endif\r
return 0;\r
}\r
\r
void CGitLogListBase::Refresh()\r
{ \r
m_bExitThread=TRUE;\r
- DWORD ret =::WaitForSingleObject(m_LoadingThread->m_hThread,20000);\r
- if(ret == WAIT_TIMEOUT)\r
- TerminateThread();\r
-\r
+ if(m_LoadingThread!=NULL)\r
+ {\r
+ DWORD ret =::WaitForSingleObject(m_LoadingThread->m_hThread,20000);\r
+ if(ret == WAIT_TIMEOUT)\r
+ TerminateThread();\r
+ }\r
+ \r
+ this->SetItemCountEx(0);\r
this->Clear();\r
\r
//Update branch and Tag info\r
//Assume Thread have exited\r
//if(!m_bThreadRunning)\r
{\r
- this->SetItemCountEx(0);\r
+ \r
m_logEntries.clear();\r
m_bExitThread=FALSE;\r
InterlockedExchange(&m_bThreadRunning, TRUE);\r
#endif\r
if ((m_nSelectedFilter == LOGFILTER_ALL)||(m_nSelectedFilter == LOGFILTER_MESSAGES))\r
{\r
- ATLTRACE(_T("messge = \"%s\"\n"),m_logEntries[i].m_Subject);\r
- if (regex_search(wstring((LPCTSTR)m_logEntries[i].m_Subject), pat, flags)&&IsEntryInDateRange(i))\r
+ ATLTRACE(_T("messge = \"%s\"\n"),m_logEntries.GetGitRevAt(i).m_Subject);\r
+ if (regex_search(wstring((LPCTSTR)m_logEntries.GetGitRevAt(i).m_Subject), pat, flags)&&IsEntryInDateRange(i))\r
{\r
- pShownlist->Add(&m_logEntries[i]);\r
+ pShownlist->Add(&m_logEntries.GetGitRevAt(i));\r
continue;\r
}\r
\r
- ATLTRACE(_T("messge = \"%s\"\n"),m_logEntries[i].m_Body);\r
- if (regex_search(wstring((LPCTSTR)m_logEntries[i].m_Body), pat, flags)&&IsEntryInDateRange(i))\r
+ ATLTRACE(_T("messge = \"%s\"\n"),m_logEntries.GetGitRevAt(i).m_Body);\r
+ if (regex_search(wstring((LPCTSTR)m_logEntries.GetGitRevAt(i).m_Body), pat, flags)&&IsEntryInDateRange(i))\r
{\r
- pShownlist->Add(&m_logEntries[i]);\r
+ pShownlist->Add(&m_logEntries.GetGitRevAt(i));\r
continue;\r
}\r
}\r
#endif\r
if ((m_nSelectedFilter == LOGFILTER_ALL)||(m_nSelectedFilter == LOGFILTER_AUTHORS))\r
{\r
- if (regex_search(wstring((LPCTSTR)m_logEntries[i].m_AuthorName), pat, flags)&&IsEntryInDateRange(i))\r
+ if (regex_search(wstring((LPCTSTR)m_logEntries.GetGitRevAt(i).m_AuthorName), pat, flags)&&IsEntryInDateRange(i))\r
{\r
- pShownlist->Add(&m_logEntries[i]);\r
+ pShownlist->Add(&m_logEntries.GetGitRevAt(i));\r
continue;\r
}\r
}\r
if ((m_nSelectedFilter == LOGFILTER_ALL)||(m_nSelectedFilter == LOGFILTER_REVS))\r
{\r
- sRev.Format(_T("%s"), m_logEntries[i].m_CommitHash);\r
+ sRev.Format(_T("%s"), m_logEntries.GetGitRevAt(i).m_CommitHash.ToString());\r
if (regex_search(wstring((LPCTSTR)sRev), pat, flags)&&IsEntryInDateRange(i))\r
{\r
- pShownlist->Add(&m_logEntries[i]);\r
+ pShownlist->Add(&m_logEntries.GetGitRevAt(i));\r
continue;\r
}\r
}\r
#endif\r
if ((m_nSelectedFilter == LOGFILTER_ALL)||(m_nSelectedFilter == LOGFILTER_MESSAGES))\r
{\r
- CString msg = m_logEntries[i].m_Subject;\r
+ CString msg = m_logEntries.GetGitRevAt(i).m_Subject;\r
\r
msg = msg.MakeLower();\r
if ((msg.Find(find) >= 0)&&(IsEntryInDateRange(i)))\r
{\r
- pShownlist->Add(&m_logEntries[i]);\r
+ pShownlist->Add(&m_logEntries.GetGitRevAt(i));\r
continue;\r
}\r
- msg = m_logEntries[i].m_Body;\r
+ msg = m_logEntries.GetGitRevAt(i).m_Body;\r
\r
msg = msg.MakeLower();\r
if ((msg.Find(find) >= 0)&&(IsEntryInDateRange(i)))\r
{\r
- pShownlist->Add(&m_logEntries[i]);\r
+ pShownlist->Add(&m_logEntries.GetGitRevAt(i));\r
continue;\r
}\r
}\r
#endif\r
if ((m_nSelectedFilter == LOGFILTER_ALL)||(m_nSelectedFilter == LOGFILTER_AUTHORS))\r
{\r
- CString msg = m_logEntries[i].m_AuthorName;\r
+ CString msg = m_logEntries.GetGitRevAt(i).m_AuthorName;\r
msg = msg.MakeLower();\r
if ((msg.Find(find) >= 0)&&(IsEntryInDateRange(i)))\r
{\r
- pShownlist->Add(&m_logEntries[i]);\r
+ pShownlist->Add(&m_logEntries.GetGitRevAt(i));\r
continue;\r
}\r
}\r
if ((m_nSelectedFilter == LOGFILTER_ALL)||(m_nSelectedFilter == LOGFILTER_REVS))\r
{\r
- sRev.Format(_T("%s"), m_logEntries[i].m_CommitHash);\r
+ sRev.Format(_T("%s"), m_logEntries.GetGitRevAt(i).m_CommitHash.ToString());\r
if ((sRev.Find(find) >= 0)&&(IsEntryInDateRange(i)))\r
{\r
- pShownlist->Add(&m_logEntries[i]);\r
+ pShownlist->Add(&m_logEntries.GetGitRevAt(i));\r
continue;\r
}\r
}\r
\r
BOOL CGitLogListBase::IsEntryInDateRange(int i)\r
{\r
- __time64_t time = m_logEntries[i].m_AuthorDate.GetTime();\r
+ __time64_t time = m_logEntries.GetGitRevAt(i).m_AuthorDate.GetTime();\r
if ((time >= m_From.GetTime())&&(time <= m_To.GetTime()))\r
return TRUE;\r
\r
void CGitLogListBase::Clear()\r
{\r
m_arShownList.RemoveAll();\r
- m_logEntries.clear();\r
- m_logEntries.m_HashMap.clear();\r
DeleteAllItems();\r
- m_logEntries.m_Lns.clear();\r
\r
- m_logEntries.m_FirstFreeLane=0;\r
- m_logEntries.m_Lns.clear();\r
+ m_logEntries.ClearAll();\r
\r
}\r
\r
int i=(int)wParam;\r
this->GetItemRect(i,&rect,LVIR_BOUNDS);\r
this->InvalidateRect(rect);\r
+\r
+ if(this->GetItemState(i,LVIF_STATE) & LVIS_SELECTED)\r
+ {\r
+ int i=0;\r
+ }\r
return 0;\r
}\r
\r
{\r
int width = GetColumnWidth( col );\r
CString regentry;\r
- regentry.Format( _T("Software\\TortoiseGit\\log\\ColWidth%d"), col);\r
+ regentry.Format( _T("Software\\TortoiseGit\\%s\\ColWidth%d"),m_ColumnRegKey, col);\r
CRegDWORD regwidth(regentry, 0);\r
regwidth = width; // this writes it to reg\r
}\r
}\r
}\r
\r
+int CGitLogListBase::GetHeadIndex()\r
+{\r
+ if(m_HeadHash.IsEmpty())\r
+ return -1;\r
+\r
+ for(int i=0;i<m_arShownList.GetCount();i++)\r
+ {\r
+ GitRev *pRev = (GitRev*)m_arShownList[i];\r
+ if(pRev)\r
+ {\r
+ if(pRev->m_CommitHash.ToString() == m_HeadHash )\r
+ return i;\r
+ }\r
+ }\r
+ return -1;\r
+}
\ No newline at end of file