Fixed Issue #141: Bizarre ordering in commit dialog?
[TortoiseGit.git] / src / Git / GitStatusListCtrl.h
blob40af64f2b75d24377604ad90594b2be7e54fa5f8
1 // TortoiseSVN - a Windows shell extension for easy version control
3 // Copyright (C) 2003-2008 - TortoiseSVN
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 2
8 // of the License, or (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software Foundation,
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 #pragma once
20 #include "TGitPath.h"
21 #include "GitStatus.h"
22 #include "GitRev.h"
23 #include "GitConfig.h"
24 #include "Colors.h"
25 #include "XPTheme.h"
26 #include "CommonResource.h"
28 #define SVN_WC_ENTRY_WORKING_SIZE_UNKNOWN (-1)
30 // these defines must be in the order the columns are inserted!
31 #define SVNSLC_COLFILENAME 0x000000002
32 #define SVNSLC_COLEXT 0x000000004
33 #define SVNSLC_COLSTATUS 0x000000008
34 #define SVNSLC_COLTEXTSTATUS 0x000000010
35 #define SVNSLC_COLPROPSTATUS 0x000000020
36 #define SVNSLC_COLAUTHOR 0x000000040
37 #define SVNSLC_COLREVISION 0x000000080
38 #define SVNSLC_COLDATE 0x000000100
39 #define SVNSLC_COLMODIFICATIONDATE 0x000000200
40 #define SVNSLC_COLADD 0x000000400
41 #define SVNSLC_COLDEL 0x000000800
42 #define SVNSLC_NUMCOLUMNS 12
44 //#define SVNSLC_COLREMOTESTATUS 0x000000010
45 //#define SVNSLC_COLREMOTETEXT 0x000000080
46 //#define SVNSLC_COLREMOTEPROP 0x000000100
47 //#define SVNSLC_COLURL 0x000000200
48 //#define SVNSLC_COLLOCK 0x000000400
49 //#define SVNSLC_COLLOCKCOMMENT 0x000000800
51 //#define SVNSLC_COLREMOTEREVISION 0x000004000
53 //#define SVNSLC_COLSVNNEEDSLOCK 0x000010000
54 //#define SVNSLC_COLCOPYFROM 0x000020000
57 #define SVNSLC_SHOWUNVERSIONED CTGitPath::LOGACTIONS_UNVER
58 #define SVNSLC_SHOWNORMAL 0x000000000
59 #define SVNSLC_SHOWMODIFIED (CTGitPath::LOGACTIONS_MODIFIED)
60 #define SVNSLC_SHOWADDED (CTGitPath::LOGACTIONS_ADDED|CTGitPath::LOGACTIONS_COPY)
61 #define SVNSLC_SHOWREMOVED CTGitPath::LOGACTIONS_DELETED
62 #define SVNSLC_SHOWCONFLICTED CTGitPath::LOGACTIONS_UNMERGED
63 #define SVNSLC_SHOWMISSING 0x00000000
64 #define SVNSLC_SHOWREPLACED CTGitPath::LOGACTIONS_REPLACED
65 #define SVNSLC_SHOWMERGED CTGitPath::LOGACTIONS_MERGED
66 #define SVNSLC_SHOWIGNORED CTGitPath::LOGACTIONS_IGNORE
67 #define SVNSLC_SHOWOBSTRUCTED 0x00000000
68 #define SVNSLC_SHOWEXTERNAL 0x00000000
69 #define SVNSLC_SHOWINCOMPLETE 0x00000000
70 #define SVNSLC_SHOWINEXTERNALS 0x00000000
71 #define SVNSLC_SHOWREMOVEDANDPRESENT 0x00000000
72 #define SVNSLC_SHOWLOCKS 0x00000000
73 #define SVNSLC_SHOWDIRECTFILES 0x00000000
74 #define SVNSLC_SHOWDIRECTFOLDER 0x00000000
75 #define SVNSLC_SHOWEXTERNALFROMDIFFERENTREPO 0x00000000
76 #define SVNSLC_SHOWSWITCHED 0x00000000
77 #define SVNSLC_SHOWINCHANGELIST 0x00000000
79 #define SVNSLC_SHOWDIRECTS (SVNSLC_SHOWDIRECTFILES | SVNSLC_SHOWDIRECTFOLDER)
82 #define SVNSLC_SHOWVERSIONED (CTGitPath::LOGACTIONS_FORWORD|SVNSLC_SHOWNORMAL|SVNSLC_SHOWMODIFIED|\
83 SVNSLC_SHOWADDED|SVNSLC_SHOWREMOVED|SVNSLC_SHOWCONFLICTED|SVNSLC_SHOWMISSING|\
84 SVNSLC_SHOWREPLACED|SVNSLC_SHOWMERGED|SVNSLC_SHOWIGNORED|SVNSLC_SHOWOBSTRUCTED|\
85 SVNSLC_SHOWEXTERNAL|SVNSLC_SHOWINCOMPLETE|SVNSLC_SHOWINEXTERNALS|\
86 SVNSLC_SHOWEXTERNALFROMDIFFERENTREPO)
88 #define SVNSLC_SHOWVERSIONEDBUTNORMAL (SVNSLC_SHOWMODIFIED|SVNSLC_SHOWADDED|\
89 SVNSLC_SHOWREMOVED|SVNSLC_SHOWCONFLICTED|SVNSLC_SHOWMISSING|\
90 SVNSLC_SHOWREPLACED|SVNSLC_SHOWMERGED|SVNSLC_SHOWIGNORED|SVNSLC_SHOWOBSTRUCTED|\
91 SVNSLC_SHOWEXTERNAL|SVNSLC_SHOWINCOMPLETE|SVNSLC_SHOWINEXTERNALS|\
92 SVNSLC_SHOWEXTERNALFROMDIFFERENTREPO)
94 #define SVNSLC_SHOWVERSIONEDBUTNORMALANDEXTERNALSFROMDIFFERENTREPOS (SVNSLC_SHOWMODIFIED|\
95 SVNSLC_SHOWADDED|SVNSLC_SHOWREMOVED|SVNSLC_SHOWCONFLICTED|SVNSLC_SHOWMISSING|\
96 SVNSLC_SHOWREPLACED|SVNSLC_SHOWMERGED|SVNSLC_SHOWIGNORED|SVNSLC_SHOWOBSTRUCTED|\
97 SVNSLC_SHOWINCOMPLETE|SVNSLC_SHOWEXTERNAL|SVNSLC_SHOWINEXTERNALS)
99 #define SVNSLC_SHOWVERSIONEDBUTNORMALANDEXTERNALS (SVNSLC_SHOWMODIFIED|\
100 SVNSLC_SHOWADDED|SVNSLC_SHOWREMOVED|SVNSLC_SHOWCONFLICTED|SVNSLC_SHOWMISSING|\
101 SVNSLC_SHOWREPLACED|SVNSLC_SHOWMERGED|SVNSLC_SHOWIGNORED|SVNSLC_SHOWOBSTRUCTED|\
102 SVNSLC_SHOWINCOMPLETE)
104 #define SVNSLC_SHOWALL (SVNSLC_SHOWVERSIONED|SVNSLC_SHOWUNVERSIONED)
106 #define SVNSLC_POPALL 0xFFFFFFFFFFFFFFFF
107 #define SVNSLC_POPCOMPAREWITHBASE CGitStatusListCtrl::GetContextMenuBit(CGitStatusListCtrl::IDSVNLC_COMPARE)
108 #define SVNSLC_POPCOMPARE CGitStatusListCtrl::GetContextMenuBit(CGitStatusListCtrl::IDSVNLC_COMPAREWC)
109 #define SVNSLC_POPGNUDIFF CGitStatusListCtrl::GetContextMenuBit(CGitStatusListCtrl::IDSVNLC_GNUDIFF1)
110 #define SVNSLC_POPREVERT CGitStatusListCtrl::GetContextMenuBit(CGitStatusListCtrl::IDSVNLC_REVERT)
111 #define SVNSLC_POPUPDATE CGitStatusListCtrl::GetContextMenuBit(CGitStatusListCtrl::IDSVNLC_UPDATE)
112 #define SVNSLC_POPSHOWLOG CGitStatusListCtrl::GetContextMenuBit(CGitStatusListCtrl::IDSVNLC_LOG)
113 #define SVNSLC_POPOPEN CGitStatusListCtrl::GetContextMenuBit(CGitStatusListCtrl::IDSVNLC_OPEN)
114 #define SVNSLC_POPDELETE CGitStatusListCtrl::GetContextMenuBit(CGitStatusListCtrl::IDSVNLC_DELETE)
115 #define SVNSLC_POPADD CGitStatusListCtrl::GetContextMenuBit(CGitStatusListCtrl::IDSVNLC_ADD)
116 #define SVNSLC_POPIGNORE CGitStatusListCtrl::GetContextMenuBit(CGitStatusListCtrl::IDSVNLC_IGNORE)
117 #define SVNSLC_POPCONFLICT CGitStatusListCtrl::GetContextMenuBit(CGitStatusListCtrl::IDSVNLC_EDITCONFLICT)
118 #define SVNSLC_POPRESOLVE CGitStatusListCtrl::GetContextMenuBit(CGitStatusListCtrl::IDSVNLC_RESOLVECONFLICT)
119 #define SVNSLC_POPLOCK CGitStatusListCtrl::GetContextMenuBit(CGitStatusListCtrl::IDSVNLC_LOCK)
120 #define SVNSLC_POPUNLOCK CGitStatusListCtrl::GetContextMenuBit(CGitStatusListCtrl::IDSVNLC_UNLOCK)
121 #define SVNSLC_POPUNLOCKFORCE CGitStatusListCtrl::GetContextMenuBit(CGitStatusListCtrl::IDSVNLC_UNLOCKFORCE)
122 #define SVNSLC_POPEXPLORE CGitStatusListCtrl::GetContextMenuBit(CGitStatusListCtrl::IDSVNLC_EXPLORE)
123 #define SVNSLC_POPCOMMIT CGitStatusListCtrl::GetContextMenuBit(CGitStatusListCtrl::IDSVNLC_COMMIT)
124 #define SVNSLC_POPPROPERTIES CGitStatusListCtrl::GetContextMenuBit(CGitStatusListCtrl::IDSVNLC_PROPERTIES)
125 #define SVNSLC_POPREPAIRMOVE CGitStatusListCtrl::GetContextMenuBit(CGitStatusListCtrl::IDSVNLC_REPAIRMOVE)
126 #define SVNSLC_POPCHANGELISTS CGitStatusListCtrl::GetContextMenuBit(CGitStatusListCtrl::IDSVNLC_CHECKGROUP)
127 #define SVNSLC_POPBLAME CGitStatusListCtrl::GetContextMenuBit(CGitStatusListCtrl::IDSVNLC_BLAME)
129 #define SVNSLC_IGNORECHANGELIST _T("ignore-on-commit")
131 // This gives up to 64 standard properties and menu entries
132 // plus 192 user-defined properties (should be plenty).
133 // User-defined properties will start at column SVNSLC_NUMCOLUMNS+1
134 // but in the registry, we will record them starting at SVNSLC_USERPROPCOLOFFSET.
136 #define SVNSLC_USERPROPCOLOFFSET 0x40
137 #define SVNSLC_USERPROPCOLLIMIT 0xff
138 #define SVNSLC_MAXCOLUMNCOUNT 0xff
140 // Supporting extreamly long user props makes no sense here --
141 // especially for binary properties. CString uses a pool allocator
142 // that works for up to 256 chars. Make sure we are well below that.
144 #define SVNSLC_MAXUSERPROPLENGTH 0x70
146 typedef int (__cdecl *GENERICCOMPAREFN)(const void * elem1, const void * elem2);
147 typedef CComCritSecLock<CComCriticalSection> Locker;
149 class CGitStatusListCtrlDropTarget;
151 * \ingroup SVN
152 * A List control, based on the MFC CListCtrl which shows a list of
153 * files with their Subversion status. The control also provides a context
154 * menu to do some Subversion tasks on the selected files.
156 * This is the main control used in many dialogs to show a list of files to
157 * work on.
159 class CGitStatusListCtrl :
160 public CListCtrl
162 public:
163 enum
165 IDSVNLC_REVERT = 1,
166 IDSVNLC_COMPARE,
167 IDSVNLC_OPEN,
168 IDSVNLC_DELETE,
169 IDSVNLC_IGNORE,
170 IDSVNLC_GNUDIFF1 ,
171 IDSVNLC_UPDATE ,
172 IDSVNLC_LOG ,
173 IDSVNLC_EDITCONFLICT ,
174 IDSVNLC_IGNOREMASK ,
175 IDSVNLC_ADD ,
176 IDSVNLC_RESOLVECONFLICT ,
177 IDSVNLC_LOCK ,
178 IDSVNLC_LOCKFORCE ,
179 IDSVNLC_UNLOCK ,
180 IDSVNLC_UNLOCKFORCE ,
181 IDSVNLC_OPENWITH ,
182 IDSVNLC_EXPLORE ,
183 IDSVNLC_RESOLVETHEIRS ,
184 IDSVNLC_RESOLVEMINE ,
185 IDSVNLC_REMOVE ,
186 IDSVNLC_COMMIT ,
187 IDSVNLC_PROPERTIES ,
188 IDSVNLC_COPY ,
189 IDSVNLC_COPYEXT ,
190 IDSVNLC_REPAIRMOVE ,
191 IDSVNLC_REMOVEFROMCS ,
192 IDSVNLC_CREATECS ,
193 IDSVNLC_CREATEIGNORECS ,
194 IDSVNLC_CHECKGROUP ,
195 IDSVNLC_UNCHECKGROUP ,
196 IDSVNLC_ADD_RECURSIVE ,
197 IDSVNLC_COMPAREWC ,
198 IDSVNLC_BLAME ,
199 IDSVNLC_SAVEAS ,
200 IDSVNLC_REVERTTOREV ,
201 IDSVNLC_VIEWREV ,
202 IDSVNLC_FINDENTRY ,
203 IDSVNLC_COMPARETWO ,
204 IDSVNLC_GNUDIFF2 ,
205 // the IDSVNLC_MOVETOCS *must* be the last index, because it contains a dynamic submenu where
206 // the submenu items get command ID's sequent to this number
207 IDSVNLC_MOVETOCS ,
209 int GetColumnIndex(int colmask);
210 static inline unsigned __int64 GetContextMenuBit(int i){ return ((unsigned __int64 )0x1)<<i ;}
212 * Sent to the parent window (using ::SendMessage) after a context menu
213 * command has finished if the item count has changed.
215 static const UINT SVNSLNM_ITEMCOUNTCHANGED;
217 * Sent to the parent window (using ::SendMessage) when the control needs
218 * to be refreshed. Since this is done usually in the parent window using
219 * a thread, this message is used to tell the parent to do exactly that.
221 static const UINT SVNSLNM_NEEDSREFRESH;
224 * Sent to the parent window (using ::SendMessage) when the user drops
225 * files on the control. The LPARAM is a pointer to a TCHAR string
226 * containing the dropped path.
228 static const UINT SVNSLNM_ADDFILE;
231 * Sent to the parent window (using ::SendMessage) when the user checks/unchecks
232 * one or more items in the control. The WPARAM contains the number of
233 * checked items in the control.
235 static const UINT SVNSLNM_CHECKCHANGED;
237 CGitStatusListCtrl(void);
238 ~CGitStatusListCtrl(void);
240 CString m_Rev1;
241 CString m_Rev2;
244 * \ingroup TortoiseProc
245 * Helper class for CGitStatusListCtrl which represents
246 * the data for each file shown.
248 #if 0
249 class FileEntry
251 public:
252 FileEntry() : status(git_wc_status_unversioned)
253 // , copyfrom_rev(GIT_REV_ZERO)
254 , last_commit_date(0)
255 , last_commit_rev(GIT_REV_ZERO)
256 // , remoterev(GIT_REV_ZERO)
257 , textstatus(git_wc_status_unversioned)
258 , propstatus(git_wc_status_unversioned)
259 // , remotestatus(git_wc_status_unversioned)
260 // , remotetextstatus(git_wc_status_unversioned)
261 // , remotepropstatus(git_wc_status_unversioned)
262 , copied(false)
263 , switched(false)
264 , checked(false)
265 , inunversionedfolder(false)
266 , inexternal(false)
267 , differentrepo(false)
268 , direct(false)
269 , isfolder(false)
270 , isNested(false)
271 , Revision(GIT_REV_ZERO)
272 , isConflicted(false)
273 // , present_props()
274 , needslock(false)
275 /// , working_size(SVN_WC_ENTRY_WORKING_SIZE_UNKNOWN)
276 , keeplocal(false)
277 // , depth(git_depth_unknown)
280 const CTGitPath& GetPath() const
282 return path;
284 const bool IsChecked() const
286 return checked;
288 CString GetRelativeGitPath() const
290 if (path.IsEquivalentTo(basepath))
291 return path.GetGitPathString();
292 return path.GetGitPathString().Mid(basepath.GetGitPathString().GetLength()+1);
294 // const bool IsLocked() const
295 // {
296 // return !(lock_token.IsEmpty() && lock_remotetoken.IsEmpty());
297 // }
298 // const bool HasNeedsLock() const
299 // {
300 // return needslock;
301 // }
302 const bool IsFolder() const
304 return isfolder;
306 const bool IsInExternal() const
308 return inexternal;
310 const bool IsNested() const
312 return isNested;
314 const bool IsFromDifferentRepository() const
316 return differentrepo;
318 CString GetDisplayName() const
320 CString const& chopped = path.GetDisplayString(&basepath);
321 if (!chopped.IsEmpty())
323 return chopped;
325 else
327 // "Display name" must not be empty.
328 return path.GetFileOrDirectoryName();
331 CString GetChangeList() const
333 return changelist;
335 // CString GetURL() const
336 // {
337 // return url;
338 // }
339 public:
340 git_wc_status_kind status; ///< local status
341 git_wc_status_kind textstatus; ///< local text status
342 git_wc_status_kind propstatus; ///< local property status
344 private:
345 CTGitPath path; ///< full path of the file
346 CTGitPath basepath; ///< common ancestor path of all files
348 CString changelist; ///< the name of the changelist the item belongs to
350 CString last_commit_author; ///< the author which last committed this item
351 CTime last_commit_date; ///< the date when this item was last committed
352 git_revnum_t last_commit_rev; ///< the revision where this item was last committed
354 git_revnum_t remoterev; ///< the revision in HEAD of the repository
355 bool copied; ///< if the file/folder is added-with-history
356 bool switched; ///< if the file/folder is switched to another url
357 bool checked; ///< if the file is checked in the list control
358 bool inunversionedfolder; ///< if the file is inside an unversioned folder
359 bool inexternal; ///< if the item is in an external folder
360 bool differentrepo; ///< if the item is from a different repository than the rest
361 bool direct; ///< directly included (TRUE) or just a child of a folder
362 bool isfolder; ///< TRUE if entry refers to a folder
363 bool isNested; ///< TRUE if the folder from a different repository and/or path
364 bool isConflicted; ///< TRUE if a file entry is conflicted, i.e. if it has the conflicted paths set
365 bool needslock; ///< TRUE if the Git:needs-lock property is set
366 git_revnum_t Revision; ///< the base revision
367 // PropertyList present_props; ///< cacheable properties present in BASE
368 bool keeplocal; ///< Whether a local copy of this entry should be kept in the working copy after a deletion has been committed
369 git_depth_t depth; ///< the depth of this entry
370 friend class CGitStatusListCtrl;
371 friend class CGitStatusListCtrlDropTarget;
372 friend class CSorter;
374 #endif
376 * \ingroup TortoiseProc
377 * Helper class for CGitStatusListCtrl that represents
378 * the columns visible and their order as well as
379 * persisting that data in the registry.
381 * It assigns logical index values to the (potential) columns:
382 * 0 .. GitSLC_NUMCOLUMNS-1 contain the standard attributes
383 * GitSLC_USERPROPCOLOFFSET .. GitSLC_MAXCOLUMNCOUNT are user props.
385 * The column vector contains the columns that are actually
386 * available in the control.
388 * Since the set of userprops may change from one WC to another,
389 * we also store the settings (width and order) for those
390 * userprops that are not used in this WC.
392 * A userprop is considered "in use", if the respective column
393 * is not hidden or if at least one item has this property set.
395 class ColumnManager
397 public:
399 /// construction / destruction
401 ColumnManager (CListCtrl* control) : control (control) {};
402 ~ColumnManager() {};
404 /// registry access
406 void ReadSettings (DWORD defaultColumns, const CString& containerName);
407 void WriteSettings() const;
409 /// read column definitions
411 int GetColumnCount() const; ///< total number of columns
412 bool IsVisible (int column) const;
413 int GetInvisibleCount() const;
414 bool IsRelevant (int column) const;
415 bool IsUserProp (int column) const;
416 CString GetName (int column) const;
417 int GetWidth (int column, bool useDefaults = false) const;
418 int GetVisibleWidth (int column, bool useDefaults) const;
420 /// switch columns on and off
422 void SetVisible (int column, bool visible);
424 /// tracking column modifications
426 void ColumnMoved (int column, int position);
427 void ColumnResized (int column);
429 /// call these to update the user-prop list
430 /// (will also auto-insert /-remove new list columns)
432 //void UpdateUserPropList (const std::vector<FileEntry*>& files);
433 //void UpdateRelevance ( const std::vector<FileEntry*>& files
434 // , const std::vector<size_t>& visibleFiles);
436 /// don't clutter the context menu with irrelevant prop info
438 bool AnyUnusedProperties() const;
439 void RemoveUnusedProps();
441 /// bring everything back to its "natural" order
443 void ResetColumns (DWORD defaultColumns);
445 private:
447 /// initialization utilities
449 void ParseUserPropSettings ( const CString& userPropList
450 , const CString& shownUserProps);
451 void ParseWidths (const CString& widths);
452 void SetStandardColumnVisibility (DWORD visibility);
453 void ParseColumnOrder (const CString& widths);
455 /// map internal column order onto visible column order
456 /// (all invisibles in front)
458 std::vector<int> GetGridColumnOrder();
459 void ApplyColumnOrder();
461 /// utilities used when writing data to the registry
463 DWORD GetSelectedStandardColumns() const;
464 CString GetUserPropList() const;
465 CString GetShownUserProps() const;
466 CString GetWidthString() const;
467 CString GetColumnOrderString() const;
469 /// our parent control and its data
471 CListCtrl* control;
473 /// where to store in the registry
475 CString registryPrefix;
477 /// all columns in their "natural" order
479 struct ColumnInfo
481 int index; ///< is a user prop when < GitSLC_USERPROPCOLOFFSET
482 int width;
483 bool visible;
484 bool relevant; ///< set to @a visible, if no *shown* item has that property
487 std::vector<ColumnInfo> columns;
489 /// user-defined properties
491 struct UserProp
493 CString name; ///< is a user prop when < GitSLC_USERPROPCOLOFFSET
494 int width;
497 std::vector<UserProp> userProps;
499 /// stored result from last UpdateUserPropList() call
501 std::set<CString> itemProps;
503 /// global column ordering including unused user props
505 std::vector<int> columnOrder;
507 };/**
508 * \ingroup TortoiseProc
509 * Simple utility class that defines the sort column order.
511 class CSorter
513 public:
515 CSorter ( ColumnManager* columnManager
516 , int sortedColumn
517 , bool ascending);
519 bool operator() ( const CTGitPath* entry1
520 , const CTGitPath* entry2) const;
522 static int A2L(const CString &str)
524 if(str==_T("-"))
525 return -1;
526 else
527 return _ttol(str);
530 private:
532 ColumnManager* columnManager;
533 int sortedColumn;
534 bool ascending;
538 * Initializes the control, sets up the columns.
539 * \param dwColumns mask of columns to show. Use the GitSLC_COLxxx defines.
540 * \param sColumnInfoContainer Name of a registry key
541 * where the position and visibility of each column
542 * is saved and used from. If the registry key
543 * doesn't exist, the default order is used
544 * and dwColumns tells which columns are visible.
545 * \param dwContextMenus mask of context menus to be active, not all make sense for every use of this control.
546 * Use the GitSLC_POPxxx defines.
547 * \param bHasCheckboxes TRUE if the control should show check boxes on the left of each file entry.
549 void Init(DWORD dwColumns, const CString& sColumnInfoContainer, unsigned __int64 dwContextMenus = (SVNSLC_POPALL ^ SVNSLC_POPCOMMIT), bool bHasCheckboxes = true);
551 * Sets a background image for the list control.
552 * The image is shown in the right bottom corner.
553 * \param nID the resource ID of the bitmap to use as the background
555 bool SetBackgroundImage(UINT nID);
557 * Makes the 'ignore' context menu only ignore the files and not add the
558 * folder which gets the Git:ignore property changed to the list.
559 * This is needed e.g. for the Add-dialog, where the modified folder
560 * showing up would break the resulting "add" command.
562 void SetIgnoreRemoveOnly(bool bRemoveOnly = true) {m_bIgnoreRemoveOnly = bRemoveOnly;}
564 * The unversioned items are by default shown after all other files in the list.
565 * If that behavior should be changed, set this value to false.
567 void PutUnversionedLast(bool bLast) {m_bUnversionedLast = bLast;}
569 * Fetches the Subversion status of all files and stores the information
570 * about them in an internal array.
571 * \param sFilePath path to a file which contains a list of files and/or folders for which to
572 * fetch the status, separated by newlines.
573 * \param bUpdate TRUE if the remote status is requested too.
574 * \return TRUE on success.
576 BOOL GetStatus ( const CTGitPathList* pathList=NULL
577 , bool bUpdate = false
578 , bool bShowIgnores = false
579 , bool bShowUnRev=false
580 , bool bShowUserProps = false);
583 * Populates the list control with the previously (with GetStatus) gathered status information.
584 * \param dwShow mask of file types to show. Use the GitSLC_SHOWxxx defines.
585 * \param dwCheck mask of file types to check. Use GitLC_SHOWxxx defines. Default (0) means 'use the entry's stored check status'
587 void Show(DWORD dwShow, DWORD dwCheck = 0, bool bShowFolders = true,BOOL updateStatusList=FALSE);
588 void Show(DWORD dwShow, const CTGitPathList& checkedList, bool bShowFolders = true);
591 * Copies the selected entries in the control to the clipboard. The entries
592 * are separated by newlines.
593 * \param dwCols the columns to copy. Each column is separated by a tab.
595 bool CopySelectedEntriesToClipboard(DWORD dwCols);
598 * If during the call to GetStatus() some Git:externals are found from different
599 * repositories than the first one checked, then this method returns TRUE.
601 BOOL HasExternalsFromDifferentRepos() const {return m_bHasExternalsFromDifferentRepos;}
604 * If during the call to GetStatus() some Git:externals are found then this method returns TRUE.
606 BOOL HasExternals() const {return m_bHasExternals;}
609 * If unversioned files are found (but not necessarily shown) TRUE is returned.
611 BOOL HasUnversionedItems() {return m_bHasUnversionedItems;}
614 * If there are any locks in the working copy, TRUE is returned
616 BOOL HasLocks() const {return m_bHasLocks;}
619 * If there are any change lists defined in the working copy, TRUE is returned
621 BOOL HasChangeLists() const {return m_bHasChangeLists;}
624 * Returns the file entry data for the list control index.
626 //CGitStatusListCtrl::FileEntry * GetListEntry(UINT_PTR index);
629 * Returns the file entry data for the specified path.
630 * \note The entry might not be shown in the list control.
632 //CGitStatusListCtrl::FileEntry * GetListEntry(const CTGitPath& path);
635 * Returns the index of the list control entry with the specified path,
636 * or -1 if the path is not in the list control.
638 int GetIndex(const CTGitPath& path);
641 * Returns the file entry data for the specified path in the list control.
643 //CGitStatusListCtrl::FileEntry * GetVisibleListEntry(const CTGitPath& path);
646 * Returns a String containing some statistics like number of modified, normal, deleted,...
647 * files.
649 CString GetStatisticsString();
652 * Set a static control which will be updated automatically with
653 * the number of selected and total files shown in the list control.
655 void SetStatLabel(CWnd * pStatLabel){m_pStatLabel = pStatLabel;};
658 * Set a tri-state checkbox which is updated automatically if the
659 * user checks/unchecks file entries in the list control to indicate
660 * if all files are checked, none are checked or some are checked.
662 void SetSelectButton(CButton * pButton) {m_pSelectButton = pButton;}
665 * Set a button which is de-/activated automatically. The button is
666 * only set active if at least one item is selected.
668 void SetConfirmButton(CButton * pButton) {m_pConfirmButton = pButton;}
671 * Select/unselect all entries in the list control.
672 * \param bSelect TRUE to check, FALSE to uncheck.
674 void SelectAll(bool bSelect, bool bIncludeNoCommits = false);
676 /** Set a checkbox on an entry in the listbox
677 * Keeps the listctrl checked state and the FileEntry's checked flag in sync
679 void SetEntryCheck(CTGitPath* pEntry, int listboxIndex, bool bCheck);
681 /** Write a list of the checked items' paths into a path list
683 void WriteCheckedNamesToPathList(CTGitPathList& pathList);
685 /** fills in \a lMin and \a lMax with the lowest/highest revision of all
686 * files/folders in the working copy.
687 * \param bShownOnly if true, the min/max revisions are calculated only for shown items
688 * \param bCheckedOnly if true, the min/max revisions are calculated only for items
689 * which are checked.
690 * \remark Since an item can only be checked if it is visible/shown in the list control
691 * bShownOnly is automatically set to true if bCheckedOnly is true
693 void GetMinMaxRevisions(git_revnum_t& rMin, git_revnum_t& rMax, bool bShownOnly, bool bCheckedOnly);
696 * Returns the parent directory of all entries in the control.
697 * if \a bStrict is set to false, then the paths passed to the control
698 * to fetch the status (in GetStatus()) are used if possible.
700 CString GetCommonDirectory(bool bStrict);
703 * Returns the parent url of all entries in the control.
704 * if \a bStrict is set to false, then the paths passed to the control
705 * to fetch the status (in GetStatus()) are used if possible.
707 CTGitPath GetCommonURL(bool bStrict);
710 * Sets a pointer to a boolean variable which is checked periodically
711 * during the status fetching. As soon as the variable changes to true,
712 * the operations stops.
714 void SetCancelBool(bool * pbCanceled) {m_pbCanceled = pbCanceled;}
717 * Sets the string shown in the control while the status is fetched.
718 * If not set, it defaults to "please wait..."
720 void SetBusyString(const CString& str) {m_sBusy = str;}
721 void SetBusyString(UINT id) {m_sBusy.LoadString(id);}
724 * Sets the string shown in the control if no items are shown. This
725 * can happen for example if there's nothing modified and the unversioned
726 * files aren't shown either, so there's nothing to commit.
727 * If not set, it defaults to "file list is empty".
729 void SetEmptyString(const CString& str) {m_sEmpty = str;}
730 void SetEmptyString(UINT id) {m_sEmpty.LoadString(id);}
733 * Determines if the control should recurse into unversioned folders
734 * when fetching the status. The default behavior is defined by the
735 * registry key HKCU\Software\TortoiseGit\UnversionedRecurse, which
736 * is read in the Init() method.
737 * If you want to change the behavior, call this method *after*
738 * calling Init().
740 void SetUnversionedRecurse(bool bUnversionedRecurse) {m_bUnversionedRecurse = bUnversionedRecurse;}
743 * Returns the number of selected items
745 LONG GetSelected(){return m_nSelected;};
748 * Enables dropping of files on the control.
750 bool EnableFileDrop();
753 * Checks if the path already exists in the list.
755 bool HasPath(const CTGitPath& path);
757 * Checks if the path is shown/visible in the list control.
759 bool IsPathShown(const CTGitPath& path);
761 * Forces the children to be checked when the parent folder is checked,
762 * and the parent folder to be unchecked if one of its children is unchecked.
764 void CheckChildrenWithParent(bool bCheck) {m_bCheckChildrenWithParent = bCheck;}
767 * Allows checking the items if change lists are present. If set to false,
768 * items are not checked if at least one changelist is available.
770 void CheckIfChangelistsArePresent(bool bCheck) {m_bCheckIfGroupsExist = bCheck;}
772 * Returns the currently used show flags passed to the Show() method.
774 DWORD GetShowFlags() {return m_dwShow;}
775 public:
776 CString GetLastErrorMessage() {return m_sLastError;}
778 void Block(BOOL block, BOOL blockUI) {m_bBlock = block; m_bBlockUI = blockUI;}
780 LONG m_nTargetCount; ///< number of targets in the file passed to GetStatus()
782 CString m_sURL; ///< the URL of the target or "(multiple targets)"
784 GitRev m_HeadRev; ///< the HEAD revision of the repository if bUpdate was TRUE
786 CString m_sUUID; ///< the UUID of the associated repository
788 DECLARE_MESSAGE_MAP()
790 private:
791 void SaveColumnWidths(bool bSaveToRegistry = false);
792 void Sort(); ///< Sorts the control by columns
793 //void AddEntry(FileEntry * entry, WORD langID, int listIndex); ///< add an entry to the control
794 void RemoveListEntry(int index); ///< removes an entry from the listcontrol and both arrays
795 bool BuildStatistics(); ///< build the statistics and correct the case of files/folders
796 void StartDiff(int fileindex); ///< start the external diff program
797 void StartDiffWC(int fileindex); ///< start the external diff program
798 void StartDiffTwo(int fileindex);
800 enum
802 NOTEPAD2,
803 OPEN,
804 OPEN_WITH,
806 void OpenFile(CTGitPath *path,int mode);
808 /// fetch all user properties for all items
809 void FetchUserProperties();
811 /// Process one line of the command file supplied to GetStatus
812 bool FetchStatusForSingleTarget(GitConfig& config, GitStatus& status, const CTGitPath& target,
813 bool bFetchStatusFromRepository, CStringA& strCurrentRepositoryUUID, CTGitPathList& arExtPaths,
814 bool bAllDirect, git_depth_t depth = git_depth_infinity, bool bShowIgnores = false);
816 /// Create 'status' data for each item in an unversioned folder
817 void AddUnversionedFolder(const CTGitPath& strFolderName, const CTGitPath& strBasePath, GitConfig * config);
819 /// Read the all the other status items which result from a single GetFirstStatus call
820 void ReadRemainingItemsStatus(GitStatus& status, const CTGitPath& strBasePath, CStringA& strCurrentRepositoryUUID, CTGitPathList& arExtPaths, GitConfig * config, bool bAllDirect);
822 /// Clear the status vector (contains custodial pointers)
823 void ClearStatusArray();
825 /// Sort predicate function - Compare the paths of two entries without regard to case
826 //static bool EntryPathCompareNoCase(const FileEntry* pEntry1, const FileEntry* pEntry2);
828 /// Predicate used to build a list of only the versioned entries of the FileEntry array
829 //static bool IsEntryVersioned(const FileEntry* pEntry1);
831 /// Look up the relevant show flags for a particular Git status value
832 DWORD GetShowFlagsFromGitStatus(git_wc_status_kind status);
834 /// Build a FileEntry item and add it to the FileEntry array
835 //const FileEntry* AddNewFileEntry(
836 // const git_wc_status2_t* pGitStatus, // The return from the Git GetStatus functions
837 // const CTGitPath& path, // The path of the item we're adding
838 // const CTGitPath& basePath, // The base directory for this status build
839 // bool bDirectItem, // Was this item the first found by GetFirstFileStatus or by a subsequent GetNextFileStatus call
840 // bool bInExternal, // Are we in an 'external' folder
841 // bool bEntryfromDifferentRepo // if the entry is from a different repository
842 // );
844 /// Adjust the checkbox-state on all descendants of a specific item
845 //void SetCheckOnAllDescendentsOf(const FileEntry* parentEntry, bool bCheck);
847 /// Build a path list of all the selected items in the list (NOTE - SELECTED, not CHECKED)
848 void FillListOfSelectedItemPaths(CTGitPathList& pathList, bool bNoIgnored = false);
850 /// Enables/Disables group view and adds all groups to the list control.
851 /// If bForce is true, then group view is enabled and the 'null' group is added.
852 bool PrepareGroups(bool bForce = false);
853 /// Returns the group number to which the group header belongs
854 /// If the point is not over a group header, -1 is returned
855 int GetGroupFromPoint(POINT * ppt);
856 /// Returns the number of change lists the selection has
857 size_t GetNumberOfChangelistsInSelection();
859 /// Puts the item to the corresponding group
860 bool SetItemGroup(int item, int groupindex);
862 void CheckEntry(int index, int nListItems);
863 void UncheckEntry(int index, int nListItems);
865 /// sends an GitSLNM_CHECKCHANGED notification to the parent
866 void NotifyCheck();
868 int CellRectFromPoint(CPoint& point, RECT *cellrect, int *col) const;
870 void OnContextMenuList(CWnd * pWnd, CPoint point);
871 void OnContextMenuGroup(CWnd * pWnd, CPoint point);
872 void OnContextMenuHeader(CWnd * pWnd, CPoint point);
874 virtual void PreSubclassWindow();
875 virtual BOOL PreTranslateMessage(MSG* pMsg);
876 virtual INT_PTR OnToolHitTest(CPoint point, TOOLINFO* pTI) const;
877 afx_msg void OnBeginDrag(NMHDR* pNMHDR, LRESULT* pResult);
878 afx_msg BOOL OnToolTipText(UINT id, NMHDR *pNMHDR, LRESULT *pResult);
879 afx_msg void OnHdnItemclick(NMHDR *pNMHDR, LRESULT *pResult);
880 afx_msg void OnLvnItemchanging(NMHDR *pNMHDR, LRESULT *pResult);
881 afx_msg BOOL OnLvnItemchanged(NMHDR *pNMHDR, LRESULT *pResult);
882 afx_msg void OnColumnResized(NMHDR *pNMHDR, LRESULT *pResult);
883 afx_msg void OnColumnMoved(NMHDR *pNMHDR, LRESULT *pResult);
884 afx_msg void OnContextMenu(CWnd* pWnd, CPoint point);
886 void CreateChangeList(const CString& name);
888 afx_msg void OnNMDblclk(NMHDR *pNMHDR, LRESULT *pResult);
889 afx_msg void OnLvnGetInfoTip(NMHDR *pNMHDR, LRESULT *pResult);
890 afx_msg void OnNMCustomdraw(NMHDR *pNMHDR, LRESULT *pResult);
891 afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);
892 afx_msg UINT OnGetDlgCode();
893 afx_msg void OnNMReturn(NMHDR *pNMHDR, LRESULT *pResult);
894 afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
895 afx_msg void OnPaint();
896 afx_msg void OnHdnBegintrack(NMHDR *pNMHDR, LRESULT *pResult);
897 afx_msg void OnHdnItemchanging(NMHDR *pNMHDR, LRESULT *pResult);
898 afx_msg void OnDestroy();
901 void FileSaveAs(CTGitPath *path);
902 int RevertSelectedItemToVersion();
904 private:
905 bool * m_pbCanceled;
906 bool m_bAscending; ///< sort direction
907 int m_nSortedColumn; ///< which column to sort
908 bool m_bHasCheckboxes;
909 bool m_bUnversionedLast;
910 bool m_bHasExternalsFromDifferentRepos;
911 bool m_bHasExternals;
912 BOOL m_bHasUnversionedItems;
913 bool m_bHasLocks;
914 bool m_bHasChangeLists;
915 //typedef std::vector<FileEntry*> FileEntryVector;
916 //FileEntryVector m_arStatusArray;
917 std::vector<CTGitPath*> m_arStatusArray;
918 std::vector<size_t> m_arListArray;
919 std::map<CString, int> m_changelists;
920 bool m_bHasIgnoreGroup;
921 //CTGitPathList m_ConflictFileList;
922 CTGitPathList m_StatusFileList;
923 CTGitPathList m_UnRevFileList;
924 CTGitPathList m_IgnoreFileList;
925 //CTGitPathList m_StatusUrlList;
926 CString m_sLastError;
928 LONG m_nUnversioned;
929 LONG m_nNormal;
930 LONG m_nModified;
931 LONG m_nAdded;
932 LONG m_nDeleted;
933 LONG m_nConflicted;
934 LONG m_nTotal;
935 LONG m_nSelected;
937 DWORD m_dwDefaultColumns;
938 DWORD m_dwShow;
939 bool m_bShowFolders;
940 bool m_bShowIgnores;
941 bool m_bUpdate;
942 unsigned __int64 m_dwContextMenus;
943 BOOL m_bBlock;
944 BOOL m_bBlockUI;
945 bool m_bBusy;
946 bool m_bEmpty;
947 bool m_bIgnoreRemoveOnly;
948 bool m_bCheckIfGroupsExist;
949 bool m_bFileDropsEnabled;
950 bool m_bOwnDrag;
952 int m_nIconFolder;
954 CWnd * m_pStatLabel;
955 CButton * m_pSelectButton;
956 CButton * m_pConfirmButton;
957 CColors m_Colors;
959 CString m_sEmpty;
960 CString m_sBusy;
961 CString m_sNoPropValueText;
963 bool m_bUnversionedRecurse;
965 bool m_bCheckChildrenWithParent;
966 CGitStatusListCtrlDropTarget * m_pDropTarget;
968 ColumnManager m_ColumnManager;
970 std::map<CString,bool> m_mapFilenameToChecked; ///< Remember manually de-/selected items
971 CComCriticalSection m_critSec;
973 friend class CGitStatusListCtrlDropTarget;
974 public:
975 enum
977 FILELIST_MODIFY= 0x1,
978 FILELIST_UNVER = 0x2,
979 FILELIST_IGNORE =0x4
981 public:
982 int UpdateFileList(git_revnum_t hash,CTGitPathList *List=NULL);
983 int UpdateFileList(int mask, bool once=true,CTGitPathList *List=NULL);
984 int UpdateUnRevFileList(CTGitPathList *List=NULL);
985 int UpdateIgnoreFileList(CTGitPathList *List=NULL);
987 int UpdateWithGitPathList(CTGitPathList &list);
989 void AddEntry(CTGitPath* path, WORD langID, int ListIndex);
990 void Clear();
991 int m_FileLoaded;
992 git_revnum_t m_CurrentVersion;
993 public:
994 CXPTheme m_Theme;
997 #if 0
998 class CGitStatusListCtrlDropTarget : public CIDropTarget
1000 public:
1001 CGitStatusListCtrlDropTarget(CGitStatusListCtrl * pGitStatusListCtrl):CIDropTarget(pGitStatusListCtrl->m_hWnd){m_pGitStatusListCtrl = pGitStatusListCtrl;}
1003 virtual bool OnDrop(FORMATETC* pFmtEtc, STGMEDIUM& medium, DWORD * /*pdwEffect*/, POINTL pt);
1004 virtual HRESULT STDMETHODCALLTYPE DragOver(DWORD grfKeyState, POINTL pt, DWORD __RPC_FAR *pdwEffect);
1005 private:
1006 CGitStatusListCtrl * m_pGitStatusListCtrl;
1008 #endif