Refactor out CResizableColumnsListCtrl
[TortoiseGit.git] / src / Git / GitStatusListCtrl.h
blob5ecaf1eba963017a599d65f6f235a97f1e67bf91
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2008-2016 - TortoiseGit
4 // Copyright (C) 2003-2008, 2014 - 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 #pragma once
21 #include "TGitPath.h"
22 #include "GitStatus.h"
23 #include "GitRev.h"
24 #include "Colors.h"
25 #include "ResizableColumnsListCtrl.h"
27 #define GIT_WC_ENTRY_WORKING_SIZE_UNKNOWN (-1)
29 // these defines must be in the order the columns are inserted!
30 #define GITSLC_COLFILENAME 0x000000002
31 #define GITSLC_COLEXT 0x000000004
32 #define GITSLC_COLSTATUS 0x000000008
33 //#define SVNSLC_COLAUTHOR 0x000000040
34 //#define SVNSLC_COLREVISION 0x000000080
35 //#define SVNSLC_COLDATE 0x000000100
36 #define GITSLC_COLADD 0x000000010
37 #define GITSLC_COLDEL 0x000000020
38 #define GITSLC_COLMODIFICATIONDATE 0x000000040
39 #define GITSLC_COLSIZE 0x000000080
40 #define GITSLC_NUMCOLUMNS 8
42 //#define SVNSLC_COLURL 0x000000200
43 //#define SVNSLC_COLCOPYFROM 0x000020000
45 #define GITSLC_SHOWUNVERSIONED CTGitPath::LOGACTIONS_UNVER
46 #define GITSLC_SHOWNORMAL 0x00000000
47 #define GITSLC_SHOWMODIFIED (CTGitPath::LOGACTIONS_MODIFIED)
48 #define GITSLC_SHOWADDED (CTGitPath::LOGACTIONS_ADDED|CTGitPath::LOGACTIONS_COPY)
49 #define GITSLC_SHOWREMOVED CTGitPath::LOGACTIONS_DELETED
50 #define GITSLC_SHOWCONFLICTED CTGitPath::LOGACTIONS_UNMERGED
51 #define GITSLC_SHOWMISSING 0x00000000
52 #define GITSLC_SHOWREPLACED CTGitPath::LOGACTIONS_REPLACED
53 #define GITSLC_SHOWMERGED CTGitPath::LOGACTIONS_MERGED
54 #define GITSLC_SHOWIGNORED CTGitPath::LOGACTIONS_IGNORE
55 #define GITSLC_SHOWOBSTRUCTED 0x00000000
56 #define GITSLC_SHOWEXTERNAL 0x00000000
57 #define GITSLC_SHOWINCOMPLETE 0x00000000
58 #define GITSLC_SHOWINEXTERNALS 0x00000000
59 #define GITSLC_SHOWREMOVEDANDPRESENT 0x00000000
60 #define GITSLC_SHOWLOCKS 0x00000000
61 #define GITSLC_SHOWDIRECTFILES 0x04000000
62 #define GITSLC_SHOWDIRECTFOLDER 0x00000000
63 #define GITSLC_SHOWEXTERNALFROMDIFFERENTREPO 0x00000000
64 #define GITSLC_SHOWSWITCHED 0x00000000
65 #define GITSLC_SHOWINCHANGELIST 0x00000000
66 #define GITSLC_SHOWASSUMEVALID CTGitPath::LOGACTIONS_ASSUMEVALID
67 #define GITSLC_SHOWSKIPWORKTREE CTGitPath::LOGACTIONS_SKIPWORKTREE
69 #define GITSLC_SHOWDIRECTS (GITSLC_SHOWDIRECTFILES | GITSLC_SHOWDIRECTFOLDER)
71 #define GITSLC_SHOWFILES 0x01000000
72 #define GITSLC_SHOWSUBMODULES 0x02000000
73 #define GITSLC_SHOWEVERYTHING 0xffffffff
75 #define GITSLC_SHOWVERSIONED (GITSLC_SHOWNORMAL|GITSLC_SHOWMODIFIED|\
76 GITSLC_SHOWADDED|GITSLC_SHOWREMOVED|GITSLC_SHOWCONFLICTED|GITSLC_SHOWMISSING|\
77 GITSLC_SHOWREPLACED|GITSLC_SHOWMERGED|GITSLC_SHOWIGNORED|GITSLC_SHOWOBSTRUCTED|\
78 GITSLC_SHOWEXTERNAL|GITSLC_SHOWINCOMPLETE|GITSLC_SHOWINEXTERNALS|\
79 GITSLC_SHOWEXTERNALFROMDIFFERENTREPO)
81 #define GITSLC_SHOWVERSIONEDBUTNORMAL (GITSLC_SHOWMODIFIED|GITSLC_SHOWADDED|\
82 GITSLC_SHOWREMOVED|GITSLC_SHOWCONFLICTED|GITSLC_SHOWMISSING|\
83 GITSLC_SHOWREPLACED|GITSLC_SHOWMERGED|GITSLC_SHOWIGNORED|GITSLC_SHOWOBSTRUCTED|\
84 GITSLC_SHOWEXTERNAL|GITSLC_SHOWINCOMPLETE|GITSLC_SHOWINEXTERNALS|\
85 GITSLC_SHOWEXTERNALFROMDIFFERENTREPO)
87 #define GITSLC_SHOWVERSIONEDBUTNORMALANDEXTERNALSFROMDIFFERENTREPOS (GITSLC_SHOWMODIFIED|\
88 GITSLC_SHOWADDED|GITSLC_SHOWREMOVED|GITSLC_SHOWCONFLICTED|GITSLC_SHOWMISSING|\
89 GITSLC_SHOWREPLACED|GITSLC_SHOWMERGED|GITSLC_SHOWIGNORED|GITSLC_SHOWOBSTRUCTED|\
90 GITSLC_SHOWINCOMPLETE|GITSLC_SHOWEXTERNAL|GITSLC_SHOWINEXTERNALS)
92 #define GITSLC_SHOWVERSIONEDBUTNORMALANDEXTERNALS (GITSLC_SHOWMODIFIED|\
93 GITSLC_SHOWADDED|GITSLC_SHOWREMOVED|GITSLC_SHOWCONFLICTED|GITSLC_SHOWMISSING|\
94 GITSLC_SHOWREPLACED|GITSLC_SHOWMERGED|GITSLC_SHOWIGNORED|GITSLC_SHOWOBSTRUCTED|\
95 GITSLC_SHOWINCOMPLETE)
97 #define GITSLC_SHOWALL (GITSLC_SHOWVERSIONED|GITSLC_SHOWUNVERSIONED)
99 #define GITSLC_POPALL 0xFFFFFFFFFFFFFFFF
100 #define GITSLC_POPCOMPAREWITHBASE CGitStatusListCtrl::GetContextMenuBit(CGitStatusListCtrl::IDGITLC_COMPARE)
101 #define GITSLC_POPCOMPARE CGitStatusListCtrl::GetContextMenuBit(CGitStatusListCtrl::IDGITLC_COMPAREWC)
102 #define GITSLC_POPGNUDIFF CGitStatusListCtrl::GetContextMenuBit(CGitStatusListCtrl::IDGITLC_GNUDIFF1)
103 #define GITSLC_POPREVERT CGitStatusListCtrl::GetContextMenuBit(CGitStatusListCtrl::IDGITLC_REVERT)
104 #define GITSLC_POPSHOWLOG CGitStatusListCtrl::GetContextMenuBit(CGitStatusListCtrl::IDGITLC_LOG)
105 #define GITSLC_POPSHOWLOGSUBMODULE CGitStatusListCtrl::GetContextMenuBit(CGitStatusListCtrl::IDGITLC_LOGSUBMODULE)
106 #define GITSLC_POPSHOWLOGOLDNAME CGitStatusListCtrl::GetContextMenuBit(CGitStatusListCtrl::IDGITLC_LOGOLDNAME)
107 #define GITSLC_POPOPEN CGitStatusListCtrl::GetContextMenuBit(CGitStatusListCtrl::IDGITLC_OPEN)
108 #define GITSLC_POPDELETE CGitStatusListCtrl::GetContextMenuBit(CGitStatusListCtrl::IDGITLC_DELETE)
109 #define GITSLC_POPADD CGitStatusListCtrl::GetContextMenuBit(CGitStatusListCtrl::IDGITLC_ADD)
110 #define GITSLC_POPIGNORE CGitStatusListCtrl::GetContextMenuBit(CGitStatusListCtrl::IDGITLC_IGNORE)
111 #define GITSLC_POPCONFLICT CGitStatusListCtrl::GetContextMenuBit(CGitStatusListCtrl::IDGITLC_EDITCONFLICT)
112 #define GITSLC_POPRESOLVE CGitStatusListCtrl::GetContextMenuBit(CGitStatusListCtrl::IDGITLC_RESOLVECONFLICT)
113 #define GITSLC_POPEXPLORE CGitStatusListCtrl::GetContextMenuBit(CGitStatusListCtrl::IDGITLC_EXPLORE)
114 #define GITSLC_POPCOMMIT CGitStatusListCtrl::GetContextMenuBit(CGitStatusListCtrl::IDGITLC_COMMIT)
115 #define GITSLC_POPCHANGELISTS CGitStatusListCtrl::GetContextMenuBit(CGitStatusListCtrl::IDGITLC_CHECKGROUP)
116 #define GITSLC_POPBLAME CGitStatusListCtrl::GetContextMenuBit(CGitStatusListCtrl::IDGITLC_BLAME)
117 #define GITSLC_POPSAVEAS CGitStatusListCtrl::GetContextMenuBit(CGitStatusListCtrl::IDGITLC_SAVEAS)
118 #define GITSLC_POPCOMPARETWOFILES CGitStatusListCtrl::GetContextMenuBit(CGitStatusListCtrl::IDGITLC_COMPARETWOFILES)
119 #define GITSLC_POPRESTORE CGitStatusListCtrl::GetContextMenuBit(CGitStatusListCtrl::IDGITLC_POPRESTORE)
120 #define GITSLC_POPASSUMEVALID CGitStatusListCtrl::GetContextMenuBit(CGitStatusListCtrl::IDGITLC_ASSUMEVALID)
121 #define GITSLC_POPSKIPWORKTREE CGitStatusListCtrl::GetContextMenuBit(CGitStatusListCtrl::IDGITLC_SKIPWORKTREE)
122 #define GITSLC_POPEXPORT CGitStatusListCtrl::GetContextMenuBit(CGitStatusListCtrl::IDGITLC_EXPORT)
123 #define GITLC_POPUNSETIGNORELOCALCHANGES CGitStatusListCtrl::GetContextMenuBit(CGitStatusListCtrl::IDGITLC_UNSETIGNORELOCALCHANGES)
124 #define GITSLC_PREPAREDIFF CGitStatusListCtrl::GetContextMenuBit(CGitStatusListCtrl::IDGITLC_PREPAREDIFF)
126 #define GITSLC_IGNORECHANGELIST _T("ignore-on-commit")
128 #define OVL_RESTORE 1
130 typedef int (__cdecl *GENERICCOMPAREFN)(const void * elem1, const void * elem2);
131 typedef CComCritSecLock<CComCriticalSection> Locker;
133 class CGitStatusListCtrlDropTarget;
136 * \ingroup TortoiseProc
137 * Simple utility class that defines the sort column order.
139 class CSorter
141 public:
143 CSorter ( ColumnManager* columnManager
144 , int sortedColumn
145 , bool ascending);
147 bool operator() ( const CTGitPath* entry1
148 , const CTGitPath* entry2) const;
150 static int A2L(const CString &str)
152 if(str==_T("-"))
153 return -1;
154 else
155 return _ttol(str);
158 private:
160 ColumnManager* columnManager;
161 int sortedColumn;
162 bool ascending;
166 * \ingroup SVN
167 * A List control, based on the MFC CListCtrl which shows a list of
168 * files with their git status. The control also provides a context
169 * menu to do some git tasks on the selected files.
171 * This is the main control used in many dialogs to show a list of files to
172 * work on.
174 class CGitStatusListCtrl :
175 public CResizableColumnsListCtrl<CListCtrl>
177 public:
178 enum
180 IDGITLC_REVERT = 1,
181 /** Compare with base version. when current version is zero (i.e. working tree changes), compare working tree and HEAD */
182 IDGITLC_COMPARE,
183 IDGITLC_OPEN,
184 IDGITLC_DELETE,
185 IDGITLC_IGNORE,
186 /** Compare with base version and generate unified diff. when current version is zero (i.e. working tree changes), compare working tree and HEAD */
187 IDGITLC_GNUDIFF1 ,
188 IDGITLC_LOG ,
189 IDGITLC_LOGOLDNAME,
190 IDGITLC_LOGSUBMODULE,
191 IDGITLC_EDITCONFLICT ,
192 IDGITLC_IGNOREMASK ,
193 IDGITLC_IGNOREFOLDER ,
194 IDGITLC_ADD ,
195 IDGITLC_RESOLVECONFLICT ,
196 IDGITLC_OPENWITH ,
197 IDGITLC_EXPLORE ,
198 IDGITLC_RESOLVETHEIRS ,
199 IDGITLC_RESOLVEMINE ,
200 IDGITLC_REMOVE ,
201 IDGITLC_COMMIT ,
202 IDGITLC_COPY ,
203 IDGITLC_COPYEXT ,
204 IDGITLC_REMOVEFROMCS ,
205 IDGITLC_CREATECS ,
206 IDGITLC_CREATEIGNORECS ,
207 IDGITLC_CHECKGROUP ,
208 IDGITLC_UNCHECKGROUP ,
209 /** Compare current version and working tree */
210 IDGITLC_COMPAREWC ,
211 IDGITLC_BLAME ,
212 IDGITLC_SAVEAS ,
213 IDGITLC_REVERTTOREV ,
214 IDGITLC_REVERTTOPARENT ,
215 IDGITLC_VIEWREV ,
216 IDGITLC_FINDENTRY ,
217 /** used in sync dlg, compare in/out file changes; in combination with m_Rev1 and m_Rev2 */
218 IDGITLC_COMPARETWOREVISIONS,
219 /** used in sync dlg, compare in/out file changes; in combination with m_Rev1 and m_Rev2 */
220 IDGITLC_GNUDIFF2REVISIONS,
221 /** Compare two selected files */
222 IDGITLC_COMPARETWOFILES ,
223 IDGITLC_POPRESTORE ,
224 IDGITLC_CREATERESTORE ,
225 IDGITLC_RESTOREPATH ,
226 IDGITLC_ASSUMEVALID ,
227 IDGITLC_SKIPWORKTREE ,
228 IDGITLC_EXPORT ,
229 IDGITLC_UNSETIGNORELOCALCHANGES,
230 IDGITLC_PREPAREDIFF ,
231 IDGITLC_PREPAREDIFF_COMPARE,
232 // the IDSVNLC_MOVETOCS *must* be the last index, because it contains a dynamic submenu where
233 // the submenu items get command ID's sequent to this number
234 IDGITLC_MOVETOCS ,
236 int GetColumnIndex(int colmask);
237 static inline unsigned __int64 GetContextMenuBit(int i){ return ((unsigned __int64 )0x1)<<i ;}
239 * Sent to the parent window (using ::SendMessage) after a context menu
240 * command has finished if the item count has changed.
242 static const UINT GITSLNM_ITEMCOUNTCHANGED;
244 * Sent to the parent window (using ::SendMessage) when the control needs
245 * to be refreshed. Since this is done usually in the parent window using
246 * a thread, this message is used to tell the parent to do exactly that.
248 static const UINT GITSLNM_NEEDSREFRESH;
251 * Sent to the parent window (using ::SendMessage) when the user drops
252 * files on the control. The LPARAM is a pointer to a TCHAR string
253 * containing the dropped path.
255 static const UINT GITSLNM_ADDFILE;
258 * Sent to the parent window (using ::SendMessage) when the user checks/unchecks
259 * one or more items in the control. The WPARAM contains the number of
260 * checked items in the control.
262 static const UINT GITSLNM_CHECKCHANGED;
264 static const UINT GITSLNM_ITEMCHANGED;
266 CGitStatusListCtrl(void);
267 ~CGitStatusListCtrl(void);
269 CString m_Rev1;
270 CString m_Rev2;
273 * \ingroup TortoiseProc
274 * Helper class for CGitStatusListCtrl which represents
275 * the data for each file shown.
277 #if 0
278 class FileEntry
280 public:
281 FileEntry() : status(git_wc_status_unversioned)
282 // , copyfrom_rev(GIT_REV_ZERO)
283 , last_commit_date(0)
284 , last_commit_rev(GIT_REV_ZERO)
285 // , remoterev(GIT_REV_ZERO)
286 , textstatus(git_wc_status_unversioned)
287 , propstatus(git_wc_status_unversioned)
288 // , remotestatus(git_wc_status_unversioned)
289 // , remotetextstatus(git_wc_status_unversioned)
290 // , remotepropstatus(git_wc_status_unversioned)
291 , copied(false)
292 , switched(false)
293 , checked(false)
294 , inunversionedfolder(false)
295 , inexternal(false)
296 , differentrepo(false)
297 , direct(false)
298 , isfolder(false)
299 , isNested(false)
300 , Revision(GIT_REV_ZERO)
301 , isConflicted(false)
302 // , present_props()
303 , needslock(false)
304 /// , working_size(SVN_WC_ENTRY_WORKING_SIZE_UNKNOWN)
305 , keeplocal(false)
306 // , depth(git_depth_unknown)
309 const CTGitPath& GetPath() const
311 return path;
313 const bool IsChecked() const
315 return checked;
317 CString GetRelativeGitPath() const
319 if (path.IsEquivalentTo(basepath))
320 return path.GetGitPathString();
321 return path.GetGitPathString().Mid(basepath.GetGitPathString().GetLength()+1);
323 // const bool IsLocked() const
324 // {
325 // return !(lock_token.IsEmpty() && lock_remotetoken.IsEmpty());
326 // }
327 // const bool HasNeedsLock() const
328 // {
329 // return needslock;
330 // }
331 const bool IsFolder() const
333 return isfolder;
335 const bool IsInExternal() const
337 return inexternal;
339 const bool IsNested() const
341 return isNested;
343 const bool IsFromDifferentRepository() const
345 return differentrepo;
347 CString GetDisplayName() const
349 CString const& chopped = path.GetDisplayString(&basepath);
350 if (!chopped.IsEmpty())
352 return chopped;
354 else
356 // "Display name" must not be empty.
357 return path.GetFileOrDirectoryName();
360 CString GetChangeList() const
362 return changelist;
364 // CString GetURL() const
365 // {
366 // return url;
367 // }
368 public:
369 git_wc_status_kind status; ///< local status
370 git_wc_status_kind textstatus; ///< local text status
371 git_wc_status_kind propstatus; ///< local property status
373 private:
374 CTGitPath path; ///< full path of the file
375 CTGitPath basepath; ///< common ancestor path of all files
377 CString changelist; ///< the name of the changelist the item belongs to
379 CString last_commit_author; ///< the author which last committed this item
380 CTime last_commit_date; ///< the date when this item was last committed
381 git_revnum_t last_commit_rev; ///< the revision where this item was last committed
383 git_revnum_t remoterev; ///< the revision in HEAD of the repository
384 bool copied; ///< if the file/folder is added-with-history
385 bool switched; ///< if the file/folder is switched to another url
386 bool checked; ///< if the file is checked in the list control
387 bool inunversionedfolder; ///< if the file is inside an unversioned folder
388 bool inexternal; ///< if the item is in an external folder
389 bool differentrepo; ///< if the item is from a different repository than the rest
390 bool direct; ///< directly included (TRUE) or just a child of a folder
391 bool isfolder; ///< TRUE if entry refers to a folder
392 bool isNested; ///< TRUE if the folder from a different repository and/or path
393 bool isConflicted; ///< TRUE if a file entry is conflicted, i.e. if it has the conflicted paths set
394 bool needslock; ///< TRUE if the Git:needs-lock property is set
395 git_revnum_t Revision; ///< the base revision
396 // PropertyList present_props; ///< cacheable properties present in BASE
397 bool keeplocal; ///< Whether a local copy of this entry should be kept in the working copy after a deletion has been committed
398 git_depth_t depth; ///< the depth of this entry
399 friend class CGitStatusListCtrl;
400 friend class CGitStatusListCtrlDropTarget;
401 friend class CSorter;
403 #endif
406 * Initializes the control, sets up the columns.
407 * \param dwColumns mask of columns to show. Use the GitSLC_COLxxx defines.
408 * \param sColumnInfoContainer Name of a registry key
409 * where the position and visibility of each column
410 * is saved and used from. If the registry key
411 * doesn't exist, the default order is used
412 * and dwColumns tells which columns are visible.
413 * \param dwContextMenus mask of context menus to be active, not all make sense for every use of this control.
414 * Use the GitSLC_POPxxx defines.
415 * \param bHasCheckboxes TRUE if the control should show check boxes on the left of each file entry.
416 * \param bHasWC TRUE if the reporisty is not a bare repository (hides wc related items on the contextmenu)
418 void Init(DWORD dwColumns, const CString& sColumnInfoContainer, unsigned __int64 dwContextMenus = ((GITSLC_POPALL ^ GITSLC_POPCOMMIT) ^ GITSLC_POPRESTORE), bool bHasCheckboxes = true, bool bHasWC = true, DWORD allowedColumns = 0xffffffff);
420 * Sets a background image for the list control.
421 * The image is shown in the right bottom corner.
422 * \param nID the resource ID of the bitmap to use as the background
424 bool SetBackgroundImage(UINT nID);
426 * Makes the 'ignore' context menu only ignore the files and not add the
427 * folder which gets the Git:ignore property changed to the list.
428 * This is needed e.g. for the Add-dialog, where the modified folder
429 * showing up would break the resulting "add" command.
431 void SetIgnoreRemoveOnly(bool bRemoveOnly = true) {m_bIgnoreRemoveOnly = bRemoveOnly;}
433 * The unversioned items are by default shown after all other files in the list.
434 * If that behavior should be changed, set this value to false.
436 void PutUnversionedLast(bool bLast) {m_bUnversionedLast = bLast;}
438 * Fetches the git status of all files and stores the information
439 * about them in an internal array.
440 * \param sFilePath path to a file which contains a list of files and/or folders for which to
441 * fetch the status, separated by newlines.
442 * \param bUpdate TRUE if the remote status is requested too.
443 * \return TRUE on success.
445 BOOL GetStatus (const CTGitPathList* pathList = nullptr
446 , bool bUpdate = false
447 , bool bShowIgnores = false
448 , bool bShowUnRev = false
449 , bool bShowLocalChangesIgnored = false);
452 * Populates the list control with the previously (with GetStatus) gathered status information.
453 * \param dwShow mask of file types to show. Use the GitSLC_SHOWxxx defines.
454 * \param dwCheck mask of file types to check. Use GitLC_SHOWxxx defines. Default (0) means 'use the entry's stored check status'
456 void Show(unsigned int dwShow, unsigned int dwCheck = 0, bool bShowFolders = true,BOOL updateStatusList=FALSE, bool UseStoredCheckStatus=false);
457 void Show(unsigned int dwShow, const CTGitPathList& checkedList, bool bShowFolders = true);
460 * Copies the selected entries in the control to the clipboard. The entries
461 * are separated by newlines.
462 * \param dwCols the columns to copy. Each column is separated by a tab.
464 bool CopySelectedEntriesToClipboard(DWORD dwCols);
467 * If during the call to GetStatus() some Git:externals are found from different
468 * repositories than the first one checked, then this method returns TRUE.
470 BOOL HasExternalsFromDifferentRepos() const {return m_bHasExternalsFromDifferentRepos;}
473 * If during the call to GetStatus() some Git:externals are found then this method returns TRUE.
475 BOOL HasExternals() const {return m_bHasExternals;}
478 * If unversioned files are found (but not necessarily shown) TRUE is returned.
480 BOOL HasUnversionedItems() {return m_bHasUnversionedItems;}
483 * If there are any locks in the working copy, TRUE is returned
485 BOOL HasLocks() const {return m_bHasLocks;}
488 * If there are any change lists defined in the working copy, TRUE is returned
490 BOOL HasChangeLists() const {return m_bHasChangeLists;}
493 * Returns the file entry data for the list control index.
495 //CGitStatusListCtrl::FileEntry * GetListEntry(UINT_PTR index);
498 * Returns the file entry data for the specified path.
499 * \note The entry might not be shown in the list control.
501 //CGitStatusListCtrl::FileEntry * GetListEntry(const CTGitPath& path);
504 * Returns the index of the list control entry with the specified path,
505 * or -1 if the path is not in the list control.
507 int GetIndex(const CTGitPath& path);
510 * Returns the file entry data for the specified path in the list control.
512 //CGitStatusListCtrl::FileEntry * GetVisibleListEntry(const CTGitPath& path);
515 * Returns a String containing some statistics like number of modified, normal, deleted,...
516 * files.
518 CString GetStatisticsString(bool simple=false);
521 * Set a static control which will be updated automatically with
522 * the number of selected and total files shown in the list control.
524 void SetStatLabel(CWnd * pStatLabel){m_pStatLabel = pStatLabel;};
527 * Set a tri-state checkbox which is updated automatically if the
528 * user checks/unchecks file entries in the list control to indicate
529 * if all files are checked, none are checked or some are checked.
531 void SetSelectButton(CButton * pButton) {m_pSelectButton = pButton;}
534 * Set a button which is de-/activated automatically. The button is
535 * only set active if at least one item is selected.
537 void SetConfirmButton(CButton * pButton) {m_pConfirmButton = pButton;}
540 * Select/unselect all entries in the list control.
541 * \param bSelect TRUE to check, FALSE to uncheck.
543 void SelectAll(bool bSelect, bool bIncludeNoCommits = false);
546 * Checks or unchecks all specified items
547 * \param dwCheck GITLC_SHOWxxx defines
548 * \param check if true matching items will be selected, false unchecks matching items
550 void Check(DWORD dwCheck, bool check = true);
552 /** Set a checkbox on an entry in the listbox
553 * Keeps the listctrl checked state and the FileEntry's checked flag in sync
555 void SetEntryCheck(CTGitPath* pEntry, int listboxIndex, bool bCheck);
557 /** Write a list of the checked items' paths into a path list
559 void WriteCheckedNamesToPathList(CTGitPathList& pathList);
561 /** fills in \a lMin and \a lMax with the lowest/highest revision of all
562 * files/folders in the working copy.
563 * \param bShownOnly if true, the min/max revisions are calculated only for shown items
564 * \param bCheckedOnly if true, the min/max revisions are calculated only for items
565 * which are checked.
566 * \remark Since an item can only be checked if it is visible/shown in the list control
567 * bShownOnly is automatically set to true if bCheckedOnly is true
569 void GetMinMaxRevisions(git_revnum_t& rMin, git_revnum_t& rMax, bool bShownOnly, bool bCheckedOnly);
572 * Returns the parent directory of all entries in the control.
573 * if \a bStrict is set to false, then the paths passed to the control
574 * to fetch the status (in GetStatus()) are used if possible.
576 CString GetCommonDirectory(bool bStrict);
579 * Returns the parent url of all entries in the control.
580 * if \a bStrict is set to false, then the paths passed to the control
581 * to fetch the status (in GetStatus()) are used if possible.
583 CTGitPath GetCommonURL(bool bStrict);
586 * Sets a pointer to a boolean variable which is checked periodically
587 * during the status fetching. As soon as the variable changes to true,
588 * the operations stops.
590 void SetCancelBool(bool * pbCanceled) {m_pbCanceled = pbCanceled;}
593 * Sets the string shown in the control while the status is fetched.
594 * If not set, it defaults to "please wait..."
596 void SetBusyString(const CString& str) {m_sBusy = str;}
597 void SetBusyString(UINT id) {m_sBusy.LoadString(id);}
600 * Sets the string shown in the control if no items are shown. This
601 * can happen for example if there's nothing modified and the unversioned
602 * files aren't shown either, so there's nothing to commit.
603 * If not set, it defaults to "file list is empty".
605 void SetEmptyString(const CString& str) {m_sEmpty = str;}
606 void SetEmptyString(UINT id) {m_sEmpty.LoadString(id);}
609 * Returns the number of selected items
611 LONG GetSelected(){return m_nSelected;};
614 * Enables dropping of files on the control.
616 bool EnableFileDrop();
619 * Checks if the path already exists in the list.
621 bool HasPath(const CTGitPath& path);
623 * Checks if the path is shown/visible in the list control.
625 bool IsPathShown(const CTGitPath& path);
627 * Forces the children to be checked when the parent folder is checked,
628 * and the parent folder to be unchecked if one of its children is unchecked.
630 void CheckChildrenWithParent(bool bCheck) {m_bCheckChildrenWithParent = bCheck;}
633 * Allows checking the items if change lists are present. If set to false,
634 * items are not checked if at least one changelist is available.
636 void CheckIfChangelistsArePresent(bool bCheck) {m_bCheckIfGroupsExist = bCheck;}
638 * Returns the currently used show flags passed to the Show() method.
640 DWORD GetShowFlags() {return m_dwShow;}
642 public:
643 CString GetLastErrorMessage() {return m_sLastError;}
645 void Block(BOOL block, BOOL blockUI) {m_bBlock = block; m_bBlockUI = blockUI;}
647 LONG GetUnversionedCount() { return m_nShownUnversioned; }
648 LONG GetModifiedCount() { return m_nShownModified; }
649 LONG GetAddedCount() { return m_nShownAdded; }
650 LONG GetDeletedCount() { return m_nShownDeleted; }
651 LONG GetConflictedCount() { return m_nShownConflicted; }
652 LONG GetFileCount() { return m_nShownFiles; }
653 LONG GetSubmoduleCount() { return m_nShownSubmodules; }
655 LONG m_nTargetCount; ///< number of targets in the file passed to GetStatus()
657 CString m_sURL; ///< the URL of the target or "(multiple targets)"
659 GitRev m_HeadRev; ///< the HEAD revision of the repository if bUpdate was TRUE
661 bool m_amend; ///< if true show the changes to the revision before the last commit
663 CString m_sUUID; ///< the UUID of the associated repository
665 CString m_sDisplayedBranch; ///< When on LogDialog, what is the current displayed branch
667 CWnd *m_hwndLogicalParent;
669 DECLARE_MESSAGE_MAP()
671 public:
672 void SetBusy(bool b) {m_bBusy = b; Invalidate();}
673 bool IsBusy() const { return m_bBusy; }
674 void SetHasCheckboxes(bool bHasCheckboxes)
676 m_bHasCheckboxes = bHasCheckboxes;
677 DWORD exStyle = GetExtendedStyle();
678 if (bHasCheckboxes)
679 exStyle |= LVS_EX_CHECKBOXES;
680 else
681 exStyle &= ~LVS_EX_CHECKBOXES;
682 SetExtendedStyle(exStyle);
685 private:
686 //void AddEntry(FileEntry * entry, WORD langID, int listIndex); ///< add an entry to the control
687 void RemoveListEntry(int index); ///< removes an entry from the listcontrol and both arrays
688 bool BuildStatistics(); ///< build the statistics and correct the case of files/folders
689 void StartDiff(int fileindex); ///< start the external diff program
690 void StartDiffWC(int fileindex); ///< start the external diff program
691 void StartDiffTwo(int fileindex);
693 void SetGitIndexFlagsForSelectedFiles(UINT message, BOOL assumevalid, BOOL skipworktree);
695 CString m_sMarkForDiffFilename;
696 CString m_sMarkForDiffVersion;
698 /* while rebasing, Their and My versios are swapped. */
699 bool m_bIsRevertTheirMy;
701 enum
703 ALTERNATIVEEDITOR,
704 OPEN,
705 OPEN_WITH,
707 void OpenFile(CTGitPath *path,int mode);
709 /// Clear the status vector (contains custodial pointers)
710 void ClearStatusArray();
712 /// Sort predicate function - Compare the paths of two entries without regard to case
713 //static bool EntryPathCompareNoCase(const FileEntry* pEntry1, const FileEntry* pEntry2);
715 /// Predicate used to build a list of only the versioned entries of the FileEntry array
716 //static bool IsEntryVersioned(const FileEntry* pEntry1);
718 /// Look up the relevant show flags for a particular Git status value
719 DWORD GetShowFlagsFromGitStatus(git_wc_status_kind status);
721 /// Adjust the checkbox-state on all descendants of a specific item
722 //void SetCheckOnAllDescendentsOf(const FileEntry* parentEntry, bool bCheck);
724 /// Build a path list of all the selected items in the list (NOTE - SELECTED, not CHECKED)
725 void FillListOfSelectedItemPaths(CTGitPathList& pathList, bool bNoIgnored = false);
727 /// Enables/Disables group view and adds all groups to the list control.
728 /// If bForce is true, then group view is enabled and the 'null' group is added.
729 bool PrepareGroups(bool bForce = false);
730 /// Returns the group number to which the group header belongs
731 /// If the point is not over a group header, -1 is returned
732 int GetGroupFromPoint(POINT * ppt);
733 /// Returns the number of change lists the selection has
734 size_t GetNumberOfChangelistsInSelection();
736 /// Puts the item to the corresponding group
737 bool SetItemGroup(int item, int groupindex);
739 void CheckEntry(int index, int nListItems);
740 void UncheckEntry(int index, int nListItems);
742 /// sends an GitSLNM_CHECKCHANGED notification to the parent
743 void NotifyCheck();
744 CWnd* GetLogicalParent() { return m_hwndLogicalParent ? m_hwndLogicalParent : this->GetParent(); }
746 void OnContextMenuList(CWnd * pWnd, CPoint point);
747 void OnContextMenuGroup(CWnd * pWnd, CPoint point);
748 bool CheckMultipleDiffs();
750 void DeleteSelectedFiles();
752 virtual void PreSubclassWindow();
753 virtual BOOL PreTranslateMessage(MSG* pMsg);
754 virtual BOOL OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult);
755 afx_msg void OnBeginDrag(NMHDR* pNMHDR, LRESULT* pResult);
756 afx_msg BOOL OnToolTipText(UINT id, NMHDR *pNMHDR, LRESULT *pResult);
757 afx_msg void OnHdnItemclick(NMHDR *pNMHDR, LRESULT *pResult);
758 afx_msg void OnLvnItemchanging(NMHDR *pNMHDR, LRESULT *pResult);
759 afx_msg BOOL OnLvnItemchanged(NMHDR *pNMHDR, LRESULT *pResult);
760 afx_msg void OnContextMenu(CWnd* pWnd, CPoint point);
762 void CreateChangeList(const CString& name);
764 afx_msg void OnNMDblclk(NMHDR *pNMHDR, LRESULT *pResult);
765 afx_msg void OnLvnGetInfoTip(NMHDR *pNMHDR, LRESULT *pResult);
766 afx_msg void OnNMCustomdraw(NMHDR *pNMHDR, LRESULT *pResult);
767 afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);
768 afx_msg UINT OnGetDlgCode();
769 afx_msg void OnNMReturn(NMHDR *pNMHDR, LRESULT *pResult);
770 afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
771 afx_msg void OnPaint();
773 void FilesExport();
774 void FileSaveAs(CTGitPath *path);
775 int RevertSelectedItemToVersion(bool parent = false);
777 private:
778 bool * m_pbCanceled;
779 bool m_bAscending; ///< sort direction
780 int m_nSortedColumn; ///< which column to sort
781 bool m_bHasCheckboxes;
782 bool m_bHasWC;
783 bool m_bUnversionedLast;
784 bool m_bHasExternalsFromDifferentRepos;
785 bool m_bHasExternals;
786 BOOL m_bHasUnversionedItems;
787 bool m_bHasLocks;
788 bool m_bHasChangeLists;
789 //typedef std::vector<FileEntry*> FileEntryVector;
790 //FileEntryVector m_arStatusArray;
791 std::vector<CTGitPath*> m_arStatusArray;
792 std::vector<size_t> m_arListArray;
793 std::map<CString, int> m_changelists;
794 bool m_bHasIgnoreGroup;
795 //CTGitPathList m_ConflictFileList;
796 CTGitPathList m_StatusFileList;
797 CTGitPathList m_UnRevFileList;
798 CTGitPathList m_IgnoreFileList;
799 CTGitPathList m_LocalChangesIgnoredFileList; // assume valid & skip worktree
800 //CTGitPathList m_StatusUrlList;
801 CString m_sLastError;
803 LONG m_nUnversioned;
804 LONG m_nNormal;
805 LONG m_nModified;
806 LONG m_nAdded;
807 LONG m_nDeleted;
808 LONG m_nConflicted;
809 LONG m_nTotal;
810 LONG m_nSelected;
811 LONG m_nLineAdded;
812 LONG m_nLineDeleted;
813 LONG m_nRenamed;
815 LONG m_nShownUnversioned;
816 LONG m_nShownModified;
817 LONG m_nShownAdded;
818 LONG m_nShownDeleted;
819 LONG m_nShownConflicted;
820 LONG m_nShownFiles;
821 LONG m_nShownSubmodules;
823 DWORD m_dwDefaultColumns;
824 DWORD m_dwShow;
825 bool m_bShowFolders;
826 bool m_bShowIgnores;
827 bool m_bUpdate;
828 unsigned __int64 m_dwContextMenus;
829 BOOL m_bBlock;
830 BOOL m_bBlockUI;
831 bool m_bBusy;
832 bool m_bEmpty;
833 bool m_bIgnoreRemoveOnly;
834 bool m_bCheckIfGroupsExist;
835 bool m_bFileDropsEnabled;
836 bool m_bOwnDrag;
838 int m_nIconFolder;
839 int m_nRestoreOvl;
841 CWnd * m_pStatLabel;
842 CButton * m_pSelectButton;
843 CButton * m_pConfirmButton;
844 CColors m_Colors;
846 CString m_sEmpty;
847 CString m_sBusy;
848 CString m_sNoPropValueText;
850 bool m_bCheckChildrenWithParent;
851 CGitStatusListCtrlDropTarget * m_pDropTarget;
853 std::map<CString,bool> m_mapFilenameToChecked; ///< Remember de-/selected items
854 std::map<CString,bool> m_mapDirectFiles;
855 CComCriticalSection m_critSec;
857 friend class CGitStatusListCtrlDropTarget;
858 public:
859 enum
861 FILELIST_MODIFY= 0x1,
862 FILELIST_UNVER = 0x2,
863 FILELIST_IGNORE =0x4,
864 FILELIST_LOCALCHANGESIGNORED = 0x8, // assume valid & skip worktree files
866 private:
867 int UpdateFileList(CTGitPathList* List = nullptr);
868 public:
869 int UpdateFileList(int mask, bool once = true, CTGitPathList* List = nullptr);
870 int UpdateUnRevFileList(CTGitPathList &list);
871 int UpdateUnRevFileList(CTGitPathList* List = nullptr);
872 int UpdateIgnoreFileList(CTGitPathList* List = nullptr);
873 int UpdateLocalChangesIgnoredFileList(CTGitPathList* list = nullptr);
875 int UpdateWithGitPathList(CTGitPathList &list);
877 void AddEntry(CTGitPath* path, WORD langID, int ListIndex);
878 void Clear();
879 int m_FileLoaded;
880 git_revnum_t m_CurrentVersion;
881 bool m_bDoNotAutoselectSubmodules;
882 bool m_bNoAutoselectMissing;
883 std::map<CString, CString> m_restorepaths;
885 HMENU m_hShellMenu;
886 LPCONTEXTMENU m_pContextMenu;
889 #if 0
890 class CGitStatusListCtrlDropTarget : public CIDropTarget
892 public:
893 CGitStatusListCtrlDropTarget(CGitStatusListCtrl * pGitStatusListCtrl):CIDropTarget(pGitStatusListCtrl->m_hWnd){m_pGitStatusListCtrl = pGitStatusListCtrl;}
895 virtual bool OnDrop(FORMATETC* pFmtEtc, STGMEDIUM& medium, DWORD * /*pdwEffect*/, POINTL pt);
896 virtual HRESULT STDMETHODCALLTYPE DragOver(DWORD grfKeyState, POINTL pt, DWORD __RPC_FAR *pdwEffect);
897 private:
898 CGitStatusListCtrl * m_pGitStatusListCtrl;
900 #endif