//
// 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<LPTSTR>((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<LPTSTR>((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<LPTSTR>((LPCTSTR)txt); break;
case 1:
lvItem.pszText= const_cast<LPTSTR>((LPCTSTR)change->GetChangeDate()); break;
case 2:
lvItem.pszText= const_cast<LPTSTR>((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<len; i++)
{
if(*ptr==_T('\r'))
{
*ptrout=_T(' ');
ptrout++;
}
else if(*ptr!=_T('\n') && *ptr!=_T('\t'))
{
*ptrout=*ptr;
ptrout++;
}
ptr++;
}
*ptrout=_T('\0');
txtout.ReleaseBuffer();
lvItem.pszText=const_cast<LPTSTR>((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<LPTSTR>((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;
}
| # | Change | User | Description | Committed | |
|---|---|---|---|---|---|
| #1 | 19924 | YourUncleBob |
Populate -o //guest/perforce_software/p4win/... //guest/YourUncleBob/p4win/..... |
||
| //guest/perforce_software/p4win/main/gui/OldChgListCtrl.cpp | |||||
| #1 | 16169 | perforce_software | Move files to follow new path scheme for branches. | ||
| //guest/perforce_software/p4win/gui/OldChgListCtrl.cpp | |||||
| #1 | 8562 | Matt Attaway |
These feet never stop running. Initial commit of the P4Win source code. To the best of our knowledge this compiles and runs using the 2013.3 P4 API and VS 2010. Expect a few changes as we refine the build process. Please post any build issues to the forums. |
||