From f56bb35301836e56582a575a75864392a0177875 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20P=2E=20Tjern=C3=B8?= Date: Mon, 2 Dec 2013 19:31:46 -0800 Subject: Fix line endings. WHAMMY. --- mp/src/vgui2/vgui_controls/PerforceFileList.cpp | 1140 +++++++++++------------ 1 file changed, 570 insertions(+), 570 deletions(-) (limited to 'mp/src/vgui2/vgui_controls/PerforceFileList.cpp') diff --git a/mp/src/vgui2/vgui_controls/PerforceFileList.cpp b/mp/src/vgui2/vgui_controls/PerforceFileList.cpp index 618f4443..de7fa32a 100644 --- a/mp/src/vgui2/vgui_controls/PerforceFileList.cpp +++ b/mp/src/vgui2/vgui_controls/PerforceFileList.cpp @@ -1,570 +1,570 @@ -//========= Copyright Valve Corporation, All rights reserved. ============// -// -// Purpose: Contains a list of files, determines their perforce status -// -// $NoKeywords: $ -//===========================================================================// - -#include -#include -#include -#include -#include "tier1/KeyValues.h" -#include -#include "filesystem.h" -#include "p4lib/ip4.h" -#include "tier2/tier2.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include - - -using namespace vgui; - - -static int ListFileNameSortFunc(ListPanel *pPanel, const ListPanelItem &item1, const ListPanelItem &item2 ) -{ - NOTE_UNUSED( pPanel ); - - bool dir1 = item1.kv->GetInt("directory") == 1; - bool dir2 = item2.kv->GetInt("directory") == 1; - - // if they're both not directories of files, return if dir1 is a directory (before files) - if ( dir1 != dir2 ) - { - return dir1 ? -1 : 1; - } - - const char *string1 = item1.kv->GetString("text"); - const char *string2 = item2.kv->GetString("text"); - - // YWB: Mimic windows behavior where filenames starting with numbers are sorted based on numeric part - int num1 = Q_atoi( string1 ); - int num2 = Q_atoi( string2 ); - - if ( num1 != 0 && - num2 != 0 ) - { - if ( num1 < num2 ) - return -1; - else if ( num1 > num2 ) - return 1; - } - - // Push numbers before everything else - if ( num1 != 0 ) - { - return -1; - } - - // Push numbers before everything else - if ( num2 != 0 ) - { - return 1; - } - - return Q_stricmp( string1, string2 ); -} - -static int ListBaseStringSortFunc(ListPanel *pPanel, const ListPanelItem &item1, const ListPanelItem &item2, char const *fieldName ) -{ - bool dir1 = item1.kv->GetInt("directory") == 1; - bool dir2 = item2.kv->GetInt("directory") == 1; - - // if they're both not directories of files, return if dir1 is a directory (before files) - if (dir1 != dir2) - { - return -1; - } - - const char *string1 = item1.kv->GetString(fieldName); - const char *string2 = item2.kv->GetString(fieldName); - int cval = Q_stricmp(string1, string2); - if ( cval == 0 ) - { - // Use filename to break ties - return ListFileNameSortFunc( pPanel, item1, item2 ); - } - - return cval; -} - -static int ListBaseIntegerSortFunc(ListPanel *pPanel, const ListPanelItem &item1, const ListPanelItem &item2, char const *fieldName ) -{ - bool dir1 = item1.kv->GetInt("directory") == 1; - bool dir2 = item2.kv->GetInt("directory") == 1; - - // if they're both not directories of files, return if dir1 is a directory (before files) - if (dir1 != dir2) - { - return -1; - } - - int i1 = item1.kv->GetInt(fieldName); - int i2 = item2.kv->GetInt(fieldName); - if ( i1 == i2 ) - { - // Use filename to break ties - return ListFileNameSortFunc( pPanel, item1, item2 ); - } - - return ( i1 < i2 ) ? -1 : 1; -} - -static int ListFileSizeSortFunc(ListPanel *pPanel, const ListPanelItem &item1, const ListPanelItem &item2 ) -{ - return ListBaseIntegerSortFunc( pPanel, item1, item2, "filesizeint" ); -} - -static int ListFileAttributesSortFunc(ListPanel *pPanel, const ListPanelItem &item1, const ListPanelItem &item2 ) -{ - return ListBaseStringSortFunc( pPanel, item1, item2, "attributes" ); -} - -static int ListFileTypeSortFunc(ListPanel *pPanel, const ListPanelItem &item1, const ListPanelItem &item2 ) -{ - return ListBaseStringSortFunc( pPanel, item1, item2, "type" ); -} - - -//----------------------------------------------------------------------------- -// Dictionary of start dir contexts -//----------------------------------------------------------------------------- -struct ColumnInfo_t -{ - char const *columnName; - char const *columnText; - int startingWidth; - int minWidth; - int maxWidth; - int flags; - SortFunc *pfnSort; - Label::Alignment alignment; -}; - -static ColumnInfo_t g_ColInfo[] = -{ - { "text", "#PerforceFileList_Col_Name", 175, 20, 10000, ListPanel::COLUMN_UNHIDABLE, &ListFileNameSortFunc , Label::a_west }, - { "type", "#PerforceFileList_Col_Type", 150, 20, 10000, 0, &ListFileTypeSortFunc , Label::a_west }, - { "in_perforce", "#PerforceFileList_Col_InPerforce", 50, 20, 10000, ListPanel::COLUMN_UNHIDABLE, &ListFileAttributesSortFunc , Label::a_west }, - { "synched", "#PerforceFileList_Col_Synched", 50, 20, 10000, ListPanel::COLUMN_UNHIDABLE, &ListFileAttributesSortFunc , Label::a_west }, - { "checked_out", "#PerforceFileList_Col_Checked_Out", 50, 20, 10000, ListPanel::COLUMN_UNHIDABLE, &ListFileAttributesSortFunc , Label::a_west }, - { "attributes", "#PerforceFileList_Col_Attributes", 50, 20, 10000, ListPanel::COLUMN_HIDDEN, &ListFileAttributesSortFunc , Label::a_west }, -}; - - -//----------------------------------------------------------------------------- -// Purpose: Constructor -//----------------------------------------------------------------------------- -PerforceFileList::PerforceFileList( Panel *pParent, const char *pPanelName ) : - BaseClass( pParent, pPanelName ) -{ - SetMultiselectEnabled( false ); - m_bShowDeletedFiles = false; - - // list panel - for ( int i = 0; i < ARRAYSIZE( g_ColInfo ); ++i ) - { - const ColumnInfo_t& info = g_ColInfo[ i ]; - - AddColumnHeader( i, info.columnName, info.columnText, info.startingWidth, info.minWidth, info.maxWidth, info.flags ); - SetSortFunc( i, info.pfnSort ); - SetColumnTextAlignment( i, info.alignment ); - } - - SetSortColumn( 0 ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Destructor -//----------------------------------------------------------------------------- -PerforceFileList::~PerforceFileList() -{ -} - - -//----------------------------------------------------------------------------- -// Purpose: Apply scheme settings -//----------------------------------------------------------------------------- -void PerforceFileList::ApplySchemeSettings(IScheme *pScheme) -{ - BaseClass::ApplySchemeSettings( pScheme ); - - ImageList *pImageList = new ImageList( false ); - pImageList->AddImage( scheme()->GetImage( "resource/icon_file", false ) ); - pImageList->AddImage( scheme()->GetImage( "resource/icon_folder", false ) ); - pImageList->AddImage( scheme()->GetImage( "resource/icon_folder_selected", false ) ); - - SetImageList( pImageList, true ); -} - - -//----------------------------------------------------------------------------- -// Toggle showing deleted files or not -//----------------------------------------------------------------------------- -void PerforceFileList::ShowDeletedFiles( bool bShowDeletedFiles ) -{ - if ( m_bShowDeletedFiles != bShowDeletedFiles ) - { - m_bShowDeletedFiles = bShowDeletedFiles; - - for ( int i = FirstItem(); i != InvalidItemID(); i = NextItem( i ) ) - { - KeyValues *pKeyValues = GetItem( i ); - if ( !pKeyValues->GetInt( "deleted", 0 ) ) - continue; - - SetItemVisible( i, m_bShowDeletedFiles ); - } - } -} - - -//----------------------------------------------------------------------------- -// Add a directory to the directory list, returns client spec -//----------------------------------------------------------------------------- -void PerforceFileList::AddItemToDirectoryList( const char *pFullPath, int nItemID, bool bIsDirectory ) -{ - char pDirectoryBuf[MAX_PATH]; - Q_ExtractFilePath( pFullPath, pDirectoryBuf, sizeof(pDirectoryBuf) ); - Q_StripTrailingSlash( pDirectoryBuf ); - pFullPath = pDirectoryBuf; - - DirectoryInfo_t *pInfo; - UtlSymId_t i = m_Directories.Find( pFullPath ); - if ( i != m_Directories.InvalidIndex() ) - { - pInfo = &m_Directories[i]; - } - else - { - char pClientSpec[MAX_PATH]; - if ( !p4->GetClientSpecForDirectory( pFullPath, pClientSpec, sizeof(pClientSpec) ) ) - { - pClientSpec[0] = 0; - } - - pInfo = &m_Directories[ pFullPath ]; - pInfo->m_ClientSpec = pClientSpec; - } - - pInfo->m_ItemIDs.AddToTail( nItemID ); -} - - -//----------------------------------------------------------------------------- -// Add a file to the file list. -//----------------------------------------------------------------------------- -int PerforceFileList::AddFileToFileList( const char *pFullPath, bool bExistsOnDisk ) -{ - bool bIsFileWriteable = bExistsOnDisk ? g_pFullFileSystem->IsFileWritable( pFullPath, NULL ) : true; - - // add the file to the list - KeyValues *kv = new KeyValues("item"); - - const char *pRelativePath = Q_UnqualifiedFileName( pFullPath ); - kv->SetString( "text", pRelativePath ); - kv->SetString( "fullpath", pFullPath ); - kv->SetInt( "image", 1 ); - - IImage *pImage = surface()->GetIconImageForFullPath( pFullPath ); - if ( pImage ) - { - kv->SetPtr( "iconImage", (void *)pImage ); - } - - kv->SetInt( "imageSelected", 1 ); - kv->SetInt( "directory", 0 ); - - // These are computed by Refresh - kv->SetInt( "in_perforce", 0 ); - kv->SetInt( "synched", 0 ); - kv->SetInt( "checked_out", 0 ); - kv->SetInt( "deleted", 0 ); - - wchar_t pFileType[ 80 ]; - g_pFullFileSystem->GetFileTypeForFullPath( pFullPath, pFileType, sizeof( pFileType ) ); - - kv->SetWString( "type", pFileType ); - kv->SetString( "attributes", bIsFileWriteable ? "" : "R" ); - - int nItemID = AddItem( kv, 0, false, false ); - kv->deleteThis(); - - AddItemToDirectoryList( pFullPath, nItemID, false ); - return nItemID; -} - - -//----------------------------------------------------------------------------- -// Add a directory to the file list. -//----------------------------------------------------------------------------- -int PerforceFileList::AddDirectoryToFileList( const char *pFullPath, bool bExistsOnDisk ) -{ - KeyValues *kv = new KeyValues("item"); - - const char *pRelativePath = Q_UnqualifiedFileName( pFullPath ); - kv->SetString( "text", pRelativePath ); - kv->SetString( "fullpath", pFullPath ); - kv->SetPtr( "iconImage", (void *)NULL ); - kv->SetInt( "image", 2 ); - kv->SetInt( "imageSelected", 3 ); - kv->SetInt( "directory", 1 ); - - // These are computed by Refresh - kv->SetInt( "in_perforce", 0 ); - kv->SetInt( "synched", 0 ); - kv->SetInt( "checked_out", 0 ); - kv->SetInt( "deleted", 0 ); - - kv->SetString( "type", "#PerforceFileList_FileType_Folder" ); - kv->SetString( "attributes", "D" ); - - int nItemID = AddItem(kv, 0, false, false); - kv->deleteThis(); - - AddItemToDirectoryList( pFullPath, nItemID, true ); - return nItemID; -} - - -//----------------------------------------------------------------------------- -// Add a file or directory to the file list. -//----------------------------------------------------------------------------- -int PerforceFileList::AddFile( const char *pFullPath, int nFileExists, int nIsDirectory ) -{ - if ( !pFullPath ) - return InvalidItemID(); - - if ( !Q_IsAbsolutePath( pFullPath ) ) - { - Warning( "Absolute paths required for PerforceFileList::AddFile!\n" - "\"%s\" is not an abolute path", pFullPath ); - return InvalidItemID(); - } - - char pFixedPath[MAX_PATH]; - Q_strncpy( pFixedPath, pFullPath, sizeof(pFixedPath) ); - Q_FixSlashes( pFixedPath ); - - // Check to see if the file is on disk - int nItemID = -1; - bool bFileExists, bIsDirectory; - if ( nFileExists < 0 ) - { - bFileExists = g_pFullFileSystem->FileExists( pFixedPath ) ; - } - else - { - bFileExists = ( nFileExists != 0 ); - } - - if ( nIsDirectory < 0 ) - { - if ( bFileExists ) - { - bIsDirectory = g_pFullFileSystem->IsDirectory( pFixedPath ); - } - else - { - int nLen = Q_strlen( pFixedPath ); - bIsDirectory = ( pFixedPath[nLen-1] == CORRECT_PATH_SEPARATOR ); - } - } - else - { - bIsDirectory = ( nIsDirectory != 0 ); - } - - if ( bIsDirectory ) - { - nItemID = AddDirectoryToFileList( pFixedPath, bFileExists ); - } - else - { - nItemID = AddFileToFileList( pFixedPath, bFileExists ); - } - - return nItemID; -} - - -//----------------------------------------------------------------------------- -// Remove all files from the list -//----------------------------------------------------------------------------- -void PerforceFileList::RemoveAllFiles() -{ - RemoveAll(); - m_Directories.Clear(); -} - - -//----------------------------------------------------------------------------- -// Finds a file in the p4 list -//----------------------------------------------------------------------------- -static P4File_t *FindFileInPerforceList( const char *pFileName, CUtlVector &fileList, bool *pFound ) -{ - int nCount = fileList.Count(); - for ( int i = 0; i < nCount; ++i ) - { - if ( pFound[i] ) - continue; - - const char *pPerforceFileName = p4->String( fileList[i].m_sLocalFile ); - if ( !Q_stricmp( pPerforceFileName, pFileName ) ) - { - pFound[i] = true; - return &fileList[i]; - } - } - return NULL; -} - - -//----------------------------------------------------------------------------- -// Refresh perforce information -//----------------------------------------------------------------------------- -void PerforceFileList::RefreshPerforceState( int nItemID, bool bFileExists, P4File_t *pFileInfo ) -{ - KeyValues *kv = GetItem( nItemID ); - - bool bIsSynched = false; - bool bIsFileInPerforce = (pFileInfo != NULL); - if ( bIsFileInPerforce ) - { - if ( pFileInfo->m_bDeleted != bFileExists ) - { - bIsSynched = ( pFileInfo->m_bDeleted || ( pFileInfo->m_iHeadRevision == pFileInfo->m_iHaveRevision ) ); - } - } - else - { - bIsSynched = !bFileExists; - } - - bool bIsDeleted = bIsFileInPerforce && !bFileExists && pFileInfo->m_bDeleted; - - kv->SetInt( "in_perforce", bIsFileInPerforce ); - kv->SetInt( "synched", bIsSynched ); - kv->SetInt( "checked_out", bIsFileInPerforce && ( pFileInfo->m_eOpenState != P4FILE_UNOPENED ) ); - kv->SetInt( "deleted", bIsDeleted ); - - if ( bIsDeleted ) - { - SetItemVisible( nItemID, m_bShowDeletedFiles ); - } -} - - -//----------------------------------------------------------------------------- -// Refresh perforce information -//----------------------------------------------------------------------------- -void PerforceFileList::Refresh() -{ - /* - // Slow method.. does too many perforce operations - for ( int i = FirstItem(); i != InvalidItemID(); i = NextItem( i ) ) - { - const char *pFile = GetFile( i ); - - P4File_t fileInfo; - bool bIsFileInPerforce = p4->GetFileInfo( pFile, &fileInfo ); - bool bFileExists = g_pFullFileSystem->FileExists( pFile ); - RefreshPerforceState( i, bFileExists, bIsFileInPerforce ? &fileInfo : NULL ); - } - */ - - // NOTE: Reducing the # of perforce calls is important for performance - int nCount = m_Directories.GetNumStrings(); - for ( int i = 0; i < nCount; ++i ) - { - const char *pDirectory = m_Directories.String(i); - DirectoryInfo_t *pInfo = &m_Directories[i]; - - // Retrives files, uses faster method to avoid finding clientspec - CUtlVector &fileList = p4->GetFileListUsingClientSpec( pDirectory, pInfo->m_ClientSpec ); - int nFileCount = fileList.Count(); - bool *pFound = (bool*)_alloca( nFileCount * sizeof(bool) ); - memset( pFound, 0, nFileCount * sizeof(bool) ); - - int nItemCount = pInfo->m_ItemIDs.Count(); - for ( int j = 0; j < nItemCount; ++j ) - { - int nItemID = pInfo->m_ItemIDs[j]; - const char *pFileName = GetFile( nItemID ); - bool bFileExists = g_pFullFileSystem->FileExists( pFileName ); - P4File_t *pFileInfo = FindFileInPerforceList( pFileName, fileList, pFound ); - RefreshPerforceState( nItemID, bFileExists, pFileInfo ); - } - } -} - - -//----------------------------------------------------------------------------- -// Is a particular list item a directory? -//----------------------------------------------------------------------------- -bool PerforceFileList::IsDirectoryItem( int nItemID ) -{ - KeyValues *kv = GetItem( nItemID ); - return kv->GetInt( "directory", 0 ) != 0; -} - - -//----------------------------------------------------------------------------- -// Returns the file associated with a particular item ID -//----------------------------------------------------------------------------- -const char *PerforceFileList::GetFile( int nItemID ) -{ - KeyValues *kv = GetItem( nItemID ); - Assert( kv ); - return kv->GetString( "fullpath", "" ); -} - - -//----------------------------------------------------------------------------- -// Find the item ID associated with a particular file -//----------------------------------------------------------------------------- -int PerforceFileList::FindFile( const char *pFullPath ) -{ - for ( int i = FirstItem(); i != InvalidItemID(); i = NextItem( i ) ) - { - const char *pFile = GetFile( i ); - if ( !Q_stricmp( pFile, pFullPath ) ) - return i; - } - return InvalidItemID(); -} - - -//----------------------------------------------------------------------------- -// Is a file already in the list? -//----------------------------------------------------------------------------- -bool PerforceFileList::IsFileInList( const char *pFullPath ) -{ - return ( FindFile( pFullPath ) != InvalidItemID() ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Double-click: expand folders -//----------------------------------------------------------------------------- -void PerforceFileList::OnMouseDoublePressed( MouseCode code ) -{ - if ( code == MOUSE_LEFT ) - { - // select the item - OnMousePressed(code); - - // post a special message - if ( GetSelectedItemsCount() > 0 ) - { - PostActionSignal( new KeyValues("ItemDoubleClicked" ) ); - } - return; - } - - BaseClass::OnMouseDoublePressed( code ); -} - - +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Contains a list of files, determines their perforce status +// +// $NoKeywords: $ +//===========================================================================// + +#include +#include +#include +#include +#include "tier1/KeyValues.h" +#include +#include "filesystem.h" +#include "p4lib/ip4.h" +#include "tier2/tier2.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include + + +using namespace vgui; + + +static int ListFileNameSortFunc(ListPanel *pPanel, const ListPanelItem &item1, const ListPanelItem &item2 ) +{ + NOTE_UNUSED( pPanel ); + + bool dir1 = item1.kv->GetInt("directory") == 1; + bool dir2 = item2.kv->GetInt("directory") == 1; + + // if they're both not directories of files, return if dir1 is a directory (before files) + if ( dir1 != dir2 ) + { + return dir1 ? -1 : 1; + } + + const char *string1 = item1.kv->GetString("text"); + const char *string2 = item2.kv->GetString("text"); + + // YWB: Mimic windows behavior where filenames starting with numbers are sorted based on numeric part + int num1 = Q_atoi( string1 ); + int num2 = Q_atoi( string2 ); + + if ( num1 != 0 && + num2 != 0 ) + { + if ( num1 < num2 ) + return -1; + else if ( num1 > num2 ) + return 1; + } + + // Push numbers before everything else + if ( num1 != 0 ) + { + return -1; + } + + // Push numbers before everything else + if ( num2 != 0 ) + { + return 1; + } + + return Q_stricmp( string1, string2 ); +} + +static int ListBaseStringSortFunc(ListPanel *pPanel, const ListPanelItem &item1, const ListPanelItem &item2, char const *fieldName ) +{ + bool dir1 = item1.kv->GetInt("directory") == 1; + bool dir2 = item2.kv->GetInt("directory") == 1; + + // if they're both not directories of files, return if dir1 is a directory (before files) + if (dir1 != dir2) + { + return -1; + } + + const char *string1 = item1.kv->GetString(fieldName); + const char *string2 = item2.kv->GetString(fieldName); + int cval = Q_stricmp(string1, string2); + if ( cval == 0 ) + { + // Use filename to break ties + return ListFileNameSortFunc( pPanel, item1, item2 ); + } + + return cval; +} + +static int ListBaseIntegerSortFunc(ListPanel *pPanel, const ListPanelItem &item1, const ListPanelItem &item2, char const *fieldName ) +{ + bool dir1 = item1.kv->GetInt("directory") == 1; + bool dir2 = item2.kv->GetInt("directory") == 1; + + // if they're both not directories of files, return if dir1 is a directory (before files) + if (dir1 != dir2) + { + return -1; + } + + int i1 = item1.kv->GetInt(fieldName); + int i2 = item2.kv->GetInt(fieldName); + if ( i1 == i2 ) + { + // Use filename to break ties + return ListFileNameSortFunc( pPanel, item1, item2 ); + } + + return ( i1 < i2 ) ? -1 : 1; +} + +static int ListFileSizeSortFunc(ListPanel *pPanel, const ListPanelItem &item1, const ListPanelItem &item2 ) +{ + return ListBaseIntegerSortFunc( pPanel, item1, item2, "filesizeint" ); +} + +static int ListFileAttributesSortFunc(ListPanel *pPanel, const ListPanelItem &item1, const ListPanelItem &item2 ) +{ + return ListBaseStringSortFunc( pPanel, item1, item2, "attributes" ); +} + +static int ListFileTypeSortFunc(ListPanel *pPanel, const ListPanelItem &item1, const ListPanelItem &item2 ) +{ + return ListBaseStringSortFunc( pPanel, item1, item2, "type" ); +} + + +//----------------------------------------------------------------------------- +// Dictionary of start dir contexts +//----------------------------------------------------------------------------- +struct ColumnInfo_t +{ + char const *columnName; + char const *columnText; + int startingWidth; + int minWidth; + int maxWidth; + int flags; + SortFunc *pfnSort; + Label::Alignment alignment; +}; + +static ColumnInfo_t g_ColInfo[] = +{ + { "text", "#PerforceFileList_Col_Name", 175, 20, 10000, ListPanel::COLUMN_UNHIDABLE, &ListFileNameSortFunc , Label::a_west }, + { "type", "#PerforceFileList_Col_Type", 150, 20, 10000, 0, &ListFileTypeSortFunc , Label::a_west }, + { "in_perforce", "#PerforceFileList_Col_InPerforce", 50, 20, 10000, ListPanel::COLUMN_UNHIDABLE, &ListFileAttributesSortFunc , Label::a_west }, + { "synched", "#PerforceFileList_Col_Synched", 50, 20, 10000, ListPanel::COLUMN_UNHIDABLE, &ListFileAttributesSortFunc , Label::a_west }, + { "checked_out", "#PerforceFileList_Col_Checked_Out", 50, 20, 10000, ListPanel::COLUMN_UNHIDABLE, &ListFileAttributesSortFunc , Label::a_west }, + { "attributes", "#PerforceFileList_Col_Attributes", 50, 20, 10000, ListPanel::COLUMN_HIDDEN, &ListFileAttributesSortFunc , Label::a_west }, +}; + + +//----------------------------------------------------------------------------- +// Purpose: Constructor +//----------------------------------------------------------------------------- +PerforceFileList::PerforceFileList( Panel *pParent, const char *pPanelName ) : + BaseClass( pParent, pPanelName ) +{ + SetMultiselectEnabled( false ); + m_bShowDeletedFiles = false; + + // list panel + for ( int i = 0; i < ARRAYSIZE( g_ColInfo ); ++i ) + { + const ColumnInfo_t& info = g_ColInfo[ i ]; + + AddColumnHeader( i, info.columnName, info.columnText, info.startingWidth, info.minWidth, info.maxWidth, info.flags ); + SetSortFunc( i, info.pfnSort ); + SetColumnTextAlignment( i, info.alignment ); + } + + SetSortColumn( 0 ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Destructor +//----------------------------------------------------------------------------- +PerforceFileList::~PerforceFileList() +{ +} + + +//----------------------------------------------------------------------------- +// Purpose: Apply scheme settings +//----------------------------------------------------------------------------- +void PerforceFileList::ApplySchemeSettings(IScheme *pScheme) +{ + BaseClass::ApplySchemeSettings( pScheme ); + + ImageList *pImageList = new ImageList( false ); + pImageList->AddImage( scheme()->GetImage( "resource/icon_file", false ) ); + pImageList->AddImage( scheme()->GetImage( "resource/icon_folder", false ) ); + pImageList->AddImage( scheme()->GetImage( "resource/icon_folder_selected", false ) ); + + SetImageList( pImageList, true ); +} + + +//----------------------------------------------------------------------------- +// Toggle showing deleted files or not +//----------------------------------------------------------------------------- +void PerforceFileList::ShowDeletedFiles( bool bShowDeletedFiles ) +{ + if ( m_bShowDeletedFiles != bShowDeletedFiles ) + { + m_bShowDeletedFiles = bShowDeletedFiles; + + for ( int i = FirstItem(); i != InvalidItemID(); i = NextItem( i ) ) + { + KeyValues *pKeyValues = GetItem( i ); + if ( !pKeyValues->GetInt( "deleted", 0 ) ) + continue; + + SetItemVisible( i, m_bShowDeletedFiles ); + } + } +} + + +//----------------------------------------------------------------------------- +// Add a directory to the directory list, returns client spec +//----------------------------------------------------------------------------- +void PerforceFileList::AddItemToDirectoryList( const char *pFullPath, int nItemID, bool bIsDirectory ) +{ + char pDirectoryBuf[MAX_PATH]; + Q_ExtractFilePath( pFullPath, pDirectoryBuf, sizeof(pDirectoryBuf) ); + Q_StripTrailingSlash( pDirectoryBuf ); + pFullPath = pDirectoryBuf; + + DirectoryInfo_t *pInfo; + UtlSymId_t i = m_Directories.Find( pFullPath ); + if ( i != m_Directories.InvalidIndex() ) + { + pInfo = &m_Directories[i]; + } + else + { + char pClientSpec[MAX_PATH]; + if ( !p4->GetClientSpecForDirectory( pFullPath, pClientSpec, sizeof(pClientSpec) ) ) + { + pClientSpec[0] = 0; + } + + pInfo = &m_Directories[ pFullPath ]; + pInfo->m_ClientSpec = pClientSpec; + } + + pInfo->m_ItemIDs.AddToTail( nItemID ); +} + + +//----------------------------------------------------------------------------- +// Add a file to the file list. +//----------------------------------------------------------------------------- +int PerforceFileList::AddFileToFileList( const char *pFullPath, bool bExistsOnDisk ) +{ + bool bIsFileWriteable = bExistsOnDisk ? g_pFullFileSystem->IsFileWritable( pFullPath, NULL ) : true; + + // add the file to the list + KeyValues *kv = new KeyValues("item"); + + const char *pRelativePath = Q_UnqualifiedFileName( pFullPath ); + kv->SetString( "text", pRelativePath ); + kv->SetString( "fullpath", pFullPath ); + kv->SetInt( "image", 1 ); + + IImage *pImage = surface()->GetIconImageForFullPath( pFullPath ); + if ( pImage ) + { + kv->SetPtr( "iconImage", (void *)pImage ); + } + + kv->SetInt( "imageSelected", 1 ); + kv->SetInt( "directory", 0 ); + + // These are computed by Refresh + kv->SetInt( "in_perforce", 0 ); + kv->SetInt( "synched", 0 ); + kv->SetInt( "checked_out", 0 ); + kv->SetInt( "deleted", 0 ); + + wchar_t pFileType[ 80 ]; + g_pFullFileSystem->GetFileTypeForFullPath( pFullPath, pFileType, sizeof( pFileType ) ); + + kv->SetWString( "type", pFileType ); + kv->SetString( "attributes", bIsFileWriteable ? "" : "R" ); + + int nItemID = AddItem( kv, 0, false, false ); + kv->deleteThis(); + + AddItemToDirectoryList( pFullPath, nItemID, false ); + return nItemID; +} + + +//----------------------------------------------------------------------------- +// Add a directory to the file list. +//----------------------------------------------------------------------------- +int PerforceFileList::AddDirectoryToFileList( const char *pFullPath, bool bExistsOnDisk ) +{ + KeyValues *kv = new KeyValues("item"); + + const char *pRelativePath = Q_UnqualifiedFileName( pFullPath ); + kv->SetString( "text", pRelativePath ); + kv->SetString( "fullpath", pFullPath ); + kv->SetPtr( "iconImage", (void *)NULL ); + kv->SetInt( "image", 2 ); + kv->SetInt( "imageSelected", 3 ); + kv->SetInt( "directory", 1 ); + + // These are computed by Refresh + kv->SetInt( "in_perforce", 0 ); + kv->SetInt( "synched", 0 ); + kv->SetInt( "checked_out", 0 ); + kv->SetInt( "deleted", 0 ); + + kv->SetString( "type", "#PerforceFileList_FileType_Folder" ); + kv->SetString( "attributes", "D" ); + + int nItemID = AddItem(kv, 0, false, false); + kv->deleteThis(); + + AddItemToDirectoryList( pFullPath, nItemID, true ); + return nItemID; +} + + +//----------------------------------------------------------------------------- +// Add a file or directory to the file list. +//----------------------------------------------------------------------------- +int PerforceFileList::AddFile( const char *pFullPath, int nFileExists, int nIsDirectory ) +{ + if ( !pFullPath ) + return InvalidItemID(); + + if ( !Q_IsAbsolutePath( pFullPath ) ) + { + Warning( "Absolute paths required for PerforceFileList::AddFile!\n" + "\"%s\" is not an abolute path", pFullPath ); + return InvalidItemID(); + } + + char pFixedPath[MAX_PATH]; + Q_strncpy( pFixedPath, pFullPath, sizeof(pFixedPath) ); + Q_FixSlashes( pFixedPath ); + + // Check to see if the file is on disk + int nItemID = -1; + bool bFileExists, bIsDirectory; + if ( nFileExists < 0 ) + { + bFileExists = g_pFullFileSystem->FileExists( pFixedPath ) ; + } + else + { + bFileExists = ( nFileExists != 0 ); + } + + if ( nIsDirectory < 0 ) + { + if ( bFileExists ) + { + bIsDirectory = g_pFullFileSystem->IsDirectory( pFixedPath ); + } + else + { + int nLen = Q_strlen( pFixedPath ); + bIsDirectory = ( pFixedPath[nLen-1] == CORRECT_PATH_SEPARATOR ); + } + } + else + { + bIsDirectory = ( nIsDirectory != 0 ); + } + + if ( bIsDirectory ) + { + nItemID = AddDirectoryToFileList( pFixedPath, bFileExists ); + } + else + { + nItemID = AddFileToFileList( pFixedPath, bFileExists ); + } + + return nItemID; +} + + +//----------------------------------------------------------------------------- +// Remove all files from the list +//----------------------------------------------------------------------------- +void PerforceFileList::RemoveAllFiles() +{ + RemoveAll(); + m_Directories.Clear(); +} + + +//----------------------------------------------------------------------------- +// Finds a file in the p4 list +//----------------------------------------------------------------------------- +static P4File_t *FindFileInPerforceList( const char *pFileName, CUtlVector &fileList, bool *pFound ) +{ + int nCount = fileList.Count(); + for ( int i = 0; i < nCount; ++i ) + { + if ( pFound[i] ) + continue; + + const char *pPerforceFileName = p4->String( fileList[i].m_sLocalFile ); + if ( !Q_stricmp( pPerforceFileName, pFileName ) ) + { + pFound[i] = true; + return &fileList[i]; + } + } + return NULL; +} + + +//----------------------------------------------------------------------------- +// Refresh perforce information +//----------------------------------------------------------------------------- +void PerforceFileList::RefreshPerforceState( int nItemID, bool bFileExists, P4File_t *pFileInfo ) +{ + KeyValues *kv = GetItem( nItemID ); + + bool bIsSynched = false; + bool bIsFileInPerforce = (pFileInfo != NULL); + if ( bIsFileInPerforce ) + { + if ( pFileInfo->m_bDeleted != bFileExists ) + { + bIsSynched = ( pFileInfo->m_bDeleted || ( pFileInfo->m_iHeadRevision == pFileInfo->m_iHaveRevision ) ); + } + } + else + { + bIsSynched = !bFileExists; + } + + bool bIsDeleted = bIsFileInPerforce && !bFileExists && pFileInfo->m_bDeleted; + + kv->SetInt( "in_perforce", bIsFileInPerforce ); + kv->SetInt( "synched", bIsSynched ); + kv->SetInt( "checked_out", bIsFileInPerforce && ( pFileInfo->m_eOpenState != P4FILE_UNOPENED ) ); + kv->SetInt( "deleted", bIsDeleted ); + + if ( bIsDeleted ) + { + SetItemVisible( nItemID, m_bShowDeletedFiles ); + } +} + + +//----------------------------------------------------------------------------- +// Refresh perforce information +//----------------------------------------------------------------------------- +void PerforceFileList::Refresh() +{ + /* + // Slow method.. does too many perforce operations + for ( int i = FirstItem(); i != InvalidItemID(); i = NextItem( i ) ) + { + const char *pFile = GetFile( i ); + + P4File_t fileInfo; + bool bIsFileInPerforce = p4->GetFileInfo( pFile, &fileInfo ); + bool bFileExists = g_pFullFileSystem->FileExists( pFile ); + RefreshPerforceState( i, bFileExists, bIsFileInPerforce ? &fileInfo : NULL ); + } + */ + + // NOTE: Reducing the # of perforce calls is important for performance + int nCount = m_Directories.GetNumStrings(); + for ( int i = 0; i < nCount; ++i ) + { + const char *pDirectory = m_Directories.String(i); + DirectoryInfo_t *pInfo = &m_Directories[i]; + + // Retrives files, uses faster method to avoid finding clientspec + CUtlVector &fileList = p4->GetFileListUsingClientSpec( pDirectory, pInfo->m_ClientSpec ); + int nFileCount = fileList.Count(); + bool *pFound = (bool*)_alloca( nFileCount * sizeof(bool) ); + memset( pFound, 0, nFileCount * sizeof(bool) ); + + int nItemCount = pInfo->m_ItemIDs.Count(); + for ( int j = 0; j < nItemCount; ++j ) + { + int nItemID = pInfo->m_ItemIDs[j]; + const char *pFileName = GetFile( nItemID ); + bool bFileExists = g_pFullFileSystem->FileExists( pFileName ); + P4File_t *pFileInfo = FindFileInPerforceList( pFileName, fileList, pFound ); + RefreshPerforceState( nItemID, bFileExists, pFileInfo ); + } + } +} + + +//----------------------------------------------------------------------------- +// Is a particular list item a directory? +//----------------------------------------------------------------------------- +bool PerforceFileList::IsDirectoryItem( int nItemID ) +{ + KeyValues *kv = GetItem( nItemID ); + return kv->GetInt( "directory", 0 ) != 0; +} + + +//----------------------------------------------------------------------------- +// Returns the file associated with a particular item ID +//----------------------------------------------------------------------------- +const char *PerforceFileList::GetFile( int nItemID ) +{ + KeyValues *kv = GetItem( nItemID ); + Assert( kv ); + return kv->GetString( "fullpath", "" ); +} + + +//----------------------------------------------------------------------------- +// Find the item ID associated with a particular file +//----------------------------------------------------------------------------- +int PerforceFileList::FindFile( const char *pFullPath ) +{ + for ( int i = FirstItem(); i != InvalidItemID(); i = NextItem( i ) ) + { + const char *pFile = GetFile( i ); + if ( !Q_stricmp( pFile, pFullPath ) ) + return i; + } + return InvalidItemID(); +} + + +//----------------------------------------------------------------------------- +// Is a file already in the list? +//----------------------------------------------------------------------------- +bool PerforceFileList::IsFileInList( const char *pFullPath ) +{ + return ( FindFile( pFullPath ) != InvalidItemID() ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Double-click: expand folders +//----------------------------------------------------------------------------- +void PerforceFileList::OnMouseDoublePressed( MouseCode code ) +{ + if ( code == MOUSE_LEFT ) + { + // select the item + OnMousePressed(code); + + // post a special message + if ( GetSelectedItemsCount() > 0 ) + { + PostActionSignal( new KeyValues("ItemDoubleClicked" ) ); + } + return; + } + + BaseClass::OnMouseDoublePressed( code ); +} + + -- cgit v1.2.3