/* * * Copyright 2004 Perforce Software. All rights reserved. * * Developed by Data Shades Ltd. */ #include "HistoryDialog.h" #include "PerforceConnection.h" #include "debug.h" #include <commctrl.h> #include <time.h> HistoryDialog::HistoryDialog( PluginOperations *ops, PerforceResults *results ) : Dialog( ops, IDD_HISTORY_DIALOG, DialogWndProc ) { this->results = results; // Set initial sort orders revOrder = -1; changeOrder = -1; dateOrder = -1; userOrder = -1; actionOrder = -1; descOrder = -1; } PerforceResults *HistoryDialog::Results() { return results; } StrBuf *HistoryDialog::TempFile() { return &tempFile; } void HistoryDialog::CreateTempFile( TCHAR *version ) { UniStrDict *dict = ( UniStrDict * )results->Get( 0 ); // Get full depot path of file including revision number StrPtr *depotFile = dict->GetVar( "depotFile" ); UniStrBuf depotVersion; depotVersion.Set( (TCHAR *)depotFile->Text() ); depotVersion.Append( _T("#") ); depotVersion.Append( version ); // Generate full path of temporary file TCHAR buff[MAX_PATH]; GetTempPath( MAX_PATH, buff ); tempFile.Set( buff ); tempFile.Append( _T("Ver-") ); tempFile.Append( version ); tempFile.Append( _T("-") ); tempFile.Append( ExtractFilename( depotFile ) ); // Copy depot file to temporary file CONNECTION( ops ); PerforceCommand cmd( _T("print"), _T("-q"), _T("-o"), tempFile.Text(), depotVersion.Text() ); PerforceResults results; con.Exec( &cmd, &results ); // Make the file read-only DWORD attr = GetFileAttributes( tempFile.Text() ); attr |= FILE_ATTRIBUTE_READONLY; SetFileAttributes( tempFile.Text(), attr ); } void HistoryDialog::InsertListData( HWND list, UniStrDict *dict ) { LV_ITEM item; StrBuf key; UniStrBuf userClient; StrPtr *revision, *description, *changelist; StrPtr *time, *user, *client, *action; // Insert all history lines for ( int i=0;;i++ ) { // Test if we have another entry key.Clear(); revision = dict->GetVar( key << "rev" << i ); if ( revision == NULL ) { break; } key.Clear(); changelist = dict->GetVar( key << "change" << i); key.Clear(); time = dict->GetVar( key << "time" << i ); key.Clear(); user = dict->GetVar( key << "user" << i ); key.Clear(); client = dict->GetVar( key << "client" << i ); key.Clear(); action = dict->GetVar( key << "action" << i ); key.Clear(); description = dict->GetVar( key << "desc" << i ); // Revision column item.mask = LVIF_TEXT | LVIF_PARAM; item.iItem = i; item.iSubItem = 0; item.pszText = (TCHAR *)revision->Text(); // Store the item number in the userdata. item.lParam = ( LPARAM )i; ListView_InsertItem( list, &item ); // Changelist column item.mask = LVIF_TEXT; item.iItem = i; item.iSubItem = 1; item.pszText = (TCHAR *)changelist->Text(); ListView_SetItem( list, &item ); // Date Column item.mask = LVIF_TEXT; item.iItem = i; item.iSubItem = 2; item.pszText = AsciiTime( time ); ListView_SetItem( list, &item ); // User Column userClient.Clear(); userClient.Set( user ); userClient.Append( _T("@") ); userClient.Append( client ); item.mask = LVIF_TEXT; item.iItem = i; item.iSubItem = 3; item.pszText = userClient.Text(); ListView_SetItem( list, &item ); // Action Column item.mask = LVIF_TEXT; item.iItem = i; item.iSubItem = 4; item.pszText = (TCHAR *)action->Text(); ListView_SetItem( list, &item ); // Description Column item.mask = LVIF_TEXT; item.iItem = i; item.iSubItem = 5; TCHAR *buff = ReplaceNewlines( description, _T(" ") ); item.pszText = buff; ListView_SetItem( list, &item ); // Free buffer created by ReplaceNewlines delete []buff; } } void HistoryDialog::SetupList( HWND list ) { // Set full row highlight bar DWORD style = ListView_GetExtendedListViewStyle( list ); style |= LVS_EX_FULLROWSELECT; ListView_SetExtendedListViewStyle( list, style ); LV_COLUMN col; // Add Revision column col.mask = LVCF_SUBITEM | LVCF_FMT | LVCF_WIDTH | LVCF_TEXT; col.fmt = LVCFMT_LEFT; col.cx = 100; col.iSubItem = 0; col.pszText = _T("Revision"); ListView_InsertColumn( list, 0, &col ); // Add Changelist column col.iSubItem = 1; col.cx = 100; col.pszText = _T("Changelist"); ListView_InsertColumn( list, 1, &col ); // Add Date column col.iSubItem = 2; col.cx = 150; col.pszText = _T("Date"); ListView_InsertColumn( list, 2, &col ); // Add User column col.iSubItem = 3; col.cx = 100; col.pszText = _T("User"); ListView_InsertColumn( list, 3, &col ); // Add Action column col.iSubItem = 4; col.cx = 100; col.pszText = _T("Action"); ListView_InsertColumn( list, 4, &col ); // Add description column col.iSubItem = 5; col.cx = 100; col.pszText = _T("Description"); ListView_InsertColumn( list, 5, &col ); } BOOL CALLBACK HistoryDialog::DialogWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { HWND historyList = GetDlgItem( hWnd, IDC_HISTORY_LIST ); HWND historyDescLabel = GetDlgItem( hWnd, IDC_HISTORY_DESC_TEXT ); HWND historyDesc = GetDlgItem( hWnd, IDC_HISTORY_DESC_EDIT ); HWND viewButton = GetDlgItem( hWnd, ID_VIEW ); HWND cancelButton = GetDlgItem( hWnd, IDCANCEL ); switch(uMsg) { case WM_INITDIALOG: { HistoryDialog *dialog = (HistoryDialog *)lParam; SaveDialogObject(hWnd, dialog); SetupList( historyList ); PerforceResults *results = dialog->Results(); if (results->Count() > 0) { UniStrDict *dict = (UniStrDict *)results->Get( 0 ); StrPtr *depotFile = dict->GetVar ("depotFile"); if ( depotFile != NULL ) { // Set dialog title with filename UniStrBuf title; title.Set( _T("Document History for ") ); title.Append( dict->GetVar ("depotFile") ); SetWindowText(hWnd, title.Text()); // Populate list box with results if ( dict->GetVar( "rev0" ) != NULL ) { InsertListData( historyList, dict ); } } } // Set size of last column to fit control ListView_SetColumnWidth(historyList, 5, LVSCW_AUTOSIZE_USEHEADER); // Select first item in list ListView_SetItemState(historyList, 0, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED); SetFocus(historyList); Centre( hWnd ); SaveInitialSizes( hWnd ); SetResizeFlags( historyList, RESIZE_WIDTH | RESIZE_HEIGHT_HALF ); SetResizeFlags( historyDesc, RESIZE_TOP_HALF | RESIZE_WIDTH | RESIZE_HEIGHT_HALF ); SetResizeFlags( historyDescLabel, RESIZE_TOP_HALF ); SetResizeFlags( viewButton, RESIZE_TOP ); SetResizeFlags( cancelButton, RESIZE_TOP | RESIZE_LEFT ); return true; break; } case WM_GETMINMAXINFO: SetMinimumSize( hWnd, (LPMINMAXINFO) lParam ); return true; break; case WM_SIZE: Resize( hWnd, lParam ); return true; break; case WM_PAINT: { HistoryDialog *dialog = ( HistoryDialog * )DialogObject( hWnd ); dialog->PaintSizeGrip( hWnd ); break; } case WM_NCHITTEST: { return HitTestSizeGrip( hWnd, lParam ); } case WM_NOTIFY: { HistoryDialog *dialog = ( HistoryDialog * )DialogObject( hWnd ); LPNMHDR listEvent = (LPNMHDR) lParam; // If history list event if ((int)wParam == IDC_HISTORY_LIST) { // If selected item has changed if ( listEvent->code == LVN_ITEMCHANGED ) { LPNMLISTVIEW stateChange = (LPNMLISTVIEW) lParam; if ( stateChange->uNewState & LVIS_SELECTED ) { // Get full description stored in item user data LVITEM item; item.mask = LVIF_PARAM; item.iItem = stateChange->iItem; item.iSubItem = 0; ListView_GetItem( listEvent->hwndFrom, &item ); UniStrDict *dict = (UniStrDict *)dialog->Results()->Get( 0 ); StrBuf key; // Display the full description. StrPtr *desc = dict->GetVar( key << "desc" << (int)item.lParam ); TCHAR *buff = ReplaceNewlines( desc, _T("\r\n") ); SetDlgItemText( hWnd, IDC_HISTORY_DESC_EDIT, buff ); delete []buff; // Free buffer created by ReplaceNewlines // Set the description title key.Clear(); StrPtr *changelist = dict->GetVar( key << "change" << (int)item.lParam ); UniStrBuf title; title.Set( _T("Description for changelist ") ); title.Append( changelist ); SetDlgItemText( hWnd, IDC_HISTORY_DESC_TEXT, title.Text() ); } return 0; } // Column header click else if ( listEvent->code == LVN_COLUMNCLICK ) { LPNMLISTVIEW item = ( LPNMLISTVIEW ) lParam; dialog->sortCol = item->iSubItem; // Get column for sort and change order switch ( dialog->sortCol ) { case 0: dialog->revOrder *= -1; dialog->sortOrder = dialog->revOrder; break; case 1: dialog->changeOrder *= -1; dialog->sortOrder = dialog->changeOrder; break; case 2: dialog->dateOrder *= -1; dialog->sortOrder = dialog->dateOrder; break; case 3: dialog->userOrder *= -1; dialog->sortOrder = dialog->userOrder; break; case 4: dialog->actionOrder *= -1; dialog->sortOrder = dialog->actionOrder; break; case 5: dialog->descOrder *= -1; dialog->sortOrder = dialog->descOrder; break; } ListView_SortItems( historyList, Compare, (LPARAM) dialog ); } } } break; case WM_CTLCOLORSTATIC: // Make the background of edit boxes white instead of the read-only grey. if ( ( HWND )lParam == GetDlgItem( hWnd, IDC_HISTORY_DESC_EDIT ) ) { return ( BOOL )GetStockObject( WHITE_BRUSH ); } break; case WM_COMMAND: switch (LOWORD(wParam)) { // View button clicked case ID_VIEW: { HWND historyList = GetDlgItem( hWnd, IDC_HISTORY_LIST ); int count = ListView_GetItemCount( historyList ); // Go through list looking for selected item for (int i=0; i<count; i++) { // Found selected item if ( ListView_GetItemState( historyList, i, LVIS_SELECTED ) ) { // Get revision number of selected item LVITEM item; item.mask = LVIF_TEXT; item.iItem = i; item.iSubItem = 0; TCHAR buff[64]; item.pszText = buff; item.cchTextMax = sizeof( buff ); ListView_GetItem( historyList, &item ); // Create this file on the client and exit dialog HistoryDialog *dialog = ( HistoryDialog * )DialogObject( hWnd ); dialog->CreateTempFile( buff ); FinishDialog( hWnd, TRUE ); break; } } return true; } case IDOK: FinishDialog( hWnd, TRUE ); return true; case IDCANCEL: FinishDialog( hWnd, FALSE ); return true; } } return false; } int CALLBACK HistoryDialog::Compare( LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort ) { HistoryDialog *dialog = (HistoryDialog *)lParamSort; UniStrDict *dict = (UniStrDict *)dialog->Results()->Get( 0 ); bool strval; char *name; switch ( dialog->sortCol ) { case 0: strval = false; name = "rev"; break; case 1: strval = false; name = "change"; break; case 2: strval = false; name = "time"; break; case 3: strval = true; name = "user"; break; case 4: strval = true; name = "action"; break; case 5: strval = true; name = "desc"; break; } StrBuf key; StrPtr *val1 = dict->GetVar( key << name << (int)lParam1 ); key.Clear(); StrPtr *val2 = dict->GetVar( key << name << (int)lParam2 ); int result; if ( strval ) { result = _tcsicmp( (TCHAR *)val1->Text(), (TCHAR *)val2->Text() ); } else { long num1 = _ttol( (TCHAR *)val1->Text() ); long num2 = _ttol( (TCHAR *)val2->Text() ); if ( num1 < num2 ) { result = -1; } else if ( num2 < num1 ) { result = 1; } else { result = 0; } } return result * dialog->sortOrder; } TCHAR *HistoryDialog::AsciiTime( StrPtr *time ) { time_t secs = _ttoi( (TCHAR *)time->Text() ); std::tm ltime; localtime_s( <ime, (const time_t *)&secs ); static TCHAR buff[128]; // static buffer _stprintf_s( buff, _T("%04d/%02d/%02d %02d:%02d:%02d"), ltime.tm_year + 1900, ltime.tm_mon + 1, ltime.tm_mday, ltime.tm_hour, ltime.tm_min, ltime.tm_sec ); return buff; }
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#1 | 11314 | Robert Cowham | Initial population of perforce_software version of P4OFC | ||
//guest/robert_cowham/perforce/P4OFC/main/libp4gt/HistoryDialog.cpp | |||||
#1 | 10843 | Robert Cowham |
Initial version of P4OFC source code. See README.txt (and LICENSE.txt and doc\P4OFC-Design.docx) |