OSDN Git Service

Change Dir Structure to be same as TortoiseSVN'
[tortoisegit/TortoiseGitJp.git] / src / Git / GitStatusListCtrl.h
1 // TortoiseSVN - a Windows shell extension for easy version control\r
2 \r
3 // Copyright (C) 2003-2008 - TortoiseSVN\r
4 \r
5 // This program is free software; you can redistribute it and/or\r
6 // modify it under the terms of the GNU General Public License\r
7 // as published by the Free Software Foundation; either version 2\r
8 // of the License, or (at your option) any later version.\r
9 \r
10 // This program is distributed in the hope that it will be useful,\r
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13 // GNU General Public License for more details.\r
14 \r
15 // You should have received a copy of the GNU General Public License\r
16 // along with this program; if not, write to the Free Software Foundation,\r
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
18 //\r
19 #pragma once\r
20 #include "TGitPath.h"\r
21 #include "GitStatus.h"\r
22 #include "GitRev.h"\r
23 #include "GitConfig.h"\r
24 #include "Colors.h"\r
25 \r
26 #define SVN_WC_ENTRY_WORKING_SIZE_UNKNOWN (-1)\r
27 \r
28 // these defines must be in the order the columns are inserted!\r
29 #define SVNSLC_COLFILENAME                      0x000000002\r
30 #define SVNSLC_COLEXT                           0x000000004\r
31 #define SVNSLC_COLSTATUS                        0x000000008\r
32 #define SVNSLC_COLTEXTSTATUS            0x000000010\r
33 #define SVNSLC_COLPROPSTATUS            0x000000020\r
34 #define SVNSLC_COLAUTHOR                        0x000000040\r
35 #define SVNSLC_COLREVISION                      0x000000080\r
36 #define SVNSLC_COLDATE                          0x000000100\r
37 #define SVNSLC_COLMODIFICATIONDATE      0x000000200\r
38 #define SVNSLC_NUMCOLUMNS               10\r
39 \r
40 //#define SVNSLC_COLREMOTESTATUS                0x000000010\r
41 //#define SVNSLC_COLREMOTETEXT          0x000000080\r
42 //#define SVNSLC_COLREMOTEPROP          0x000000100\r
43 //#define SVNSLC_COLURL                         0x000000200\r
44 //#define SVNSLC_COLLOCK                                0x000000400\r
45 //#define SVNSLC_COLLOCKCOMMENT         0x000000800\r
46 \r
47 //#define       SVNSLC_COLREMOTEREVISION        0x000004000\r
48 \r
49 //#define SVNSLC_COLSVNNEEDSLOCK                0x000010000\r
50 //#define SVNSLC_COLCOPYFROM                    0x000020000\r
51 \r
52 \r
53 #define SVNSLC_SHOWUNVERSIONED  0x000000001\r
54 #define SVNSLC_SHOWNORMAL               0x000000002\r
55 #define SVNSLC_SHOWMODIFIED             0x000000004\r
56 #define SVNSLC_SHOWADDED                0x000000008\r
57 #define SVNSLC_SHOWREMOVED              0x000000010\r
58 #define SVNSLC_SHOWCONFLICTED   0x000000020\r
59 #define SVNSLC_SHOWMISSING              0x000000040\r
60 #define SVNSLC_SHOWREPLACED             0x000000080\r
61 #define SVNSLC_SHOWMERGED               0x000000100\r
62 #define SVNSLC_SHOWIGNORED              0x000000200\r
63 #define SVNSLC_SHOWOBSTRUCTED   0x000000400\r
64 #define SVNSLC_SHOWEXTERNAL             0x000000800\r
65 #define SVNSLC_SHOWINCOMPLETE   0x000001000\r
66 #define SVNSLC_SHOWINEXTERNALS  0x000002000\r
67 #define SVNSLC_SHOWREMOVEDANDPRESENT 0x000004000\r
68 #define SVNSLC_SHOWLOCKS                0x000008000\r
69 #define SVNSLC_SHOWDIRECTFILES  0x000010000\r
70 #define SVNSLC_SHOWDIRECTFOLDER 0x000020000\r
71 #define SVNSLC_SHOWEXTERNALFROMDIFFERENTREPO 0x000040000\r
72 #define SVNSLC_SHOWSWITCHED             0x000080000\r
73 #define SVNSLC_SHOWINCHANGELIST 0x000100000\r
74 \r
75 #define SVNSLC_SHOWDIRECTS              (SVNSLC_SHOWDIRECTFILES | SVNSLC_SHOWDIRECTFOLDER)\r
76 \r
77 \r
78 #define SVNSLC_SHOWVERSIONED (SVNSLC_SHOWNORMAL|SVNSLC_SHOWMODIFIED|\\r
79 SVNSLC_SHOWADDED|SVNSLC_SHOWREMOVED|SVNSLC_SHOWCONFLICTED|SVNSLC_SHOWMISSING|\\r
80 SVNSLC_SHOWREPLACED|SVNSLC_SHOWMERGED|SVNSLC_SHOWIGNORED|SVNSLC_SHOWOBSTRUCTED|\\r
81 SVNSLC_SHOWEXTERNAL|SVNSLC_SHOWINCOMPLETE|SVNSLC_SHOWINEXTERNALS|\\r
82 SVNSLC_SHOWEXTERNALFROMDIFFERENTREPO)\r
83 \r
84 #define SVNSLC_SHOWVERSIONEDBUTNORMAL (SVNSLC_SHOWMODIFIED|SVNSLC_SHOWADDED|\\r
85 SVNSLC_SHOWREMOVED|SVNSLC_SHOWCONFLICTED|SVNSLC_SHOWMISSING|\\r
86 SVNSLC_SHOWREPLACED|SVNSLC_SHOWMERGED|SVNSLC_SHOWIGNORED|SVNSLC_SHOWOBSTRUCTED|\\r
87 SVNSLC_SHOWEXTERNAL|SVNSLC_SHOWINCOMPLETE|SVNSLC_SHOWINEXTERNALS|\\r
88 SVNSLC_SHOWEXTERNALFROMDIFFERENTREPO)\r
89 \r
90 #define SVNSLC_SHOWVERSIONEDBUTNORMALANDEXTERNALSFROMDIFFERENTREPOS (SVNSLC_SHOWMODIFIED|\\r
91 SVNSLC_SHOWADDED|SVNSLC_SHOWREMOVED|SVNSLC_SHOWCONFLICTED|SVNSLC_SHOWMISSING|\\r
92 SVNSLC_SHOWREPLACED|SVNSLC_SHOWMERGED|SVNSLC_SHOWIGNORED|SVNSLC_SHOWOBSTRUCTED|\\r
93 SVNSLC_SHOWINCOMPLETE|SVNSLC_SHOWEXTERNAL|SVNSLC_SHOWINEXTERNALS)\r
94 \r
95 #define SVNSLC_SHOWVERSIONEDBUTNORMALANDEXTERNALS (SVNSLC_SHOWMODIFIED|\\r
96         SVNSLC_SHOWADDED|SVNSLC_SHOWREMOVED|SVNSLC_SHOWCONFLICTED|SVNSLC_SHOWMISSING|\\r
97         SVNSLC_SHOWREPLACED|SVNSLC_SHOWMERGED|SVNSLC_SHOWIGNORED|SVNSLC_SHOWOBSTRUCTED|\\r
98         SVNSLC_SHOWINCOMPLETE)\r
99 \r
100 #define SVNSLC_SHOWALL (SVNSLC_SHOWVERSIONED|SVNSLC_SHOWUNVERSIONED)\r
101 \r
102 #define SVNSLC_POPALL                                   0xFFFFFFFF\r
103 #define SVNSLC_POPCOMPAREWITHBASE               0x00000001\r
104 #define SVNSLC_POPCOMPARE                               0x00000002\r
105 #define SVNSLC_POPGNUDIFF                               0x00000004\r
106 #define SVNSLC_POPREVERT                                0x00000008\r
107 #define SVNSLC_POPUPDATE                                0x00000010\r
108 #define SVNSLC_POPSHOWLOG                               0x00000020\r
109 #define SVNSLC_POPOPEN                                  0x00000040\r
110 #define SVNSLC_POPDELETE                                0x00000080\r
111 #define SVNSLC_POPADD                                   0x00000100\r
112 #define SVNSLC_POPIGNORE                                0x00000200\r
113 #define SVNSLC_POPCONFLICT                              0x00000400\r
114 #define SVNSLC_POPRESOLVE                               0x00000800\r
115 #define SVNSLC_POPLOCK                                  0x00001000\r
116 #define SVNSLC_POPUNLOCK                                0x00002000\r
117 #define SVNSLC_POPUNLOCKFORCE                   0x00004000\r
118 #define SVNSLC_POPEXPLORE                               0x00008000\r
119 #define SVNSLC_POPCOMMIT                                0x00010000\r
120 #define SVNSLC_POPPROPERTIES                    0x00020000\r
121 #define SVNSLC_POPREPAIRMOVE                    0x00040000\r
122 #define SVNSLC_POPCHANGELISTS                   0x00080000\r
123 #define SVNSLC_POPBLAME                                 0x00100000\r
124 \r
125 #define SVNSLC_IGNORECHANGELIST                 _T("ignore-on-commit")\r
126 \r
127 // This gives up to 64 standard properties and menu entries\r
128 // plus 192 user-defined properties (should be plenty).\r
129 // User-defined properties will start at column SVNSLC_NUMCOLUMNS+1\r
130 // but in the registry, we will record them starting at SVNSLC_USERPROPCOLOFFSET.\r
131 \r
132 #define SVNSLC_USERPROPCOLOFFSET        0x40\r
133 #define SVNSLC_USERPROPCOLLIMIT         0xff\r
134 #define SVNSLC_MAXCOLUMNCOUNT           0xff\r
135 \r
136 // Supporting extreamly long user props makes no sense here --\r
137 // especially for binary properties. CString uses a pool allocator\r
138 // that works for up to 256 chars. Make sure we are well below that.\r
139 \r
140 #define SVNSLC_MAXUSERPROPLENGTH        0x70\r
141 \r
142 typedef int (__cdecl *GENERICCOMPAREFN)(const void * elem1, const void * elem2);\r
143 typedef CComCritSecLock<CComCriticalSection> Locker;\r
144 \r
145 /**\r
146  * \ingroup SVN\r
147  * A List control, based on the MFC CListCtrl which shows a list of\r
148  * files with their Subversion status. The control also provides a context\r
149  * menu to do some Subversion tasks on the selected files.\r
150  *\r
151  * This is the main control used in many dialogs to show a list of files to\r
152  * work on.\r
153  */\r
154 class CGitStatusListCtrl :\r
155         public CListCtrl\r
156 {\r
157 public:\r
158         /**\r
159          * Sent to the parent window (using ::SendMessage) after a context menu\r
160          * command has finished if the item count has changed.\r
161          */\r
162         static const UINT SVNSLNM_ITEMCOUNTCHANGED;\r
163         /**\r
164          * Sent to the parent window (using ::SendMessage) when the control needs\r
165          * to be refreshed. Since this is done usually in the parent window using\r
166          * a thread, this message is used to tell the parent to do exactly that.\r
167          */\r
168         static const UINT SVNSLNM_NEEDSREFRESH;\r
169 \r
170         /**\r
171          * Sent to the parent window (using ::SendMessage) when the user drops\r
172          * files on the control. The LPARAM is a pointer to a TCHAR string\r
173          * containing the dropped path.\r
174          */\r
175         static const UINT SVNSLNM_ADDFILE;\r
176 \r
177         /**\r
178          * Sent to the parent window (using ::SendMessage) when the user checks/unchecks\r
179          * one or more items in the control. The WPARAM contains the number of\r
180          * checked items in the control.\r
181          */\r
182         static const UINT SVNSLNM_CHECKCHANGED;\r
183 \r
184         CGitStatusListCtrl(void);\r
185         ~CGitStatusListCtrl(void);\r
186 \r
187         /**\r
188          * \ingroup TortoiseProc\r
189          * Helper class for CGitStatusListCtrl which represents\r
190          * the data for each file shown.\r
191          */\r
192         class FileEntry\r
193         {\r
194         public:\r
195                 FileEntry() : status(git_wc_status_unversioned)\r
196 //                      , copyfrom_rev(GIT_REV_ZERO)\r
197                         , last_commit_date(0)\r
198                         , last_commit_rev(GIT_REV_ZERO)\r
199 //                      , remoterev(GIT_REV_ZERO)\r
200                         , textstatus(git_wc_status_unversioned)\r
201                         , propstatus(git_wc_status_unversioned)\r
202 //                      , remotestatus(git_wc_status_unversioned)\r
203 //                      , remotetextstatus(git_wc_status_unversioned)\r
204 //                      , remotepropstatus(git_wc_status_unversioned)\r
205                         , copied(false)\r
206                         , switched(false)\r
207                         , checked(false)\r
208                         , inunversionedfolder(false)\r
209                         , inexternal(false)\r
210                         , differentrepo(false)\r
211                         , direct(false)\r
212                         , isfolder(false)\r
213                         , isNested(false)\r
214                         , Revision(GIT_REV_ZERO)\r
215                         , isConflicted(false)\r
216 //                      , present_props()\r
217                         , needslock(false)\r
218 ///                     , working_size(SVN_WC_ENTRY_WORKING_SIZE_UNKNOWN)\r
219                         , keeplocal(false)\r
220 //                      , depth(git_depth_unknown)\r
221                 {\r
222                 }\r
223                 const CTGitPath& GetPath() const\r
224                 {\r
225                         return path;\r
226                 }\r
227                 const bool IsChecked() const\r
228                 {\r
229                         return checked;\r
230                 }\r
231                 CString GetRelativeGitPath() const\r
232                 {\r
233                         if (path.IsEquivalentTo(basepath))\r
234                                 return path.GetGitPathString();\r
235                         return path.GetGitPathString().Mid(basepath.GetGitPathString().GetLength()+1);\r
236                 }\r
237 //              const bool IsLocked() const\r
238 //              {\r
239 //                      return !(lock_token.IsEmpty() && lock_remotetoken.IsEmpty());\r
240 //              }\r
241 //              const bool HasNeedsLock() const\r
242 //              {\r
243 //                      return needslock;\r
244 //              }\r
245                 const bool IsFolder() const\r
246                 {\r
247                         return isfolder;\r
248                 }\r
249                 const bool IsInExternal() const\r
250                 {\r
251                         return inexternal;\r
252                 }\r
253                 const bool IsNested() const\r
254                 {\r
255                         return isNested;\r
256                 }\r
257                 const bool IsFromDifferentRepository() const\r
258                 {\r
259                         return differentrepo;\r
260                 }\r
261                 CString GetDisplayName() const\r
262                 {\r
263                         CString const& chopped = path.GetDisplayString(&basepath);\r
264                         if (!chopped.IsEmpty())\r
265                         {\r
266                                 return chopped;\r
267                         }\r
268                         else\r
269                         {\r
270                                 // "Display name" must not be empty.\r
271                                 return path.GetFileOrDirectoryName();\r
272                         }\r
273                 }\r
274                 CString GetChangeList() const\r
275                 {\r
276                         return changelist;\r
277                 }\r
278 //              CString GetURL() const\r
279 //              {\r
280 //                      return url;\r
281 //              }\r
282         public:\r
283                 git_wc_status_kind              status;                                 ///< local status\r
284                 git_wc_status_kind              textstatus;                             ///< local text status\r
285                 git_wc_status_kind              propstatus;                             ///< local property status\r
286                 \r
287         private:\r
288                 CTGitPath                               path;                                   ///< full path of the file\r
289                 CTGitPath                               basepath;                               ///< common ancestor path of all files\r
290                 \r
291                 CString                                 changelist;                             ///< the name of the changelist the item belongs to\r
292                 \r
293                 CString                                 last_commit_author;             ///< the author which last committed this item\r
294                 CTime                                   last_commit_date;               ///< the date when this item was last committed\r
295                 git_revnum_t                    last_commit_rev;                ///< the revision where this item was last committed\r
296                 \r
297                 git_revnum_t                    remoterev;                              ///< the revision in HEAD of the repository\r
298                 bool                                    copied;                                 ///< if the file/folder is added-with-history\r
299                 bool                                    switched;                               ///< if the file/folder is switched to another url\r
300                 bool                                    checked;                                ///< if the file is checked in the list control\r
301                 bool                                    inunversionedfolder;    ///< if the file is inside an unversioned folder\r
302                 bool                                    inexternal;                             ///< if the item is in an external folder\r
303                 bool                                    differentrepo;                  ///< if the item is from a different repository than the rest\r
304                 bool                                    direct;                                 ///< directly included (TRUE) or just a child of a folder\r
305                 bool                                    isfolder;                               ///< TRUE if entry refers to a folder\r
306                 bool                                    isNested;                               ///< TRUE if the folder from a different repository and/or path\r
307                 bool                                    isConflicted;                   ///< TRUE if a file entry is conflicted, i.e. if it has the conflicted paths set\r
308                 bool                                    needslock;                              ///< TRUE if the Git:needs-lock property is set\r
309                 git_revnum_t                    Revision;                               ///< the base revision\r
310 //              PropertyList                    present_props;                  ///< cacheable properties present in BASE\r
311                 bool                                    keeplocal;                              ///< Whether a local copy of this entry should be kept in the working copy after a deletion has been committed\r
312                 git_depth_t                             depth;                                  ///< the depth of this entry\r
313                 friend class CGitStatusListCtrl;\r
314                 friend class CGitStatusListCtrlDropTarget;\r
315         friend class CSorter;\r
316         };\r
317         /**\r
318          * \ingroup TortoiseProc\r
319          * Helper class for CGitStatusListCtrl that represents\r
320          * the columns visible and their order as well as \r
321      * persisting that data in the registry.\r
322      *\r
323      * It assigns logical index values to the (potential) columns:\r
324      * 0 .. GitSLC_NUMCOLUMNS-1 contain the standard attributes\r
325      * GitSLC_USERPROPCOLOFFSET .. GitSLC_MAXCOLUMNCOUNT are user props.\r
326      *\r
327      * The column vector contains the columns that are actually\r
328      * available in the control.\r
329      *\r
330      * Since the set of userprops may change from one WC to another,\r
331      * we also store the settings (width and order) for those\r
332      * userprops that are not used in this WC.\r
333      *\r
334      * A userprop is considered "in use", if the respective column\r
335      * is not hidden or if at least one item has this property set.\r
336          */\r
337         class ColumnManager\r
338         {\r
339     public:\r
340 \r
341         /// construction / destruction\r
342 \r
343         ColumnManager (CListCtrl* control) : control (control) {};\r
344         ~ColumnManager() {};\r
345 \r
346         /// registry access\r
347 \r
348         void ReadSettings (DWORD defaultColumns, const CString& containerName);\r
349         void WriteSettings() const;\r
350 \r
351         /// read column definitions\r
352 \r
353         int GetColumnCount() const;                     ///< total number of columns\r
354         bool IsVisible (int column) const;\r
355                 int GetInvisibleCount() const;\r
356         bool IsRelevant (int column) const;\r
357         bool IsUserProp (int column) const;\r
358         CString GetName (int column) const;\r
359         int GetWidth (int column, bool useDefaults = false) const;\r
360         int GetVisibleWidth (int column, bool useDefaults) const;\r
361 \r
362         /// switch columns on and off\r
363 \r
364         void SetVisible (int column, bool visible);\r
365 \r
366         /// tracking column modifications\r
367 \r
368         void ColumnMoved (int column, int position);\r
369         void ColumnResized (int column);\r
370 \r
371         /// call these to update the user-prop list\r
372         /// (will also auto-insert /-remove new list columns)\r
373 \r
374         void UpdateUserPropList (const std::vector<FileEntry*>& files);\r
375         void UpdateRelevance ( const std::vector<FileEntry*>& files\r
376                              , const std::vector<size_t>& visibleFiles);\r
377 \r
378         /// don't clutter the context menu with irrelevant prop info\r
379 \r
380         bool AnyUnusedProperties() const;\r
381         void RemoveUnusedProps();\r
382 \r
383         /// bring everything back to its "natural" order\r
384 \r
385         void ResetColumns (DWORD defaultColumns);\r
386 \r
387     private:\r
388 \r
389         /// initialization utilities\r
390 \r
391         void ParseUserPropSettings ( const CString& userPropList\r
392                                    , const CString& shownUserProps);\r
393         void ParseWidths (const CString& widths);\r
394         void SetStandardColumnVisibility (DWORD visibility);\r
395         void ParseColumnOrder (const CString& widths);\r
396         \r
397         /// map internal column order onto visible column order\r
398         /// (all invisibles in front)\r
399 \r
400         std::vector<int> GetGridColumnOrder();\r
401         void ApplyColumnOrder();\r
402 \r
403         /// utilities used when writing data to the registry\r
404 \r
405         DWORD GetSelectedStandardColumns() const;\r
406         CString GetUserPropList() const;\r
407         CString GetShownUserProps() const;\r
408         CString GetWidthString() const;\r
409         CString GetColumnOrderString() const;\r
410 \r
411         /// our parent control and its data\r
412 \r
413         CListCtrl* control;\r
414 \r
415         /// where to store in the registry\r
416 \r
417         CString registryPrefix;\r
418 \r
419         /// all columns in their "natural" order\r
420 \r
421         struct ColumnInfo\r
422         {\r
423             int index;          ///< is a user prop when < GitSLC_USERPROPCOLOFFSET\r
424             int width;\r
425             bool visible;\r
426             bool relevant;      ///< set to @a visible, if no *shown* item has that property\r
427         };\r
428 \r
429         std::vector<ColumnInfo> columns;\r
430 \r
431         /// user-defined properties\r
432 \r
433         struct UserProp\r
434         {\r
435             CString name;       ///< is a user prop when < GitSLC_USERPROPCOLOFFSET\r
436             int width;\r
437         };\r
438 \r
439         std::vector<UserProp> userProps;\r
440 \r
441         /// stored result from last UpdateUserPropList() call\r
442 \r
443         std::set<CString> itemProps;\r
444 \r
445         /// global column ordering including unused user props\r
446 \r
447         std::vector<int> columnOrder;\r
448 \r
449     };/**\r
450          * \ingroup TortoiseProc\r
451          * Simple utility class that defines the sort column order.\r
452          */\r
453     class CSorter\r
454     {\r
455     public:\r
456 \r
457         CSorter ( ColumnManager* columnManager\r
458                 , int sortedColumn\r
459                 , bool ascending);\r
460 \r
461         bool operator() ( const CTGitPath* entry1\r
462                         , const CTGitPath* entry2) const;\r
463 \r
464     private:\r
465 \r
466         ColumnManager* columnManager;\r
467         int sortedColumn;\r
468         bool ascending;\r
469     };\r
470 \r
471         /**\r
472          * Initializes the control, sets up the columns.\r
473          * \param dwColumns mask of columns to show. Use the GitSLC_COLxxx defines.\r
474          * \param sColumnInfoContainer Name of a registry key\r
475          *                             where the position and visibility of each column\r
476          *                             is saved and used from. If the registry key\r
477          *                             doesn't exist, the default order is used\r
478          *                             and dwColumns tells which columns are visible.\r
479          * \param dwContextMenus mask of context menus to be active, not all make sense for every use of this control.\r
480          *                       Use the GitSLC_POPxxx defines.\r
481          * \param bHasCheckboxes TRUE if the control should show check boxes on the left of each file entry.\r
482          */\r
483         void Init(DWORD dwColumns, const CString& sColumnInfoContainer, DWORD dwContextMenus = (SVNSLC_POPALL ^ SVNSLC_POPCOMMIT), bool bHasCheckboxes = true);\r
484         /**\r
485          * Sets a background image for the list control.\r
486          * The image is shown in the right bottom corner.\r
487          * \param nID the resource ID of the bitmap to use as the background\r
488          */\r
489         bool SetBackgroundImage(UINT nID);\r
490         /**\r
491          * Makes the 'ignore' context menu only ignore the files and not add the\r
492          * folder which gets the Git:ignore property changed to the list.\r
493          * This is needed e.g. for the Add-dialog, where the modified folder\r
494          * showing up would break the resulting "add" command.\r
495          */\r
496         void SetIgnoreRemoveOnly(bool bRemoveOnly = true) {m_bIgnoreRemoveOnly = bRemoveOnly;}\r
497         /**\r
498          * The unversioned items are by default shown after all other files in the list.\r
499          * If that behavior should be changed, set this value to false.\r
500          */\r
501         void PutUnversionedLast(bool bLast) {m_bUnversionedLast = bLast;}\r
502         /**\r
503          * Fetches the Subversion status of all files and stores the information\r
504          * about them in an internal array.\r
505          * \param sFilePath path to a file which contains a list of files and/or folders for which to\r
506          *                  fetch the status, separated by newlines.\r
507          * \param bUpdate TRUE if the remote status is requested too.\r
508          * \return TRUE on success.\r
509          */\r
510         BOOL GetStatus ( const CTGitPathList& pathList\r
511                    , bool bUpdate = false\r
512                    , bool bShowIgnores = false\r
513                    , bool bShowUserProps = false);\r
514 \r
515         /**\r
516          * Populates the list control with the previously (with GetStatus) gathered status information.\r
517          * \param dwShow mask of file types to show. Use the GitSLC_SHOWxxx defines.\r
518          * \param dwCheck mask of file types to check. Use GitLC_SHOWxxx defines. Default (0) means 'use the entry's stored check status'\r
519          */\r
520         void Show(DWORD dwShow, DWORD dwCheck = 0, bool bShowFolders = true);\r
521         void Show(DWORD dwShow, const CTGitPathList& checkedList, bool bShowFolders = true);\r
522 \r
523         /**\r
524          * Copies the selected entries in the control to the clipboard. The entries\r
525          * are separated by newlines.\r
526          * \param dwCols the columns to copy. Each column is separated by a tab.\r
527          */\r
528         bool CopySelectedEntriesToClipboard(DWORD dwCols);\r
529 \r
530         /**\r
531          * If during the call to GetStatus() some Git:externals are found from different\r
532          * repositories than the first one checked, then this method returns TRUE.\r
533          */\r
534         BOOL HasExternalsFromDifferentRepos() const {return m_bHasExternalsFromDifferentRepos;}\r
535 \r
536         /**\r
537          * If during the call to GetStatus() some Git:externals are found then this method returns TRUE.\r
538          */\r
539         BOOL HasExternals() const {return m_bHasExternals;}\r
540 \r
541         /**\r
542          * If unversioned files are found (but not necessarily shown) TRUE is returned.\r
543          */\r
544         BOOL HasUnversionedItems() {return m_bHasUnversionedItems;}\r
545 \r
546         /**\r
547          * If there are any locks in the working copy, TRUE is returned\r
548          */\r
549         BOOL HasLocks() const {return m_bHasLocks;}\r
550 \r
551         /**\r
552          * If there are any change lists defined in the working copy, TRUE is returned\r
553          */\r
554         BOOL HasChangeLists() const {return m_bHasChangeLists;}\r
555 \r
556         /**\r
557          * Returns the file entry data for the list control index.\r
558          */\r
559         CGitStatusListCtrl::FileEntry * GetListEntry(UINT_PTR index);\r
560 \r
561         /**\r
562          * Returns the file entry data for the specified path.\r
563          * \note The entry might not be shown in the list control.\r
564          */\r
565         CGitStatusListCtrl::FileEntry * GetListEntry(const CTGitPath& path);\r
566 \r
567         /**\r
568          * Returns the index of the list control entry with the specified path,\r
569          * or -1 if the path is not in the list control.\r
570          */\r
571         int GetIndex(const CTGitPath& path);\r
572 \r
573         /**\r
574          * Returns the file entry data for the specified path in the list control.\r
575          */\r
576         CGitStatusListCtrl::FileEntry * GetVisibleListEntry(const CTGitPath& path);\r
577 \r
578         /**\r
579          * Returns a String containing some statistics like number of modified, normal, deleted,...\r
580          * files.\r
581          */\r
582         CString GetStatisticsString();\r
583 \r
584         /**\r
585          * Set a static control which will be updated automatically with\r
586          * the number of selected and total files shown in the list control.\r
587          */\r
588         void SetStatLabel(CWnd * pStatLabel){m_pStatLabel = pStatLabel;};\r
589 \r
590         /**\r
591          * Set a tri-state checkbox which is updated automatically if the\r
592          * user checks/unchecks file entries in the list control to indicate\r
593          * if all files are checked, none are checked or some are checked.\r
594          */\r
595         void SetSelectButton(CButton * pButton) {m_pSelectButton = pButton;}\r
596 \r
597         /**\r
598          * Set a button which is de-/activated automatically. The button is\r
599          * only set active if at least one item is selected.\r
600          */\r
601         void SetConfirmButton(CButton * pButton) {m_pConfirmButton = pButton;}\r
602 \r
603         /**\r
604          * Select/unselect all entries in the list control.\r
605          * \param bSelect TRUE to check, FALSE to uncheck.\r
606          */\r
607         void SelectAll(bool bSelect, bool bIncludeNoCommits = false);\r
608 \r
609         /** Set a checkbox on an entry in the listbox\r
610          * Keeps the listctrl checked state and the FileEntry's checked flag in sync\r
611          */\r
612         void SetEntryCheck(CTGitPath* pEntry, int listboxIndex, bool bCheck);\r
613 \r
614         /** Write a list of the checked items' paths into a path list\r
615          */\r
616         void WriteCheckedNamesToPathList(CTGitPathList& pathList);\r
617 \r
618         /** fills in \a lMin and \a lMax with the lowest/highest revision of all\r
619          * files/folders in the working copy.\r
620          * \param bShownOnly if true, the min/max revisions are calculated only for shown items\r
621          * \param bCheckedOnly if true, the min/max revisions are calculated only for items \r
622          *                   which are checked.\r
623          * \remark Since an item can only be checked if it is visible/shown in the list control\r
624          *         bShownOnly is automatically set to true if bCheckedOnly is true\r
625          */\r
626         void GetMinMaxRevisions(git_revnum_t& rMin, git_revnum_t& rMax, bool bShownOnly, bool bCheckedOnly);\r
627 \r
628         /**\r
629          * Returns the parent directory of all entries in the control.\r
630          * if \a bStrict is set to false, then the paths passed to the control\r
631          * to fetch the status (in GetStatus()) are used if possible.\r
632          */\r
633         CTGitPath GetCommonDirectory(bool bStrict);\r
634 \r
635         /**\r
636          * Returns the parent url of all entries in the control.\r
637          * if \a bStrict is set to false, then the paths passed to the control\r
638          * to fetch the status (in GetStatus()) are used if possible.\r
639          */\r
640         CTGitPath GetCommonURL(bool bStrict);\r
641 \r
642         /**\r
643          * Sets a pointer to a boolean variable which is checked periodically\r
644          * during the status fetching. As soon as the variable changes to true,\r
645          * the operations stops.\r
646          */\r
647         void SetCancelBool(bool * pbCanceled) {m_pbCanceled = pbCanceled;}\r
648 \r
649         /**\r
650          * Sets the string shown in the control while the status is fetched.\r
651          * If not set, it defaults to "please wait..."\r
652          */\r
653         void SetBusyString(const CString& str) {m_sBusy = str;}\r
654         void SetBusyString(UINT id) {m_sBusy.LoadString(id);}\r
655 \r
656         /**\r
657          * Sets the string shown in the control if no items are shown. This\r
658          * can happen for example if there's nothing modified and the unversioned\r
659          * files aren't shown either, so there's nothing to commit.\r
660          * If not set, it defaults to "file list is empty".\r
661          */\r
662         void SetEmptyString(const CString& str) {m_sEmpty = str;}\r
663         void SetEmptyString(UINT id) {m_sEmpty.LoadString(id);}\r
664 \r
665         /**\r
666          * Determines if the control should recurse into unversioned folders\r
667          * when fetching the status. The default behavior is defined by the\r
668          * registry key HKCU\Software\TortoiseGit\UnversionedRecurse, which\r
669          * is read in the Init() method.\r
670          * If you want to change the behavior, call this method *after*\r
671          * calling Init().\r
672          */\r
673         void SetUnversionedRecurse(bool bUnversionedRecurse) {m_bUnversionedRecurse = bUnversionedRecurse;}\r
674 \r
675         /**\r
676          * Returns the number of selected items\r
677          */\r
678         LONG GetSelected(){return m_nSelected;};\r
679 \r
680         /**\r
681          * Enables dropping of files on the control.\r
682          */\r
683         bool EnableFileDrop();\r
684 \r
685         /**\r
686          * Checks if the path already exists in the list.\r
687          */\r
688         bool HasPath(const CTGitPath& path);\r
689         /**\r
690          * Checks if the path is shown/visible in the list control.\r
691          */\r
692         bool IsPathShown(const CTGitPath& path);\r
693         /**\r
694          * Forces the children to be checked when the parent folder is checked,\r
695          * and the parent folder to be unchecked if one of its children is unchecked.\r
696          */\r
697         void CheckChildrenWithParent(bool bCheck) {m_bCheckChildrenWithParent = bCheck;}\r
698 \r
699         /**\r
700          * Allows checking the items if change lists are present. If set to false,\r
701          * items are not checked if at least one changelist is available.\r
702          */\r
703         void CheckIfChangelistsArePresent(bool bCheck) {m_bCheckIfGroupsExist = bCheck;}\r
704         /**\r
705          * Returns the currently used show flags passed to the Show() method.\r
706          */\r
707         DWORD GetShowFlags() {return m_dwShow;}\r
708 public:\r
709         CString GetLastErrorMessage() {return m_sLastError;}\r
710 \r
711         void Block(BOOL block, BOOL blockUI) {m_bBlock = block; m_bBlockUI = blockUI;}\r
712 \r
713         LONG                                            m_nTargetCount;         ///< number of targets in the file passed to GetStatus()\r
714 \r
715         CString                                         m_sURL;                         ///< the URL of the target or "(multiple targets)"\r
716 \r
717         GitRev                                          m_HeadRev;                      ///< the HEAD revision of the repository if bUpdate was TRUE\r
718 \r
719         CString                                         m_sUUID;                        ///< the UUID of the associated repository\r
720 \r
721         DECLARE_MESSAGE_MAP()\r
722 \r
723 private:\r
724         void SaveColumnWidths(bool bSaveToRegistry = false);\r
725         void Sort();    ///< Sorts the control by columns\r
726         void AddEntry(FileEntry * entry, WORD langID, int listIndex);   ///< add an entry to the control\r
727         void RemoveListEntry(int index);        ///< removes an entry from the listcontrol and both arrays\r
728         bool BuildStatistics(); ///< build the statistics and correct the case of files/folders\r
729         void StartDiff(int fileindex);  ///< start the external diff program\r
730 \r
731     /// fetch all user properties for all items\r
732     void FetchUserProperties();\r
733 \r
734         /// Process one line of the command file supplied to GetStatus\r
735         bool FetchStatusForSingleTarget(GitConfig& config, GitStatus& status, const CTGitPath& target, \r
736                 bool bFetchStatusFromRepository, CStringA& strCurrentRepositoryUUID, CTGitPathList& arExtPaths, \r
737                 bool bAllDirect, git_depth_t depth = git_depth_infinity, bool bShowIgnores = false);\r
738 \r
739         /// Create 'status' data for each item in an unversioned folder\r
740         void AddUnversionedFolder(const CTGitPath& strFolderName, const CTGitPath& strBasePath, GitConfig * config);\r
741 \r
742         /// Read the all the other status items which result from a single GetFirstStatus call\r
743         void ReadRemainingItemsStatus(GitStatus& status, const CTGitPath& strBasePath, CStringA& strCurrentRepositoryUUID, CTGitPathList& arExtPaths, GitConfig * config, bool bAllDirect);\r
744 \r
745         /// Clear the status vector (contains custodial pointers)\r
746         void ClearStatusArray();\r
747 \r
748         /// Sort predicate function - Compare the paths of two entries without regard to case\r
749         static bool EntryPathCompareNoCase(const FileEntry* pEntry1, const FileEntry* pEntry2);\r
750 \r
751         /// Predicate used to build a list of only the versioned entries of the FileEntry array\r
752         static bool IsEntryVersioned(const FileEntry* pEntry1);\r
753 \r
754         /// Look up the relevant show flags for a particular Git status value\r
755         DWORD GetShowFlagsFromGitStatus(git_wc_status_kind status);\r
756 \r
757         /// Build a FileEntry item and add it to the FileEntry array\r
758         const FileEntry* AddNewFileEntry(\r
759                 const git_wc_status2_t* pGitStatus,  // The return from the Git GetStatus functions\r
760                 const CTGitPath& path,                          // The path of the item we're adding\r
761                 const CTGitPath& basePath,                      // The base directory for this status build\r
762                 bool bDirectItem,                                       // Was this item the first found by GetFirstFileStatus or by a subsequent GetNextFileStatus call\r
763                 bool bInExternal,                                       // Are we in an 'external' folder\r
764                 bool bEntryfromDifferentRepo            // if the entry is from a different repository\r
765                 );\r
766 \r
767         /// Adjust the checkbox-state on all descendants of a specific item\r
768         void SetCheckOnAllDescendentsOf(const FileEntry* parentEntry, bool bCheck);\r
769 \r
770         /// Build a path list of all the selected items in the list (NOTE - SELECTED, not CHECKED)\r
771         void FillListOfSelectedItemPaths(CTGitPathList& pathList, bool bNoIgnored = false);\r
772 \r
773         /// Enables/Disables group view and adds all groups to the list control.\r
774         /// If bForce is true, then group view is enabled and the 'null' group is added.\r
775         bool PrepareGroups(bool bForce = false);\r
776         /// Returns the group number to which the group header belongs\r
777         /// If the point is not over a group header, -1 is returned\r
778         int GetGroupFromPoint(POINT * ppt);\r
779         /// Returns the number of change lists the selection has\r
780         size_t GetNumberOfChangelistsInSelection();\r
781 \r
782         /// Puts the item to the corresponding group\r
783         bool SetItemGroup(int item, int groupindex);\r
784 \r
785         void CheckEntry(int index, int nListItems);\r
786         void UncheckEntry(int index, int nListItems);\r
787 \r
788         /// sends an GitSLNM_CHECKCHANGED notification to the parent\r
789         void NotifyCheck();\r
790 \r
791         int CellRectFromPoint(CPoint& point, RECT *cellrect, int *col) const;\r
792 \r
793         void OnContextMenuList(CWnd * pWnd, CPoint point);\r
794         void OnContextMenuGroup(CWnd * pWnd, CPoint point);\r
795         void OnContextMenuHeader(CWnd * pWnd, CPoint point);\r
796 \r
797         virtual void PreSubclassWindow();\r
798         virtual BOOL PreTranslateMessage(MSG* pMsg);\r
799         virtual INT_PTR OnToolHitTest(CPoint point, TOOLINFO* pTI) const;\r
800         afx_msg void OnBeginDrag(NMHDR* pNMHDR, LRESULT* pResult);\r
801         afx_msg BOOL OnToolTipText(UINT id, NMHDR *pNMHDR, LRESULT *pResult);\r
802         afx_msg void OnHdnItemclick(NMHDR *pNMHDR, LRESULT *pResult);\r
803         afx_msg void OnLvnItemchanging(NMHDR *pNMHDR, LRESULT *pResult);\r
804         afx_msg BOOL OnLvnItemchanged(NMHDR *pNMHDR, LRESULT *pResult);\r
805     afx_msg void OnColumnResized(NMHDR *pNMHDR, LRESULT *pResult);\r
806     afx_msg void OnColumnMoved(NMHDR *pNMHDR, LRESULT *pResult);\r
807     afx_msg void OnContextMenu(CWnd* pWnd, CPoint point);\r
808 \r
809         void CreateChangeList(const CString& name);\r
810 \r
811         afx_msg void OnNMDblclk(NMHDR *pNMHDR, LRESULT *pResult);\r
812         afx_msg void OnLvnGetInfoTip(NMHDR *pNMHDR, LRESULT *pResult);\r
813         afx_msg void OnNMCustomdraw(NMHDR *pNMHDR, LRESULT *pResult);\r
814         afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);\r
815         afx_msg UINT OnGetDlgCode();\r
816         afx_msg void OnNMReturn(NMHDR *pNMHDR, LRESULT *pResult);\r
817         afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);\r
818         afx_msg void OnPaint();\r
819         afx_msg void OnHdnBegintrack(NMHDR *pNMHDR, LRESULT *pResult);\r
820         afx_msg void OnHdnItemchanging(NMHDR *pNMHDR, LRESULT *pResult);\r
821         afx_msg void OnDestroy();\r
822 \r
823 private:\r
824         bool *                                          m_pbCanceled;\r
825         bool                                        m_bAscending;               ///< sort direction\r
826         int                                             m_nSortedColumn;        ///< which column to sort\r
827         bool                                            m_bHasCheckboxes;\r
828         bool                                            m_bUnversionedLast;\r
829         bool                                            m_bHasExternalsFromDifferentRepos;\r
830         bool                                            m_bHasExternals;\r
831         BOOL                                            m_bHasUnversionedItems;\r
832         bool                                            m_bHasLocks;\r
833         bool                                            m_bHasChangeLists;\r
834         //typedef std::vector<FileEntry*> FileEntryVector;\r
835         //FileEntryVector                               m_arStatusArray;\r
836         std::vector<CTGitPath*>         m_arStatusArray;\r
837         std::vector<size_t>                     m_arListArray;\r
838         std::map<CString, int>      m_changelists;\r
839         bool                                            m_bHasIgnoreGroup;\r
840         //CTGitPathList                         m_ConflictFileList;\r
841         CTGitPathList                           m_StatusFileList;\r
842         CTGitPathList                           m_UnRevFileList;\r
843         CTGitPathList                           m_IgnoreFileList;\r
844         //CTGitPathList                         m_StatusUrlList;\r
845         CString                                         m_sLastError;\r
846 \r
847         LONG                                            m_nUnversioned;\r
848         LONG                                            m_nNormal;\r
849         LONG                                            m_nModified;\r
850         LONG                                            m_nAdded;\r
851         LONG                                            m_nDeleted;\r
852         LONG                                            m_nConflicted;\r
853         LONG                                            m_nTotal;\r
854         LONG                                            m_nSelected;\r
855 \r
856         DWORD                                           m_dwDefaultColumns;\r
857         DWORD                                           m_dwShow;\r
858         bool                                            m_bShowFolders;\r
859         bool                                            m_bShowIgnores;\r
860         bool                                            m_bUpdate;\r
861         DWORD                                           m_dwContextMenus;\r
862         BOOL                                            m_bBlock;\r
863         BOOL                                            m_bBlockUI;\r
864         bool                                            m_bBusy;\r
865         bool                                            m_bEmpty;\r
866         bool                                            m_bIgnoreRemoveOnly;\r
867         bool                                            m_bCheckIfGroupsExist;\r
868         bool                                            m_bFileDropsEnabled;\r
869         bool                                            m_bOwnDrag;\r
870 \r
871         int                                                     m_nIconFolder;\r
872 \r
873         CWnd *                                          m_pStatLabel;\r
874         CButton *                                       m_pSelectButton;\r
875         CButton *                                       m_pConfirmButton;\r
876         CColors                                         m_Colors;\r
877 \r
878         CString                                         m_sEmpty;\r
879         CString                                         m_sBusy;\r
880         CString                                         m_sNoPropValueText;\r
881 \r
882         bool                                            m_bUnversionedRecurse;\r
883 \r
884         bool                                            m_bCheckChildrenWithParent;\r
885         CGitStatusListCtrlDropTarget * m_pDropTarget;\r
886 \r
887     ColumnManager               m_ColumnManager;\r
888 \r
889         std::map<CString,bool>          m_mapFilenameToChecked; ///< Remember manually de-/selected items\r
890         CComCriticalSection                     m_critSec;\r
891 \r
892         friend class CGitStatusListCtrlDropTarget;\r
893 public:\r
894         enum\r
895         {\r
896                 FILELIST_MODIFY= 0x1,\r
897                 FILELIST_UNVER = 0x2,\r
898                 FILELIST_IGNORE =0x4\r
899         };\r
900 public:\r
901         int UpdateFileList(git_revnum_t hash);\r
902         int UpdateFileList(int mask, bool once=true);\r
903         int UpdateUnRevFileList();\r
904         int UpdateIgnoreFileList();\r
905         void AddEntry(CTGitPath* path, WORD langID, int ListIndex);\r
906         int m_FileLoaded;\r
907 };\r
908 \r
909 #if 0\r
910 class CGitStatusListCtrlDropTarget : public CIDropTarget\r
911 {\r
912 public:\r
913         CGitStatusListCtrlDropTarget(CGitStatusListCtrl * pGitStatusListCtrl):CIDropTarget(pGitStatusListCtrl->m_hWnd){m_pGitStatusListCtrl = pGitStatusListCtrl;}\r
914 \r
915         virtual bool OnDrop(FORMATETC* pFmtEtc, STGMEDIUM& medium, DWORD * /*pdwEffect*/, POINTL pt);\r
916         virtual HRESULT STDMETHODCALLTYPE DragOver(DWORD grfKeyState, POINTL pt, DWORD __RPC_FAR *pdwEffect);\r
917 private:\r
918         CGitStatusListCtrl * m_pGitStatusListCtrl;\r
919 };\r
920 #endif