Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

278 lines
8.3 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Contains a list of files, determines their perforce status
  4. //
  5. // $NoKeywords: $
  6. //===========================================================================//
  7. #include <vgui_controls/PerforceFileExplorer.h>
  8. #include <vgui_controls/PerforceFileList.h>
  9. #include <vgui_controls/ComboBox.h>
  10. #include <vgui_controls/Button.h>
  11. #include <vgui_controls/Tooltip.h>
  12. #include "tier1/KeyValues.h"
  13. #include "vgui/ISystem.h"
  14. #include "filesystem.h"
  15. #include <ctype.h>
  16. #include "p4lib/ip4.h"
  17. #include "tier2/tier2.h"
  18. // memdbgon must be the last include file in a .cpp file!!!
  19. #include <tier0/memdbgon.h>
  20. using namespace vgui;
  21. //-----------------------------------------------------------------------------
  22. // Purpose: Constructor
  23. //-----------------------------------------------------------------------------
  24. PerforceFileExplorer::PerforceFileExplorer( Panel *pParent, const char *pPanelName ) :
  25. BaseClass( pParent, pPanelName )
  26. {
  27. m_pFileList = new PerforceFileList( this, "PerforceFileList" );
  28. // Get the list of available drives and put them in a menu here.
  29. // Start with the directory we are in.
  30. m_pFullPathCombo = new ComboBox( this, "FullPathCombo", 8, false );
  31. m_pFullPathCombo->GetTooltip()->SetTooltipFormatToSingleLine();
  32. char pFullPath[MAX_PATH];
  33. g_pFullFileSystem->GetCurrentDirectory( pFullPath, sizeof(pFullPath) );
  34. SetCurrentDirectory( pFullPath );
  35. m_pFullPathCombo->AddActionSignalTarget( this );
  36. m_pFolderUpButton = new Button(this, "FolderUpButton", "", this);
  37. m_pFolderUpButton->GetTooltip()->SetText( "#FileOpenDialog_ToolTip_Up" );
  38. m_pFolderUpButton->SetCommand( new KeyValues( "FolderUp" ) );
  39. }
  40. //-----------------------------------------------------------------------------
  41. // Purpose: Destructor
  42. //-----------------------------------------------------------------------------
  43. PerforceFileExplorer::~PerforceFileExplorer()
  44. {
  45. }
  46. //-----------------------------------------------------------------------------
  47. // Inherited from Frame
  48. //-----------------------------------------------------------------------------
  49. void PerforceFileExplorer::ApplySchemeSettings( IScheme *pScheme )
  50. {
  51. BaseClass::ApplySchemeSettings( pScheme );
  52. m_pFolderUpButton->AddImage( scheme()->GetImage( "resource/icon_folderup", false), -3 );
  53. }
  54. //-----------------------------------------------------------------------------
  55. // Inherited from Frame
  56. //-----------------------------------------------------------------------------
  57. void PerforceFileExplorer::PerformLayout()
  58. {
  59. BaseClass::PerformLayout();
  60. int x, y, w, h;
  61. GetClientArea( x, y, w, h );
  62. m_pFullPathCombo->SetBounds( x, y + 6, w - 30, 24 );
  63. m_pFolderUpButton->SetBounds( x + w - 24, y + 6, 24, 24 );
  64. m_pFileList->SetBounds( x, y + 36, w, h - 36 );
  65. }
  66. //-----------------------------------------------------------------------------
  67. // Sets the current directory
  68. //-----------------------------------------------------------------------------
  69. void PerforceFileExplorer::SetCurrentDirectory( const char *pFullPath )
  70. {
  71. if ( !pFullPath )
  72. return;
  73. while ( isspace( *pFullPath ) )
  74. {
  75. ++pFullPath;
  76. }
  77. if ( !pFullPath[0] )
  78. return;
  79. m_CurrentDirectory = pFullPath;
  80. m_CurrentDirectory.StripTrailingSlash();
  81. m_CurrentDirectory.FixSlashes();
  82. PopulateFileList();
  83. PopulateDriveList();
  84. char pCurrentDirectory[ MAX_PATH ];
  85. m_pFullPathCombo->GetText( pCurrentDirectory, sizeof(pCurrentDirectory) );
  86. if ( Q_stricmp( m_CurrentDirectory.Get(), pCurrentDirectory ) )
  87. {
  88. char pNewDirectory[ MAX_PATH ];
  89. Q_snprintf( pNewDirectory, sizeof(pNewDirectory), "%s\\", m_CurrentDirectory.Get() );
  90. m_pFullPathCombo->SetText( pNewDirectory );
  91. m_pFullPathCombo->GetTooltip()->SetText( pNewDirectory );
  92. }
  93. }
  94. //-----------------------------------------------------------------------------
  95. // Purpose:
  96. //-----------------------------------------------------------------------------
  97. void PerforceFileExplorer::PopulateDriveList()
  98. {
  99. char pFullPath[MAX_PATH * 4];
  100. char pSubDirPath[MAX_PATH * 4];
  101. Q_strncpy( pFullPath, m_CurrentDirectory.Get(), sizeof( pFullPath ) );
  102. Q_strncpy( pSubDirPath, m_CurrentDirectory.Get(), sizeof( pSubDirPath ) );
  103. m_pFullPathCombo->DeleteAllItems();
  104. // populate the drive list
  105. char buf[512];
  106. int len = system()->GetAvailableDrives(buf, 512);
  107. char *pBuf = buf;
  108. for (int i=0; i < len / 4; i++)
  109. {
  110. m_pFullPathCombo->AddItem(pBuf, NULL);
  111. // is this our drive - add all subdirectories
  112. if ( !_strnicmp( pBuf, pFullPath, 2 ) )
  113. {
  114. int indent = 0;
  115. char *pData = pFullPath;
  116. while (*pData)
  117. {
  118. if (*pData == '\\')
  119. {
  120. if (indent > 0)
  121. {
  122. memset(pSubDirPath, ' ', indent);
  123. memcpy(pSubDirPath+indent, pFullPath, pData-pFullPath+1);
  124. pSubDirPath[indent+pData-pFullPath+1] = 0;
  125. m_pFullPathCombo->AddItem( pSubDirPath, NULL );
  126. }
  127. indent += 2;
  128. }
  129. pData++;
  130. }
  131. }
  132. pBuf += 4;
  133. }
  134. }
  135. //-----------------------------------------------------------------------------
  136. // Purpose: Fill the filelist with the names of all the files in the current directory
  137. //-----------------------------------------------------------------------------
  138. void PerforceFileExplorer::PopulateFileList()
  139. {
  140. // clear the current list
  141. m_pFileList->RemoveAllFiles();
  142. // Create filter string
  143. char pFullFoundPath[MAX_PATH];
  144. char pFilter[MAX_PATH+3];
  145. Q_snprintf( pFilter, sizeof(pFilter), "%s\\*.*", m_CurrentDirectory.Get() );
  146. // Find all files on disk
  147. FileFindHandle_t h;
  148. const char *pFileName = g_pFullFileSystem->FindFirstEx( pFilter, NULL, &h );
  149. for ( ; pFileName; pFileName = g_pFullFileSystem->FindNext( h ) )
  150. {
  151. if ( !Q_stricmp( pFileName, ".." ) || !Q_stricmp( pFileName, "." ) )
  152. continue;
  153. if ( !Q_IsAbsolutePath( pFileName ) )
  154. {
  155. Q_snprintf( pFullFoundPath, sizeof(pFullFoundPath), "%s\\%s", m_CurrentDirectory.Get(), pFileName );
  156. pFileName = pFullFoundPath;
  157. }
  158. int nItemID = m_pFileList->AddFile( pFileName, true );
  159. m_pFileList->RefreshPerforceState( nItemID, true, NULL );
  160. }
  161. g_pFullFileSystem->FindClose( h );
  162. // Now find all files in perforce
  163. CUtlVector<P4File_t> &fileList = p4->GetFileList( m_CurrentDirectory );
  164. int nCount = fileList.Count();
  165. for ( int i = 0; i < nCount; ++i )
  166. {
  167. pFileName = p4->String( fileList[i].m_sLocalFile );
  168. if ( !pFileName[0] )
  169. continue;
  170. int nItemID = m_pFileList->FindFile( pFileName );
  171. bool bFileExists = true;
  172. if ( nItemID == m_pFileList->InvalidItemID() )
  173. {
  174. // If it didn't find it, the file must not exist
  175. // since it already would have added it above
  176. bFileExists = false;
  177. nItemID = m_pFileList->AddFile( pFileName, false, fileList[i].m_bDir );
  178. }
  179. m_pFileList->RefreshPerforceState( nItemID, bFileExists, &fileList[i] );
  180. }
  181. m_pFileList->SortList();
  182. }
  183. //-----------------------------------------------------------------------------
  184. // Purpose: Handle an item in the Drive combo box being selected
  185. //-----------------------------------------------------------------------------
  186. void PerforceFileExplorer::OnTextChanged( KeyValues *kv )
  187. {
  188. Panel *pPanel = (Panel *)kv->GetPtr( "panel", NULL );
  189. // first check which control had its text changed!
  190. if ( pPanel == m_pFullPathCombo )
  191. {
  192. char pCurrentDirectory[ MAX_PATH ];
  193. m_pFullPathCombo->GetText( pCurrentDirectory, sizeof(pCurrentDirectory) );
  194. SetCurrentDirectory( pCurrentDirectory );
  195. return;
  196. }
  197. }
  198. //-----------------------------------------------------------------------------
  199. // Called when the file list was doubleclicked
  200. //-----------------------------------------------------------------------------
  201. void PerforceFileExplorer::OnItemDoubleClicked()
  202. {
  203. if ( m_pFileList->GetSelectedItemsCount() != 1 )
  204. return;
  205. int nItemID = m_pFileList->GetSelectedItem( 0 );
  206. if ( m_pFileList->IsDirectoryItem( nItemID ) )
  207. {
  208. const char *pDirectoryName = m_pFileList->GetFile( nItemID );
  209. SetCurrentDirectory( pDirectoryName );
  210. }
  211. }
  212. //-----------------------------------------------------------------------------
  213. // Called when the folder up button was hit
  214. //-----------------------------------------------------------------------------
  215. void PerforceFileExplorer::OnFolderUp()
  216. {
  217. char pUpDirectory[MAX_PATH];
  218. Q_strncpy( pUpDirectory, m_CurrentDirectory.Get(), sizeof(pUpDirectory) );
  219. Q_StripLastDir( pUpDirectory, sizeof(pUpDirectory) );
  220. Q_StripTrailingSlash( pUpDirectory );
  221. // This occurs at the root directory
  222. if ( !Q_stricmp( pUpDirectory, "." ) )
  223. return;
  224. SetCurrentDirectory( pUpDirectory );
  225. }