// // Copyright 1997 Nicholas J. Irias. All rights reserved. // // // OldChgListCtrl.cpp : implementation file // #include "stdafx.h" #include "p4win.h" #include "Cmd_Changes.h" #include "Cmd_EditSpec.h" #include "Cmd_MaxChange.h" #include "OldChgView.h" #include "SpecDescDlg.h" #include "MainFrm.h" #include "JobListDlg.h" #include "DeleteFixes.h" #include "P4Fix.h" #include "ChgDescribe.h" #include "Cmd_Fix.h" #include "cmd_fixes.h" #include "cmd_get.h" #include "cmd_jobs.h" #include "cmd_where.h" #include "RegKeyEx.h" #include "newclientdlg.h" #include "OldChgFilterDlg.h" #include "ImageList.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif #define IMG_INDEX(x) (x-IDB_PERFORCE) #define NUMFORMAT _T("%05d") static LPCTSTR sRegValue_SubmittedChanges = _T("Submitted Changes"); enum OldChgSubItem { OLDCHG_NAME, OLDCHG_DATE, OLDCHG_USER, OLDCHG_DESC, OLDCHG_MAXCOL }; ///////////////////////////////////////////////////////////////////////////// // COldChgListCtrl IMPLEMENT_DYNCREATE(COldChgListCtrl, CP4ListCtrl) BEGIN_MESSAGE_MAP(COldChgListCtrl, CP4ListCtrl) ON_UPDATE_COMMAND_UI(ID_VIEW_UPDATE_RIGHT, OnUpdateViewUpdate) ON_UPDATE_COMMAND_UI(ID_CHANGE_DESCRIBE, OnUpdateDescribe) ON_COMMAND(ID_CHANGE_DESCRIBE, OnDescribe) ON_UPDATE_COMMAND_UI(ID_SYNC_CHANGE, OnUpdateSyncChg) ON_COMMAND(ID_SYNC_CHANGE, OnSyncChg) ON_WM_CONTEXTMENU() ON_COMMAND(ID_VIEW_RELOADALL, OnViewReloadall) ON_UPDATE_COMMAND_UI(ID_VIEW_RELOADALL, OnUpdateViewReloadall) ON_WM_LBUTTONDBLCLK() ON_COMMAND(ID_FILTER_SETVIEW, OnFilterSetview) ON_COMMAND(ID_FILTER_SETVIEW_DROP, OnFilterSetviewDrop) ON_UPDATE_COMMAND_UI(ID_FILTER_SETVIEW, OnUpdateFilterSetview) ON_WM_CREATE() ON_UPDATE_COMMAND_UI(ID_FILTER_CLEARVIEW, OnUpdateFilterClearview) ON_COMMAND(ID_FILTER_CLEARVIEW, OnFilterClearview) ON_UPDATE_COMMAND_UI(ID_CHANGE_EDSPEC, OnUpdateChangeEdspec) ON_COMMAND(ID_CHANGE_EDSPEC, OnChangeEdspec) ON_UPDATE_COMMAND_UI(ID_CHANGE_ADDJOBFIX, OnUpdateAddjobfix) ON_NOTIFY_REFLECT(LVN_COLUMNCLICK, OnColumnclick) ON_COMMAND(ID_VIEW_UPDATE_RIGHT, OnViewReloadall) ON_NOTIFY_REFLECT(LVN_DELETEITEM, OnDeleteitem) ON_COMMAND(ID_CHANGE_ADDJOBFIX, OnAddjobfix) ON_COMMAND(ID_FILE_INTEGRATE, OnFileIntegrate) ON_UPDATE_COMMAND_UI(ID_FILE_INTEGRATE, OnUpdateFileIntegrate) ON_COMMAND(ID_FILE_INTEGSPEC, OnFileIntegspec) ON_UPDATE_COMMAND_UI(ID_FILE_INTEGSPEC, OnUpdateFileIntegrate) ON_COMMAND(ID_PERFORCE_OPTIONS, OnPerforceOptions) ON_UPDATE_COMMAND_UI(ID_POSITIONDEPOT, OnUpdatePositionDepot) ON_COMMAND(ID_POSITIONDEPOT, OnPositionDepot) ON_UPDATE_COMMAND_UI(ID_CHANGE_REMOVEFIX, OnUpdateRemovefix) ON_COMMAND(ID_CHANGE_REMOVEFIX, OnRemovefix) ON_MESSAGE(WM_P4FIXES, OnP4Fixes ) ON_MESSAGE(WM_P4FIX, OnP4Fix ) ON_MESSAGE(WM_ONDODELETEFIXES, OnDoDeleteFixes ) ON_MESSAGE(WM_RUNUPDATE, OnUpdateRequest ) ON_MESSAGE(WM_P4CHANGES, OnP4Change) ON_MESSAGE(WM_P4DESCRIBE, OnP4Describe ) ON_MESSAGE(WM_P4ENDDESCRIBE, OnP4EndDescribe ) ON_MESSAGE(WM_P4MAXCHANGE, OnP4MaxChange ) ON_MESSAGE(WM_P4EDITSPEC, OnP4ChangeSpec ) ON_MESSAGE(WM_P4ENDSPECEDIT, OnP4EndSpecEdit ) ON_MESSAGE(WM_P4JOBS, OnP4JobList ) ON_MESSAGE(WM_P4GET, OnP4Get ) ON_MESSAGE(WM_DOCUSTOMGET, OnDoSyncChg ) ON_MESSAGE(WM_P4INTEGCHG, OnIntegChg ) ON_MESSAGE(WM_SUBCHGOUFC, CallOnUpdateFilterClearview ) ON_MESSAGE(WM_P4CHGROLLBACK, OnP4ChgRollback ) ON_MESSAGE(WM_P4CHGROLLBACKPREVIEW, OnP4ChgRollbackPreview ) ON_MESSAGE(WM_P4DESCRIBEALT, OnP4ChgSelectAll ) END_MESSAGE_MAP() COldChgListCtrl::COldChgListCtrl() { m_viewType = P4CHANGE_SPEC; m_MaxChange=0; m_ItemCount=0; m_LastUpdateTime=0; m_SortAscending=FALSE; m_FilterInteg = m_FilterSpecial = m_ForceFocusHere = FALSE; m_FilteredByUser = GET_P4REGPTR()->GetFilteredByUser(); m_UserFilter = GET_P4REGPTR()->GetUserFilter(); m_FilteredByClient = GET_P4REGPTR()->GetFilteredByClient(); m_ClientFilter = GET_P4REGPTR()->GetClientFilter(); m_LastSortCol=0; m_LastDescNbr=_T(""); m_captionplain = LoadStringResource(IDS_SUBMITTED_PERFORCE_CHANGELISTS); m_DeleteFixesDlg = 0; m_CF_DEPOT = RegisterClipboardFormat(LoadStringResource(IDS_DRAGFROMDEPOT)); m_CF_CLIENT= RegisterClipboardFormat(LoadStringResource(IDS_DRAGFROMCLIENT)); m_CF_USER = RegisterClipboardFormat(LoadStringResource(IDS_DRAGFROMUSER)); m_CF_JOB = RegisterClipboardFormat(LoadStringResource(IDS_DRAGFROMJOB)); } COldChgListCtrl::~COldChgListCtrl() { } ///////////////////////////////////////////////////////////////////////////// // COldChgListCtrl diagnostics #ifdef _DEBUG void COldChgListCtrl::AssertValid() const { CP4ListCtrl::AssertValid(); } void COldChgListCtrl::Dump(CDumpContext& dc) const { CP4ListCtrl::Dump(dc); } #endif //_DEBUG ///////////////////////////////////////////////////////////////////////////// // COldChgListCtrl message handlers void COldChgListCtrl::OnLButtonDblClk(UINT nFlags, CPoint point) { // Find out what item was clicked and then run describe CPoint local = point; // find out what was hit LV_HITTESTINFO ht; ht.pt=local; ht.flags=LVHT_ONITEMICON | LVHT_ONITEMLABEL; int index=HitTest( &ht ); if(index != -1) { // If on an item, so select it and run edit SetItemState( index, LVIS_SELECTED|LVIS_FOCUSED, LVIS_SELECTED|LVIS_FOCUSED ); OnDescribe(); } else CP4ListCtrl::OnLButtonDblClk(nFlags, point);} void COldChgListCtrl::Clear() { // Clear the list view SetRedraw(FALSE); DeleteAllItems(); SetRedraw(TRUE); m_ItemCount=0; m_MaxChange=0; m_LastUpdateTime=0; CP4ListCtrl::Clear(); } void COldChgListCtrl::ClearFilter() { Clear(); GET_P4REGPTR()->SetFilteredByUser(FALSE); GET_P4REGPTR()->SetFilteredByClient(FALSE); m_FilterInteg = m_FilterSpecial = m_FilteredByUser = m_FilteredByClient = FALSE; m_FilterView.RemoveAll(); SetCaption(); PersistentChgFilter( KEY_WRITE ); } void COldChgListCtrl::InsertChange(CP4Change *change, int index) { // Add the data LV_ITEM lvItem; int iActualItem = -1; CString txt, txtout; int i; ASSERT(change != NULL); m_iImage = CP4ViewImageList::VI_OLDCHANGE; if (GET_SERVERLEVEL() < 12) { // Are we filtering by user on an old server? // (on a new server we don't have anything to do // because p4 changes -u did it for us) if (m_FilteredByUser) { txt = const_cast((LPCTSTR)change->GetUser()); if ((i = txt.Find(_T('@'))) != -1) txt = txt.Left(i); // is this the user we want? if (txt != m_UserFilter) { // no - so we must delete the change because no one // will know about it now that it is not in the list delete change; return; } } // Are we filtering by client on an old server? // (on a new server we don't have anything to do // because p4 changes -u did it for us) if (m_FilteredByClient) { txt = const_cast((LPCTSTR)change->GetUser()); if ((i = txt.Find(_T('@'))) != -1) txt = txt.Mid(i+1); // is this the client we want? if (txt != m_ClientFilter) { // no - so we must delete the change because no one // will know about it now that it is not in the list delete change; return; } } } for(int subItem=0; subItem < 4; subItem++) { lvItem.mask=LVIF_TEXT | ((subItem==0) ? LVIF_IMAGE : 0) | ((subItem==0) ? LVIF_PARAM : 0); lvItem.iItem= (subItem==0) ? index : iActualItem; ASSERT(lvItem.iItem != -1); lvItem.iSubItem= subItem; lvItem.iImage = CP4ViewImageList::VI_OLDCHANGE; lvItem.lParam=(LPARAM) change; switch(subItem) { case 0: txt.Format(NUMFORMAT, change->GetChangeNumber()); lvItem.pszText= const_cast((LPCTSTR)txt); break; case 1: lvItem.pszText= const_cast((LPCTSTR)change->GetChangeDate()); break; case 2: lvItem.pszText= const_cast((LPCTSTR)change->GetUser()); break; case 3: txt= change->GetDescription(); // Dont display cr-lf and tab chars int len=txt.GetLength(); LPTSTR ptr=txt.GetBuffer(len); LPTSTR ptrout=txtout.GetBuffer(len); for(int i=0; i((LPCTSTR)txtout); break; } if(subItem==0) iActualItem=InsertItem(&lvItem); else SetItem(&lvItem); } } LRESULT COldChgListCtrl::OnP4Change(WPARAM wParam, LPARAM lParam) { // Note: Output of 'P4 changes' arrives highest change number to // lowest change number, so use m_NewMaxChange as a temp value // and only update m_MaxChange at the end of the operation. if (lParam) { // Just got a list of changes CObList *list= (CObList *) wParam; ASSERT_KINDOF(CObList, list); POSITION pos= list->GetHeadPosition(); SetRedraw(FALSE); while(pos != NULL) { CP4Change *change= (CP4Change *) list->GetNext(pos); ASSERT_KINDOF(CP4Change, change); if(change->GetChangeNumber() > m_MaxChange) { // Note: Do not delete change if inserted in list, because // DeleteItem() will get rid of the change later. if(change->GetChangeNumber() > m_NewMaxChange) m_NewMaxChange=change->GetChangeNumber(); InsertChange(change, m_ItemCount); m_ItemCount++; } else delete change; } SetRedraw(TRUE); delete list; } else { CCmd_Changes *pCmd= (CCmd_Changes *) wParam; ASSERT_KINDOF(CCmd_Changes, pCmd); if(!pCmd->GetError()) { CP4ListCtrl::SetUpdateDone(); m_LastUpdateTime=GetTickCount(); if (!m_ItemCount) m_UpdateState = LIST_CLEAR; } else { CP4ListCtrl::SetUpdateFailed(); m_ForceFocusHere = FALSE; } // Record the new max change if (m_NewMaxChange > m_MaxChange) m_MaxChange = m_NewMaxChange; // Sort the view ReSort(); if( m_ItemCount > 0) { int i = FindInList(m_Active); if (i < 0) i=0; SetItemState( i, LVIS_SELECTED|LVIS_FOCUSED, LVIS_SELECTED|LVIS_FOCUSED ); EnsureVisible(i, FALSE); } CString msg; msg.FormatMessage( IDS_NUMBER_OF_SUBMITTED_CHANGELISTS_n, m_ItemCount ); AddToStatus( msg, SV_DEBUG ); if( pCmd->HaveServerLock() ) pCmd->ReleaseServerLock(); delete pCmd; MainFrame()->ClearStatus(); // Notify the mainframe that we have finished getting the submitted changlists, // hence the entire set of port connection async command have finished. MainFrame()->FinishedGettingChgs(FALSE); // and we are done - must explicitly call this in case filter yielded 0 chglists CP4ListCtrl::SetUpdateDone(); // if we did this update to fill a Browse listbox, call back to fill the listbox. if (m_PostViewUpdateMsg) { PostMessage(m_PostViewUpdateMsg, m_PostViewUpdateWParam, m_PostViewUpdateLParam); m_PostViewUpdateMsg = 0; } // if we just finished processing a Drop, force the focus to this pane if (m_ForceFocusHere) { m_ForceFocusHere = FALSE; MainFrame()->OnViewSubmitted(); } } return 0; } LRESULT COldChgListCtrl::OnP4Describe(WPARAM wParam, LPARAM lParam) { CCmd_Describe *pCmd= (CCmd_Describe *) wParam; if(!pCmd->GetError()) { CString desc= MakeCRs(pCmd->GetDescription()); int key; CSpecDescDlg *dlg = new CSpecDescDlg(this); dlg->SetIsModeless(TRUE); dlg->SetKey(key = pCmd->HaveServerLock()? pCmd->GetServerKey() : 0); dlg->SetDescription(LPCTSTR(desc)); dlg->SetItemName( pCmd->GetReference() ); dlg->SetCaption(LoadStringResource(IDS_PERFORCE_CHANGELIST_DESCRIPTION)); dlg->SetShowNextPrev(m_ItemCount ? TRUE : FALSE); dlg->SetShowShowDiffs(TRUE); dlg->SetDiffFlag(pCmd->GetFlag()); dlg->SetShowEditBtn(!key && !m_EditInProgress ? TRUE : FALSE); dlg->SetViewType(P4CHANGE_SPEC); if (!dlg->Create(IDD_SPECDESC, this)) // display the description dialog box { EnumChildWindows(AfxGetMainWnd()->m_hWnd, ChildSetRedraw, TRUE); dlg->DestroyWindow(); // some error! clean up delete dlg; } } else // had an error - need to turn painting back on { EnumChildWindows(AfxGetMainWnd()->m_hWnd, ChildSetRedraw, TRUE); } delete pCmd; MainFrame()->ClearStatus(); return 0; } LRESULT COldChgListCtrl::OnP4EndDescribe( WPARAM wParam, LPARAM lParam ) { CSpecDescDlg *dlg = (CSpecDescDlg *)lParam; CString ref = dlg->GetItemName(); ASSERT(!ref.IsEmpty()); switch(wParam) // which button did they click to close the box? { case ID_SHOWDIFFS_NORMAL: case ID_SHOWDIFFS_SUMMARY: case ID_SHOWDIFFS_UNIFIED: case ID_SHOWDIFFS_CONTEXT: case ID_SHOWDIFFS_RCS: case ID_SHOWDIFFS_NONE: { long l = _ttol(ref); OnDescribeLong(l, wParam); break; } case IDC_NEXTITEM: case IDC_PREVITEM: { long l = _ttol(ref); ref.Format(_T("%05d"), l); if (SetToNextPrevItem(ref, wParam == IDC_NEXTITEM ? 1 : -1, this)) { OnDescribe(); // display the next/prev in the list on the screen break; } } case IDC_EDITIT: if (wParam == IDC_EDITIT) // note fall-thru from above! { CString name = ref; BOOL uFlag = FALSE; if (GET_SERVERLEVEL() >= 23) // 2007.2 or later? { int i; CString desc = dlg->GetDescription(); if ((i = desc.Find(_T('@'))) != -1) { CString str = desc.Left(i); if ((i = str.ReverseFind(_T(' '))) != -1) { CString user = str.Mid(i+1); uFlag = !Compare(user, GET_P4REGPTR()->GetP4User()); } } } EditTheSpec(&name, uFlag); } default: // clicked OK, pressed ESC or ENTER - need to turn painting back on EnumChildWindows(AfxGetMainWnd()->m_hWnd, ChildSetRedraw, TRUE); break; } dlg->DestroyWindow(); return TRUE; } void COldChgListCtrl::OnUpdateViewUpdate(CCmdUI* pCmdUI) { // pCmdUI->SetText ( SetTextToRefresh( ) ); pCmdUI->Enable(!SERVER_BUSY() && !MainFrame()->IsModlessUp()); } void COldChgListCtrl::OnUpdateViewReloadall(CCmdUI* pCmdUI) { pCmdUI->Enable(!SERVER_BUSY()); } LRESULT COldChgListCtrl::OnUpdateRequest(WPARAM wParam, LPARAM lParam) { OnViewUpdate(); return 0; } void COldChgListCtrl::OnViewReloadall() { m_Active = GetSelectedItemText(); m_MaxChange=0; Clear(); OnViewUpdate(); } void COldChgListCtrl::OnViewUpdate() { MainFrame()->SetOldChgUpdateTime(GetTickCount()); CString str = GetSelectedItemText(); if (!str.IsEmpty()) m_Active = str; // For a full refresh, proceed to GetChanges if(m_MaxChange == 0) { int numChanges; if( GET_P4REGPTR()->GetFetchAllChanges() ) numChanges= 0; else numChanges= GET_P4REGPTR()->GetFetchChangeCount(); GetChanges(numChanges); } else { // If it has been over 20 minutes since we updated, run MaxChange long time=GetTickCount(); long elapsedTime= time-m_LastUpdateTime; if(elapsedTime < 0 || elapsedTime > 1200000L) { CCmd_MaxChange *pCmd= new CCmd_MaxChange; pCmd->Init( m_hWnd, RUN_ASYNC, HOLD_LOCK); if( pCmd->Run() ) { MainFrame()->UpdateStatus(LoadStringResource(IDS_VERIFYING_HEAD_CHANGELIST)); } else { delete pCmd; MainFrame()->ClearStatus(); } } else { // Make a conservative estimate of changes submitted since last update int numchanges=20 + 10 * (elapsedTime/60000); if( !GET_P4REGPTR()->GetFetchAllChanges() && numchanges > GET_P4REGPTR()->GetFetchChangeCount() ) { numchanges = GET_P4REGPTR()->GetFetchChangeCount(); Clear(); } GetChanges(numchanges); } } } LRESULT COldChgListCtrl::OnP4MaxChange(WPARAM wParam, LPARAM lParam) { CCmd_MaxChange *pCmd= (CCmd_MaxChange *) wParam; if(pCmd->GetError() || MainFrame()->IsQuitting()) { pCmd->ReleaseServerLock(); delete pCmd; MainFrame()->ClearStatus(); return 0; } int key= pCmd->GetServerKey(); // Get the new max change, for use if the update is a success long headChange= pCmd->GetMaxChange(); if(headChange == m_MaxChange) { // No work to do pCmd->ReleaseServerLock(); MainFrame()->ClearStatus(); } else if(headChange < m_MaxChange) { // How did max change number go down?? ASSERT(0); Clear(); int numChanges; if( GET_P4REGPTR()->GetFetchAllChanges() ) numChanges= 0; else numChanges= GET_P4REGPTR()->GetFetchChangeCount(); GetChanges(numChanges, key); } else { // Add 10 changes worth of "padding" in case a change is submitted between // the MaxChange and Changes commands GetChanges(10 + headChange-m_MaxChange, key); } delete pCmd; return 0; } void COldChgListCtrl::GetChanges(long numToFetch, int key/*=0*/) { m_NewMaxChange=0; CCmd_Changes *pCmd= new CCmd_Changes; if( key==0 ) pCmd->Init( m_hWnd, RUN_ASYNC); else pCmd->Init( m_hWnd, RUN_ASYNC, LOSE_LOCK, key); // Make a copy of the filter view, because CCmdChanges will // destroy that copy POSITION pos=m_FilterView.GetHeadPosition(); m_StrList.RemoveAll(); while(pos != NULL) m_StrList.AddTail(m_FilterView.GetNext(pos)); if( pCmd->Run(SUBMITTED_CHANGES, (GET_SERVERLEVEL() >= 19 && GET_P4REGPTR()->GetUseShortSubmittedDesc()) ? 2 : 1, &m_StrList, numToFetch, m_FilterInteg, !m_FilteredByUser || m_UserFilter.IsEmpty() ? NULL : &m_UserFilter, !m_FilteredByClient || m_ClientFilter.IsEmpty() ? NULL : &m_ClientFilter) ) { MainFrame()->UpdateStatus(LoadStringResource(IDS_REQUESTING_CHANGES)); CP4ListCtrl::OnViewUpdate(); } else { if(pCmd->HaveServerLock()) pCmd->ReleaseServerLock(); delete pCmd; MainFrame()->ClearStatus(); } } void COldChgListCtrl::OnContextMenu(CWnd* pWnd, CPoint point) { // make sure window is active GetParentFrame()->ActivateFrame(); int index; SetIndexAndPoint( index, point ); // If on an item, make sure it's selected if(index != -1) SetItemState( index, LVIS_SELECTED|LVIS_FOCUSED, LVIS_SELECTED|LVIS_FOCUSED ); /////////////////////////////// // See ContextMenuRules.txt for order of menu commands! // create an empty context menu CP4Menu popMenu; popMenu.CreatePopupMenu(); CP4Menu integMenu; integMenu.CreatePopupMenu(); if(index != -1) { popMenu.AppendMenu(MF_ENABLED | MF_STRING, ID_CHANGE_EDSPEC, LoadStringResource( IDS_EDIT ) ); popMenu.AppendMenu(MF_ENABLED | MF_STRING, ID_CHANGE_DESCRIBE ); popMenu.AppendMenu(MF_ENABLED | MF_STRING, ID_CHANGE_ADDJOBFIX, LoadStringResource( IDS_ADDJOBFIX ) ); popMenu.AppendMenu(MF_ENABLED | MF_STRING, ID_CHANGE_REMOVEFIX, LoadStringResource( IDS_CHANGE_REMOVEFIX ) ); popMenu.AppendMenu(MF_ENABLED | MF_STRING, ID_SYNC_CHANGE, LoadStringResource( IDS_SYNC_CHANGE ) ); popMenu.AppendMenu(MF_ENABLED | MF_STRING, ID_POSITIONDEPOT, LoadStringResource( IDS_FINDCHGFILESINDEPOT ) ); integMenu.AppendMenu( stringsON, ID_FILE_INTEGSPEC, LoadStringResource( IDS_USINGFILESPEC ) ); integMenu.AppendMenu( stringsON, ID_FILE_INTEGRATE, LoadStringResource( IDS_USINGBRANCHSPEC ) ); popMenu.AppendMenu(MF_POPUP, (UINT) integMenu.GetSafeHmenu(), LoadStringResource( IDS_INTEGRATE ) ); popMenu.AppendMenu(MF_SEPARATOR); } popMenu.AppendMenu(MF_ENABLED | MF_STRING, ID_FILTER_SETVIEW, LoadStringResource(IDS_FILTER_SETVIEW)); UINT flags = (m_FilterView.GetCount() || m_FilteredByClient || m_FilteredByUser) ? MF_ENABLED | MF_STRING : MF_DISABLED | MF_STRING; popMenu.AppendMenu(flags, ID_FILTER_CLEARVIEW, LoadStringResource(IDS_CLEARFILTER)); popMenu.AppendMenu( MF_SEPARATOR ); popMenu.AppendMenu(MF_ENABLED | MF_STRING, ID_VIEW_UPDATE, LoadStringResource(IDS_REFRESH)); MainFrame()->AddToolsToContextMenu(&popMenu); // Finally blast the menu onto the screen popMenu.TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, AfxGetMainWnd()); } void COldChgListCtrl::OnUpdateSyncChg(CCmdUI* pCmdUI) { pCmdUI->Enable( OnUpdateShowMenuItem( pCmdUI, IDS_SYNC_CHANGE_s ) && !MainFrame()->IsModlessUp() ); } void COldChgListCtrl::OnSyncChg() { if(!GetSelectedChange()) return; m_SyncChangeDlg = new CSyncChange(this); if (!m_SyncChangeDlg) { ASSERT(0); AfxMessageBox(IDS_COULD_NOT_CREATE_CUSTOM_SYNC_DIALOG_BOX, MB_ICONSTOP); return; } MainFrame()->SetModelessUp(TRUE); if (!m_SyncChangeDlg->Create(IDD_CHANGE_SYNC, this)) { delete m_SyncChangeDlg; MainFrame()->SetModelessUp(FALSE); } } LRESULT COldChgListCtrl::OnDoSyncChg(WPARAM wParam, LPARAM lParam) { BOOL preview=FALSE; long changeNumber= GetSelectedChange(); switch(wParam) { case IDCANCEL: break; case IDGETPREVIEW: preview=TRUE; // fall thru case IDGET: if (changeNumber) { CString syncTxt; if (lParam == 2) { // They want to roll back the files in this chg, so get the chg description CString changeTxt; changeTxt.Format(_T("%ld"), changeNumber); CCmd_Describe *pCmd= new CCmd_Describe; pCmd->Init( m_hWnd, RUN_ASYNC); pCmd->SetAlternateReplyMsg(preview ? WM_P4CHGROLLBACKPREVIEW : WM_P4CHGROLLBACK); if( pCmd->Run( P4DESCRIBE, changeTxt) ) MainFrame()->UpdateStatus(LoadStringResource(IDS_FETCHING_CHANGELIST_DESCRIPTION)); else delete pCmd; } else if (lParam) { if (GET_SERVERLEVEL() >= 17) syncTxt.Format(_T("@=%ld"), changeNumber); else syncTxt.Format(_T("@%ld,%ld"), changeNumber,changeNumber); } else syncTxt.Format(_T("@%ld"), changeNumber); m_StrList.RemoveAll(); m_StrList.AddHead(syncTxt); CCmd_Get *pCmd= new CCmd_Get; pCmd->Init( m_hWnd, RUN_ASYNC); if( pCmd->Run( &m_StrList, preview ) ) MainFrame()->UpdateStatus( LoadStringResource(IDS_FILE_SYNC) ); else delete pCmd; break; } default: ASSERT(0); break; } if (m_SyncChangeDlg && (wParam != IDGETPREVIEW)) { m_SyncChangeDlg->DestroyWindow(); delete m_SyncChangeDlg; MainFrame()->SetModelessUp(FALSE); } return 0; } void COldChgListCtrl::OnUpdateDescribe(CCmdUI* pCmdUI) { pCmdUI->Enable( OnUpdateShowMenuItem( pCmdUI, IDS_DESCRIBESUBMITTED_s ) ); } LRESULT COldChgListCtrl::OnP4Get(WPARAM wParam, LPARAM lParam) { MainFrame()->ClearStatus(); ::SendMessage(m_depotWnd, WM_P4GET, wParam, lParam); return 0; } void COldChgListCtrl::OnDescribeLong(long changeNumber /*= 0*/, int flag /*= 0*/) { if (!changeNumber) changeNumber= GetSelectedChange(); if(changeNumber != 0) { CString changeTxt; changeTxt.Format(_T("%ld"), changeNumber); CCmd_Describe *pCmd= new CCmd_Describe; pCmd->Init( m_hWnd, RUN_ASYNC); if( pCmd->Run( P4DESCRIBELONG, changeTxt, NULL, FALSE, flag) ) MainFrame()->UpdateStatus(LoadStringResource(IDS_FETCHING_CHANGELIST_DESCRIPTION)); else delete pCmd; } else AfxMessageBox ( IDS_PLEASE_SELECT_A_CHANGELIST ); } void COldChgListCtrl::OnDescribe() { long changeNumber= GetSelectedChange(); if(changeNumber != 0) { CString changeTxt; changeTxt.Format(_T("%ld"), changeNumber); CCmd_Describe *pCmd= new CCmd_Describe; pCmd->Init( m_hWnd, RUN_ASYNC); if( pCmd->Run( P4DESCRIBE, changeTxt) ) MainFrame()->UpdateStatus(LoadStringResource(IDS_FETCHING_CHANGELIST_DESCRIPTION)); else delete pCmd; } else AfxMessageBox ( IDS_PLEASE_SELECT_A_CHANGELIST ); } void COldChgListCtrl::OnDescribeChg() { // let user type in the changelist number. if it's blank the user bailed. // CChgDescribe dlg; dlg.SetNbr(m_LastDescNbr); if( dlg.DoModal( ) == IDCANCEL ) return; CString nbr = dlg.GetNbr( ) ; if ( nbr.IsEmpty( ) ) return; m_LastDescNbr = nbr; CCmd_Describe *pCmd= new CCmd_Describe; pCmd->Init( m_hWnd, RUN_ASYNC); if( pCmd->Run( P4DESCRIBE, nbr) ) MainFrame()->UpdateStatus(LoadStringResource(IDS_FETCHING_CHANGELIST_DESCRIPTION)); else delete pCmd; } void COldChgListCtrl::OnUpdateChangeEdspec(CCmdUI* pCmdUI) { pCmdUI->Enable(!m_EditInProgress); } void COldChgListCtrl::OnChangeEdspec() { BOOL uFlag = FALSE; if (GET_SERVERLEVEL() >= 23) // 2007.2 or later? { CString usercli; GetUserClientForSelectedChg(&usercli); int i; if ((i = usercli.Find(_T('@'))) != -1) { CString user = usercli.Left(i); uFlag = !Compare(user, GET_P4REGPTR()->GetP4User()); } } EditChangeSpec(GetSelectedChange(), uFlag); } void COldChgListCtrl::EditChangeSpec(long changeNumber, BOOL uFlag) { if (m_EditInProgress) { CantEditRightNow(IDS_CHANGELIST); return; } if(changeNumber != 0) { // Fire up CCmd_EditSpec. The spec edit dialog will be invoked by CCmd_EditSpec. MainFrame()->UpdateStatus( LoadStringResource(IDS_RETRIEVING_CHANGELIST_SPEC) ); CCmd_EditSpec *pCmd= new CCmd_EditSpec; pCmd->Init( m_hWnd, RUN_ASYNC, HOLD_LOCK ); if( pCmd->Run( changeNumber, FALSE, !uFlag, FALSE, FALSE, uFlag) ) MainFrame()->UpdateStatus( LoadStringResource(IDS_EDITING_CHANGELIST_SPEC) ); else delete pCmd; } } void COldChgListCtrl::EditTheSpec(CString *name, BOOL uFlag) { EditChangeSpec(_ttol(*name), uFlag); } long COldChgListCtrl::GetSelectedChange() { int index = CP4ListCtrl::GetSelectedItem(); if (index==-1) return 0; else { TCHAR str[255]; GetItemText(index, 0, str, 254); return _ttol(str); } } BOOL COldChgListCtrl::GetUserClientForSelectedChg(CString *user) { int index = CP4ListCtrl::GetSelectedItem(); if (index==-1) return FALSE; TCHAR str[255]; GetItemText(index, 2, str, 254); *user = str; return TRUE; } // A change description was sent to the server, 'P4 change -i". This should be a confirming // message. LRESULT COldChgListCtrl::OnP4ChangeSpec(WPARAM wParam, LPARAM lParam) { CCmd_EditSpec *pCmd= (CCmd_EditSpec *) wParam; MainFrame()->ClearStatus(); if(!pCmd->GetError() && !m_EditInProgress && pCmd->PreprocessChgSpec() && pCmd->DoSpecDlg(this)) { m_EditInProgress = TRUE; m_EditInProgressWnd = pCmd->GetSpecSheet(); } else { if (pCmd->HaveServerLock()) pCmd->ReleaseServerLock(); delete pCmd; } return 0; } LRESULT COldChgListCtrl::OnP4EndSpecEdit( WPARAM wParam, LPARAM lParam ) { CCmd_EditSpec *pCmd= (CCmd_EditSpec *) wParam; if (lParam != IDCANCEL && lParam != IDABORT) { // The change description may have changed, so update the display. CString desctxt=PadCRs(pCmd->GetChangeDesc()); int changeNum= pCmd->GetNewChangeNum(); CString search; search.Format( NUMFORMAT, changeNum ); int index= FindInList( search ); if( index > -1 ) { SetItemText( index, 3, desctxt ); CP4Change *change= (CP4Change *) GetItemData(index); change->SetDescription(desctxt); } CString txt; txt.FormatMessage(IDS_CHANGE_n_UPDATED, (long) pCmd->GetNewChangeNum()); AddToStatus(txt); } if (lParam != IDABORT) { MainFrame()->ClearStatus(); if (pCmd->HaveServerLock()) pCmd->ReleaseServerLock(); CDialog *dlg = (CDialog *)pCmd->GetSpecSheet(); dlg->DestroyWindow(); } delete pCmd; m_EditInProgress = FALSE; return 0; } ////////////////////////////////////////////////////////////////////////// // Sort callback, not in class int COldChgListCtrl::OnCompareItems(LPARAM lParam1, LPARAM lParam2, int subItem) { ASSERT(lParam1 && lParam2); CP4Change const *change1 = (CP4Change const *)lParam1; CP4Change const *change2 = (CP4Change const *)lParam2; CString txt1, txt2; switch(subItem) { case OLDCHG_NAME: if(m_SortAscending) return( change1->GetChangeNumber() - change2->GetChangeNumber() ); else return( change2->GetChangeNumber() - change1->GetChangeNumber() ); break; case OLDCHG_DATE: txt1= change1->GetChangeDate(); txt2= change2->GetChangeDate(); ConvertDates( txt1, txt2 ); break; case OLDCHG_USER: txt1= change1->GetUser(); txt2= change2->GetUser(); break; case OLDCHG_DESC: txt1= change1->GetDescription(); txt2= change2->GetDescription(); break; default: ASSERT(0); return 0; } int rc; if(m_SortAscending) { if ( subItem == OLDCHG_USER ) rc = Compare(txt1, txt2); else rc = txt1.Compare(txt2); } else { if ( subItem == OLDCHG_USER ) rc = Compare(txt2, txt1); else rc = txt2.Compare(txt1); } return rc; } void COldChgListCtrl::OnDeleteitem(NMHDR* pNMHDR, LRESULT* pResult) { NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR; delete (CP4Change *) GetItemData(pNMListView->iItem); *pResult = 0; } ///////////////////////////////////////////////////////////////////// // Handlers for setting filters for submitted changes view ///////////////////////////////////////////////////////////////////// void COldChgListCtrl::OnFilterClearview() { if( SERVER_BUSY() ) return; ClearFilter(); OnViewReloadall(); } void COldChgListCtrl::OnFilterSetviewDrop() { ::SendMessage(m_depotWnd, WM_GETSELLIST, (WPARAM) &m_FilterView, (LPARAM)TRUE); if (m_FilterView.GetCount()) { // save filter changes and update views PersistentChgFilter( KEY_WRITE ); SetCaption(); OnViewReloadall(); } else TheApp()->StatusAdd(LoadStringResource(IDS_NO_SELECTED_FILES_IN_LOCAL_DEPOTS), SV_WARNING); } void COldChgListCtrl::OnFilterSetview() { //FIXTHIS need to enable include integ using this?: GET_P4REGPTR()->GetEnableSubChgIntegFilter( ) COldChgFilterDlg dlg; // initialize filter vars dlg.m_useClient = m_FilteredByClient; dlg.m_client = m_ClientFilter; dlg.m_useUser = m_FilteredByUser; dlg.m_user = m_UserFilter; dlg.m_includeIntegrations = m_FilterInteg; // get selected files from depot view and convert to string CStringList selected; ::SendMessage(m_depotWnd, WM_GETSELLIST, (WPARAM) &selected, 0); CString selectedTxt; POSITION pos = selected.GetHeadPosition(); int i; for(i=0; pos != NULL; i++) { CString sel = selected.GetNext(pos); selectedTxt += sel + _T(" "); dlg.m_selected.AddTail(sel); } selectedTxt.TrimRight(); dlg.m_selectedFiles = selectedTxt; // make a radio button selection based on various strings if(m_FilterView.IsEmpty()) dlg.m_filterFiles = 0; else { // convert current view to a string CString currentTxt; pos = m_FilterView.GetHeadPosition(); for(i=0; pos != NULL; i++) currentTxt += m_FilterView.GetNext(pos) + _T(" "); currentTxt.TrimRight(); if(currentTxt == selectedTxt) dlg.m_filterFiles = 3; else dlg.m_filterFiles = 2; } if(dlg.DoModal() == IDCANCEL) return; // get client and user filter settings m_FilteredByClient = dlg.m_useClient; GET_P4REGPTR()->SetFilteredByClient(m_FilteredByClient); if(m_FilteredByClient) { m_ClientFilter = dlg.m_client; GET_P4REGPTR()->SetClientFilter(m_ClientFilter); } m_FilteredByUser = dlg.m_useUser; GET_P4REGPTR()->SetFilteredByUser(m_FilteredByUser); if(m_FilteredByUser) { m_UserFilter = dlg.m_user; GET_P4REGPTR()->SetUserFilter(m_UserFilter); } // get include integrations option m_FilterInteg = dlg.m_includeIntegrations; // get the filter view switch(dlg.m_filterFiles) { case 0: // all files m_FilterView.RemoveAll(); break; case 1: // my client files m_FilterView.RemoveAll(); m_FilterView.AddTail(CString(_T("//")) + GET_P4REGPTR()->GetP4Client( ) + _T("/...")); break; case 2: // filespec { // convert filespec into view stringlist m_FilterView.RemoveAll(); CString filespec = dlg.m_filespec; int i; while ((i = filespec.Find(_T("//"), 2)) != -1) { if (filespec.GetAt(i-1) == _T('\"')) i--; CString txt = filespec.Left(i); txt.TrimRight(); txt.TrimRight(_T('\"')); txt.TrimLeft(_T('\"')); m_FilterView.AddTail(txt); filespec = filespec.Mid(i); } filespec.TrimRight(); filespec.TrimRight(_T('\"')); filespec.TrimLeft(_T('\"')); if (!filespec.IsEmpty()) m_FilterView.AddTail(filespec); } break; case 3: // selected files { m_FilterView.RemoveAll(); POSITION pos = selected.GetHeadPosition(); while (pos != NULL) { CString str = selected.GetNext(pos); if (dlg.m_UseClientSyntax) { // user wants to convert to client syntax CCmd_Where *pCmd1 = new CCmd_Where; pCmd1->Init(NULL, RUN_SYNC); if ( pCmd1->Run(str) && !pCmd1->GetError() && pCmd1->GetClientFiles()->GetCount() ) { CStringList * list = pCmd1->GetClientFiles(); POSITION pos2 = list->GetHeadPosition(); while (pos2 != NULL) m_FilterView.AddTail(list->GetNext(pos2)); } else // p4 where failed - use depot syntax after all m_FilterView.AddTail(str); delete pCmd1; } else m_FilterView.AddTail(str); } // get the filter rev range, if any was set CString revRange; dlg.GetFilterRevRange(revRange); // apply the filter range to the view if applicable if (!revRange.IsEmpty()) { POSITION pos=m_FilterView.GetHeadPosition(); m_StrList.RemoveAll(); while(pos != NULL) m_StrList.AddTail(m_FilterView.GetNext(pos) + revRange); pos=m_StrList.GetHeadPosition(); m_FilterView.RemoveAll(); while(pos != NULL) m_FilterView.AddTail(m_StrList.GetNext(pos)); } break; } } // save filter changes and update views PersistentChgFilter( KEY_WRITE ); SetCaption(); OnViewReloadall(); } LRESULT COldChgListCtrl::CallOnUpdateFilterClearview(WPARAM wParam, LPARAM lParam) { OnUpdateFilterClearview((CCmdUI *)lParam); return 0; } void COldChgListCtrl::OnUpdateFilterClearview(CCmdUI* pCmdUI) { pCmdUI->SetText(LoadStringResource(IDS_FILTER_CLEARVIEW)); pCmdUI->Enable(MainFrame()->SetMenuIcon(pCmdUI, !SERVER_BUSY() && (m_FilterView.GetCount() || m_FilteredByClient || m_FilteredByUser))); } void COldChgListCtrl::OnUpdateFilterSetview(CCmdUI* pCmdUI) { pCmdUI->SetText(LoadStringResource(IDS_FILTER_SETVIEW)); pCmdUI->Enable( MainFrame()->SetMenuIcon(pCmdUI, !SERVER_BUSY()) ); } void COldChgListCtrl::PersistentChgFilter( REGSAM accessmask ) { LPCTSTR sKey = _T("Software\\Perforce\\P4Win\\"); LPCTSTR sEntry = _T("ChgFilter"); LPCTSTR sType = _T("ChgFiltype"); LPCTSTR sPort = _T("ChgFilPort"); CRegKeyEx key; if(ERROR_SUCCESS == key.Create(HKEY_CURRENT_USER, sKey, REG_NONE, REG_OPTION_NON_VOLATILE, accessmask)) { if(accessmask == KEY_WRITE) { POSITION pos=m_FilterView.GetHeadPosition(); CString filter; CString txt; while(pos != NULL) { txt = m_FilterView.GetNext(pos); filter += txt + _T('\t'); } key.SetValueString(filter, sEntry); if (filter.GetLength() > 0) // if filter is not blank GET_P4REGPTR()->AddMRUChgFilter( filter ); // save as most recently used in Reg txt.Format(_T("%d"), m_FilterInteg); key.SetValueString(txt, sType); key.SetValueString(GET_P4REGPTR()->GetP4Port(), sPort); } else { m_FilterView.RemoveAll(); m_FilterInteg = m_FilterSpecial = FALSE; CString port = key.QueryValueString(sPort); if(!port.IsEmpty() && port == GET_P4REGPTR()->GetP4Port()) { // in older versions, filter elements were written to the // registry using '@' as a separator. Now we use '\t', but // we have to handle finding an older setting. It's easy, // since the whole thing will be terminated with the separator // character. CString entry = key.QueryValueString(sEntry); bool oldVersion = entry.Right(1) == _T("@"); m_FilterSpecial = !oldVersion && (entry.FindOneOf(_T("@#")) != -1); CString separator = oldVersion ? _T("@") : _T("\t"); while(!entry.IsEmpty()) { CString elem = entry.SpanExcluding(separator); if(!elem.IsEmpty()) { m_FilterView.AddTail(elem); entry = entry.Mid(elem.GetLength()+1); } } CString type = key.QueryValueString(sType); if(!type.IsEmpty()) { m_FilterInteg = type[0] & 0x01; m_FilterSpecial += m_FilterInteg; } } else { GET_P4REGPTR()->SetFilteredByUser(m_FilteredByUser = FALSE); GET_P4REGPTR()->SetFilteredByUser(m_FilteredByClient = FALSE); } SetCaption(); } } } void COldChgListCtrl::SetCaption() { if (m_FilterView.GetCount() > 0 || m_FilteredByUser || m_FilteredByClient) { CString txt = _T(""); if (m_FilteredByClient) txt = LoadStringResource(IDS_CLIENT) + _T(' ') + m_ClientFilter; if (m_FilteredByUser) { if (!txt.IsEmpty()) txt += _T("; "); txt += LoadStringResource(IDS_USER) + _T(' ') + m_UserFilter; } if (m_FilterView.GetCount() > 0) { if (!txt.IsEmpty()) txt += _T("; "); txt += m_FilterView.GetHead(); if (m_FilterView.GetCount() > 1) { POSITION pos= m_FilterView.GetHeadPosition(); m_FilterView.GetNext(pos); while( pos != NULL ) txt += _T(", ") + m_FilterView.GetNext(pos); } } m_caption.FormatMessage(IDS_SUBMITTED_PERFORCE_CHANGELISTS_FILTERED, txt); } else m_caption = LoadStringResource(IDS_SUBMITTED_PERFORCE_CHANGELISTS); CP4PaneContent::GetView()->SetCaption(); } ///////////////////////////////////////////////////////////////////// // OLE drag-drop support, to accept depot files or folders // or accept user or client names which will // define a view to be used to filter the submitted // changes that this window displays. // Also can drop Jobs to be Fixed. ///////////////////////////////////////////////////////////////////// DROPEFFECT COldChgListCtrl::OnDragEnter(COleDataObject* pDataObject, DWORD dwKeyState, CPoint point) { m_DropEffect=DROPEFFECT_NONE; m_DragDataFormat=0; // Dont allow a drop if the server is busy, since a drop immediately attempts to // invoke a server command if(SERVER_BUSY()) return DROPEFFECT_NONE; if(pDataObject->IsDataAvailable( (unsigned short) m_CF_DEPOT)) { m_DropEffect=DROPEFFECT_COPY; m_DragDataFormat=m_CF_DEPOT; } else if(pDataObject->IsDataAvailable( (unsigned short) m_CF_JOB)) { // Set the display of the drag-from items m_DropEffect=DROPEFFECT_COPY; m_DragDataFormat=m_CF_JOB; // Set the scrolling data RECT rc; GetItemRect(0, &rc, LVIR_BOUNDS); m_ItemHeight = rc.bottom - rc.top; HWND hwnd = GetHeaderCtrl()->m_hWnd; if (hwnd) { ::GetWindowRect(hwnd, &rc); m_HdrHeight = rc.bottom - rc.top; } else m_HdrHeight = m_ItemHeight; m_BottomOfPage = GetCountPerPage() * m_ItemHeight + m_HdrHeight; m_bStarting = TRUE; } else if(pDataObject->IsDataAvailable( (unsigned short) m_CF_CLIENT)) { m_DropEffect=DROPEFFECT_COPY; m_DragDataFormat=m_CF_CLIENT; } else if(pDataObject->IsDataAvailable( (unsigned short) m_CF_USER)) { m_DropEffect=DROPEFFECT_COPY; m_DragDataFormat=m_CF_USER; } #ifdef UNICODE else if(pDataObject->IsDataAvailable( (unsigned short) CF_UNICODETEXT)) { m_DropEffect=DROPEFFECT_COPY; m_DragDataFormat=CF_UNICODETEXT; } #else else if(pDataObject->IsDataAvailable( (unsigned short) CF_TEXT)) { m_DropEffect=DROPEFFECT_COPY; m_DragDataFormat=CF_TEXT; } #endif return m_DropEffect; } DROPEFFECT COldChgListCtrl::OnDragOver(COleDataObject* pDataObject, DWORD dwKeyState, CPoint point) { // Dont allow a drop if the server is busy, since a drop immediately attempts to // invoke a server command if(SERVER_BUSY()) m_DropEffect= DROPEFFECT_NONE; if(pDataObject->IsDataAvailable( (unsigned short) m_CF_JOB)) { if (point.y > (m_HdrHeight + m_ItemHeight*2)) m_bStarting = FALSE; if (!m_bStarting) { if (point.y < (m_HdrHeight + m_ItemHeight/2)) Scroll(CSize(0, -m_ItemHeight)); else if (point.y > (m_BottomOfPage - m_ItemHeight/2)) Scroll(CSize(0, m_ItemHeight)); } } return m_DropEffect; } BOOL COldChgListCtrl::OnDrop(COleDataObject* pDataObject, DROPEFFECT dropEffect, CPoint point) { CString fname; if(SERVER_BUSY()) { // OnDragEnter() and OnDragOver() should avoid a drop at // the wrong time! ASSERT(0); return FALSE; } if(m_DragDataFormat == m_CF_DEPOT) { ClientToScreen(&point); ::SendMessage(m_depotWnd, WM_DROPTARGET, SUBMITTEDCHG, MAKELPARAM(point.x,point.y)); m_ForceFocusHere = TRUE; return TRUE; } if(m_DragDataFormat == m_CF_JOB) { int i = GetSelectedItem( ); if ( i > -1 ) SetItemState( i, 0, LVIS_DROPHILITED|LVIS_SELECTED|LVIS_FOCUSED ); ClientToScreen(&point); int index= GetContextItem( point ); if (index > -1) SetItemState( index, LVIS_SELECTED|LVIS_FOCUSED, LVIS_SELECTED|LVIS_FOCUSED ); CString jobname; CStringList jobnames; jobnames.AddHead(jobname = MainFrame()->GetDragFromJob()); long changeNumber = _tstol(GetSelectedItemText()); TCHAR str[ LISTVIEWNAMEBUFSIZE + 1 ]; GetItemText( index, 3, str, LISTVIEWNAMEBUFSIZE ); CString txt; txt.FormatMessage(IDS_ADD_JOB_FIX, jobname, changeNumber, str); if (IDYES == AfxMessageBox(txt, MB_ICONQUESTION|MB_YESNO)) AddJobFixes(&jobnames, changeNumber, NULL); return TRUE; } if(m_DragDataFormat == m_CF_CLIENT) { FilterByClient(MainFrame()->GetDragFromClient()); return TRUE; } if(m_DragDataFormat == m_CF_USER) { FilterByUser(MainFrame()->GetDragFromUser()); return TRUE; } #ifdef UNICODE if(m_DragDataFormat == CF_UNICODETEXT) { HGLOBAL hGlob = pDataObject->GetGlobalData(CF_UNICODETEXT); #else if(m_DragDataFormat == CF_TEXT) { HGLOBAL hGlob = pDataObject->GetGlobalData(CF_TEXT); #endif LPCTSTR p; if ((hGlob != NULL) && ((p = (LPCTSTR)::GlobalLock(hGlob)) != NULL)) { CString itemStr = p; ::GlobalUnlock(hGlob); itemStr.Format(_T("%05d"), _ttoi(itemStr)); OnEditPaste( itemStr ); } return TRUE; } // Return false, so depot window doesnt start a file-open operation return FALSE; } int COldChgListCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CP4ListCtrl::OnCreate(lpCreateStruct) == -1) return -1; SetImageList(TheApp()->GetImageList(), LVSIL_SMALL); // Insert the columns int headers[OLDCHG_MAXCOL]={IDS_CHANGELIST, IDS_DATE, IDS_P4USER, IDS_DESCRIPTION}; int width[OLDCHG_MAXCOL]={90,90,130,200}; RestoreSavedWidths(width, OLDCHG_MAXCOL, sRegValue_SubmittedChanges); int retval; LV_COLUMN lvCol; for(int subItem=0; subItem < 4; subItem++) { lvCol.mask= LVCF_FMT | LVCF_SUBITEM | LVCF_TEXT |LVCF_WIDTH; lvCol.fmt=LVCFMT_LEFT; CString header = LoadStringResource(headers[subItem]); lvCol.pszText=const_cast((LPCTSTR)header); lvCol.iSubItem=subItem; lvCol.cx=width[subItem]; retval= InsertColumn(subItem, &lvCol); } m_ColsInited = TRUE; return 0; } void COldChgListCtrl::OnUpdateAddjobfix(CCmdUI* pCmdUI) { pCmdUI->Enable(!SERVER_BUSY()); } void COldChgListCtrl::OnAddjobfix() { long changeNumber= GetSelectedChange(); if (SERVER_BUSY() || (changeNumber == 0)) { EnumChildWindows(AfxGetMainWnd()->m_hWnd, ChildSetRedraw, TRUE); ASSERT(0); return; } // Ask jobs window to update itself (if required) and send WM_P4JOBS when done // The reply message will be handled below SET_APP_HALTED(TRUE); ::SendMessage( m_jobWnd, WM_FETCHJOBS, (WPARAM)changeNumber, (LPARAM)m_hWnd); } LRESULT COldChgListCtrl::OnP4JobList(WPARAM wParam, LPARAM lParam) { long changeNumber= wParam; // Get the list of jobs CObList *jobs= (CObList *) ::SendMessage( m_jobWnd, WM_QUERYJOBS, 0, 0); CString *spec= (CString *) ::SendMessage( m_jobWnd, WM_QUERYJOBSPEC, 0, 0); CStringArray *cols= (CStringArray *) ::SendMessage( m_jobWnd, WM_QUERYJOBCOLS, 0, 0); CString *curr= (CString *) ::SendMessage( m_jobWnd, WM_QUERYJOBSELECTION, 0, 0); CJobListDlg dlg; dlg.SetJobFont(GetFont()); dlg.SetJobList(jobs); dlg.SetJobSpec(spec); dlg.SetJobCols(cols); dlg.SetJobCurr(curr); CStringList *jobnames= dlg.GetSelectedJobs(); EnumChildWindows(AfxGetMainWnd()->m_hWnd, ChildSetRedraw, TRUE); int retcode= dlg.DoModal(); SET_APP_HALTED(FALSE); // Delete the job list for(POSITION pos=jobs->GetHeadPosition(); pos!=NULL; ) delete (CP4Job *) jobs->GetNext(pos); delete jobs; if(retcode == IDOK && jobnames->GetCount() > 0) { AddJobFixes(jobnames, changeNumber, dlg.m_JobStatusValue.GetLength() ? LPCTSTR(dlg.m_JobStatusValue) : NULL); } // if IDOK else if (retcode == IDRETRY) { ::SendMessage( m_jobWnd, WM_CLEARLIST, 0, 0); PostMessage(WM_COMMAND, ID_CHANGE_ADDJOBFIX, 0); } MainFrame()->ClearStatus(); return 0; } void COldChgListCtrl::AddJobFixes(CStringList *jobnames, long changeNumber, LPCTSTR jobstatusvalue) { POSITION pos; CString str; // Copy the joblist m_JobList.RemoveAll(); for(pos= jobnames->GetHeadPosition(); pos != NULL; ) { str= jobnames->GetNext(pos); m_JobList.AddHead(str); } CCmd_Fix *pCmdFix= new CCmd_Fix; pCmdFix->Init( m_hWnd, RUN_ASYNC, LOSE_LOCK); if( pCmdFix->Run( &m_JobList, changeNumber, FALSE, jobstatusvalue ) ) { MainFrame()->UpdateStatus( LoadStringResource(IDS_FIXING_JOBS) ); } else delete pCmdFix; } void COldChgListCtrl::OnUpdateFileIntegrate(CCmdUI* pCmdUI) { pCmdUI->Enable(!SERVER_BUSY()); } void COldChgListCtrl::OnFileIntegspec() { OnIntegrate(FALSE); } void COldChgListCtrl::OnFileIntegrate() { CString str = _T("");; // long changeNumber = GetSelectedChange(); // str.Format(_T("@%ld,%ld"), changeNumber, changeNumber); CStringList stringlist; stringlist.AddHead(str); INTEGCHG integChg; integChg.useBranch = TRUE; integChg.changeList= GetSelectedChange(); integChg.filelist = &stringlist; ::SendMessage(m_depotWnd, WM_CHANGELISTINTEG, 0, (LPARAM)&integChg); } void COldChgListCtrl::OnIntegrate(BOOL useBranch) { if (MainFrame()->IsModlessUp()) return; long changeNumber= GetSelectedChange(); if(changeNumber != 0) { m_UseBranch = useBranch; CString changeTxt; changeTxt.Format(_T("%ld"), changeNumber); CCmd_Describe *pCmd= new CCmd_Describe; pCmd->Init( m_hWnd, RUN_ASYNC); pCmd->SetAlternateReplyMsg(WM_P4INTEGCHG); if( pCmd->Run( P4DESCRIBE, changeTxt) ) MainFrame()->UpdateStatus(LoadStringResource(IDS_FETCHING_CHANGELIST_DESCRIPTION)); else delete pCmd; } else AfxMessageBox ( IDS_PLEASE_SELECT_A_CHANGELIST ); } LRESULT COldChgListCtrl::OnIntegChg(WPARAM wParam, LPARAM lParam) { CCmd_Describe *pCmd= (CCmd_Describe *) wParam; if(!pCmd->GetError()) { int i, j; CString desc= MakeCRs(pCmd->GetDescription()); CString temp; CStringList stringlist; if ((i = desc.Find(_T("\nAffected files"))) != -1) { while ((j = desc.Find(_T("//"), i)) != -1) { if ((i = desc.Find(_T('#'), j)) == -1) { AfxMessageBox(_T("Unable to parse filenames from changelist - Integrate fails.")); goto breakout; } temp = desc.Mid(j, i-j); stringlist.AddTail(temp); } if (stringlist.GetCount() > 0) { INTEGCHG integChg; integChg.useBranch = m_UseBranch; integChg.changeList= GetSelectedChange(); integChg.filelist = &stringlist; ::SendMessage(m_depotWnd, WM_CHANGELISTINTEG, 0, (LPARAM)&integChg); } } } breakout: delete pCmd; MainFrame()->ClearStatus(); return 0; } void COldChgListCtrl::FilterByUser(CString user) { GET_P4REGPTR()->SetUserFilter(m_UserFilter = user); GET_P4REGPTR()->SetFilteredByUser(m_FilteredByUser = m_UserFilter.IsEmpty( ) ? FALSE : TRUE); PersistentChgFilter( KEY_WRITE ); SetCaption(); OnViewReloadall(); } void COldChgListCtrl::FilterByClient(CString client) { GET_P4REGPTR()->SetClientFilter(m_ClientFilter = client); GET_P4REGPTR()->SetFilteredByClient(m_FilteredByClient = m_ClientFilter.IsEmpty( ) ? FALSE : TRUE); PersistentChgFilter( KEY_WRITE ); SetCaption(); OnViewReloadall(); } void COldChgListCtrl::OnUpdatePositionDepot(CCmdUI* pCmdUI) { if (pCmdUI->m_pParentMenu == MainFrame()->GetMenu()) pCmdUI->SetText(LoadStringResource(IDS_FINDCHGFILESINDEPOT)); pCmdUI->Enable(!SERVER_BUSY()); } void COldChgListCtrl::OnPositionDepot() { CString changeTxt; changeTxt.Format(_T("%ld"), GetSelectedChange()); CCmd_Describe *pCmd= new CCmd_Describe; pCmd->Init( m_hWnd, RUN_ASYNC); pCmd->SetAlternateReplyMsg(WM_P4DESCRIBEALT); if( pCmd->Run( P4DESCRIBE, changeTxt) ) MainFrame()->UpdateStatus(LoadStringResource(IDS_FETCHING_CHANGELIST_DESCRIPTION)); else delete pCmd; } void COldChgListCtrl::OnPerforceOptions() { MainFrame()->OnPerforceOptions(TRUE, FALSE, IDS_PAGE_CHANGELIST); } LRESULT COldChgListCtrl::OnP4ChgRollback(WPARAM wParam, LPARAM lParam) { return OnP4DescribeAlt(wParam, 0); } LRESULT COldChgListCtrl::OnP4ChgRollbackPreview(WPARAM wParam, LPARAM lParam) { return OnP4DescribeAlt(wParam, 1); } LRESULT COldChgListCtrl::OnP4ChgSelectAll(WPARAM wParam, LPARAM lParam) { return OnP4DescribeAlt(wParam, 2); } LRESULT COldChgListCtrl::OnP4DescribeAlt(WPARAM wParam, LPARAM lParam) { CCmd_Describe *pCmd= (CCmd_Describe *) wParam; if(!pCmd->GetError()) { int i, j, count=0; BOOL preview = lParam==1; BOOL selectAll = lParam==2; CString desc= MakeCRs(pCmd->GetDescription()); MainFrame()->SetAdd2ExpandItemList(selectAll); m_StrList.RemoveAll(); CString temp; if ((i = desc.Find(_T("\nAffected files"))) != -1) { while ((j = desc.Find(_T("//"), i)) != -1) { if ((i = desc.Find(_T('#'), j)) == -1) { AfxMessageBox(_T("Unable to parse filenames from changelist - Rollback fails.")); goto breakout; } if (selectAll) { MainFrame()->ExpandDepotString( desc.Mid(j, i-j), TRUE ); while (MainFrame()->IsExpandDepotContinuing() || SERVER_BUSY()) { if ( !MainFrame()->PumpMessages( ) ) break; Sleep(250); } count++; } else { int rev = _tstoi(desc.Mid(i+1)); if (rev > 1) temp.Format(_T("%s#%d"), desc.Mid(j, i-j), rev-1); else temp.Format(_T("%s#none"), desc.Mid(j, i-j)); m_StrList.AddTail(temp); } } if (selectAll) { MainFrame()->SetAdd2ExpandItemList(FALSE); MainFrame()->SelectExpandItemList(); if (MainFrame()->GetExpandItemListCount() < count) { CString txt; int n = count - MainFrame()->GetExpandItemListCount(); txt.FormatMessage(IDS_NOTALLITEMSSELECTED_d, n, n==1 ? _T("") : _T("s")); TheApp()->StatusAdd( txt, SV_WARNING ); } } else if (m_StrList.GetCount() > 0) { CCmd_Get *pCmd2= new CCmd_Get; pCmd2->Init( m_hWnd, RUN_ASYNC); if( pCmd2->Run( &m_StrList, preview ) ) MainFrame()->UpdateStatus( LoadStringResource(IDS_FILE_SYNC) ); else delete pCmd2; } } } breakout: delete pCmd; MainFrame()->ClearStatus(); return 0; } void COldChgListCtrl::OnUpdateRemovefix(CCmdUI* pCmdUI) { pCmdUI->Enable(!m_DeleteFixesDlg && !SERVER_BUSY() && GetSelectedChange()); } void COldChgListCtrl::OnRemovefix() { int changeNum = GetSelectedChange(); if (!changeNum || m_DeleteFixesDlg) return; // Now fire off the request for all the fixes for the changelist CCmd_Fixes *pCmdFixes= new CCmd_Fixes; pCmdFixes->Init( m_hWnd, RUN_ASYNC); if( pCmdFixes->Run(changeNum, NULL) ) { MainFrame()->UpdateStatus( LoadStringResource(IDS_UPDATING_JOB_FIXES) ); } else { delete pCmdFixes; RedrawWindow(); MainFrame()->ClearStatus(); } } LRESULT COldChgListCtrl::OnP4Fixes(WPARAM wParam, LPARAM lParam) { CCmd_Fixes *pCmd= (CCmd_Fixes *) wParam; CString txt; if(!pCmd->GetError()) { m_DelFixesChgNbr = pCmd->GetFixedChangeNumber(); CObList *fixes = pCmd->GetList(); if (fixes->GetCount() > 0 && !m_DeleteFixesDlg) { m_DelFixesList.RemoveAll(); for(POSITION pos= fixes->GetHeadPosition(); pos != NULL; ) { CP4Fix *fix=(CP4Fix *) fixes->GetNext(pos); ASSERT_KINDOF(CP4Fix,fix); ASSERT(fix->GetChangeNum() == m_DelFixesChgNbr); txt.FormatMessage(IDS_s_FIXED_BY_s_ON_s, fix->GetJobName(), fix->GetUser(), fix->GetFixDate()); m_DelFixesList.AddTail(txt); delete fix; } m_DeleteFixesDlg = new CDeleteFixes(this); if (!m_DeleteFixesDlg) { ASSERT(0); AfxMessageBox(IDS_COULD_NOT_CREATE_DELFIX_DIALOG_BOX, MB_ICONSTOP); delete pCmd; return 0; } m_pJobSpec = (CString *) ::SendMessage( m_jobWnd, WM_QUERYJOBSPEC, 0, 0); if (!m_pJobSpec || m_pJobSpec->IsEmpty()) { CCmd_JobSpec *pCmd = new CCmd_JobSpec; pCmd->Init( m_hWnd, RUN_SYNC ); if( !pCmd->Run() || pCmd->GetError() ) { AddToStatus(_T("Unable to obtain the JobSpec"), SV_WARNING); //FIXME! } else { pCmd->GetSpec( m_JobSpec ); m_DeleteFixesDlg->SetJobSpec(&m_JobSpec); m_pJobSpec = NULL; } delete pCmd; } else m_DeleteFixesDlg->SetJobSpec(m_pJobSpec); txt.FormatMessage(IDS_REMOVE_FIXES_FROM_CHGLIST_d, m_DelFixesChgNbr); m_DeleteFixesDlg->SetCaption(txt); m_DeleteFixesDlg->SetSelected(&m_DelFixesList); m_DeleteFixesDlg->SetOutputList(&m_DelFixesList); m_DeleteFixesDlg->SetOutputStatus(&m_DelFixesStatus); m_DeleteFixesDlg->SetReturnMsg(WM_ONDODELETEFIXES); if (!m_DeleteFixesDlg->Create(IDD_DELETEFIXES, this)) // display the rm fixes dialog { delete m_DeleteFixesDlg; MainFrame()->SetModelessUp(FALSE); } } else { txt.FormatMessage(IDS_CHGLIST_d_HAS_NO_JOBS, m_DelFixesChgNbr); AddToStatus(txt); } } MainFrame()->ClearStatus(); delete pCmd; return 0; } LRESULT COldChgListCtrl::OnDoDeleteFixes(WPARAM wParam, LPARAM lParam) { if (wParam == IDOK) { if (m_DelFixesList.GetCount()) { int i; CString job; m_JobList.RemoveAll(); for (POSITION pos = m_DelFixesList.GetHeadPosition(); pos != NULL; ) { job = m_DelFixesList.GetNext(pos); if ((i = job.Find(_T(' '))) != -1) { job = job.Left(i); m_JobList.AddTail(job); } } CCmd_Fix *pCmd= new CCmd_Fix; pCmd->Init( m_hWnd, RUN_ASYNC, LOSE_LOCK); if( pCmd->Run( &m_JobList, m_DelFixesChgNbr, TRUE, m_DelFixesStatus.IsEmpty() ? NULL : m_DelFixesStatus.GetBuffer(40) ) ) MainFrame()->UpdateStatus( LoadStringResource(IDS_UNFIXING_JOB) ); else delete pCmd; m_DelFixesList.RemoveAll(); } else AddToStatus(LoadStringResource(IDS_NOTHING_SELECTED_NOTHING_TO_DO)); } if (m_DeleteFixesDlg) { m_DeleteFixesDlg->DestroyWindow(); // deletes m_DelSyncDlg m_DeleteFixesDlg = 0; MainFrame()->SetModelessUp(FALSE); } return 0; } LRESULT COldChgListCtrl::OnP4Fix(WPARAM wParam, LPARAM lParam) { CP4Fix *fix; CString text; BOOL b = FALSE; m_JobList.RemoveAll(); CCmd_Fix *pCmd= (CCmd_Fix *) wParam; if(!pCmd->GetError()) { CObList *list= pCmd->GetList(); if(list->GetCount() > 0) { b = pCmd->IsUnfixing() && pCmd->IsNewStatus(); POSITION pos= list->GetHeadPosition(); while( pos != NULL ) { fix= (CP4Fix *) list->GetNext(pos); UINT msgnbr; if (b) { m_JobList.AddTail(fix->GetJobName()); msgnbr = IDS_s_STATUSCHGED; } else if (pCmd->IsUnfixing()) { msgnbr = IDS_s_REMOVEDFROM_s; } else { msgnbr = IDS_s_ADDEDTO_s; } // Find the fix and display a message CString txt; txt.FormatMessage(msgnbr, fix->GetJobName(), fix->GetChangeNum()); AddToStatus(txt); delete fix; } //while } // if } MainFrame()->ClearStatus(); delete pCmd; if (b && !m_JobList.IsEmpty()) { pCmd= new CCmd_Fix; pCmd->Init( m_hWnd, RUN_ASYNC, LOSE_LOCK ); if( pCmd->Run( &m_JobList, m_DelFixesChgNbr, TRUE ) ) MainFrame()->UpdateStatus( LoadStringResource(IDS_UNFIXING_JOB) ); else delete pCmd; } return 0; }