todoctrlmgr.cpp

来自「管理项目进度工具的原代码」· C++ 代码 · 共 907 行 · 第 1/2 页

CPP
907
字号
// CToDoCtrlMgr.cpp : implementation file
//

#include "stdafx.h"
#include "ToDolist.h"
#include "ToDoCtrlMgr.h"
#include "tdstringres.h"

#include "..\shared\holdredraw.h"
#include "..\shared\enstring.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CToDoCtrlMgr dialog

enum { IM_NONE = -1, IM_READONLY, IM_CHECKEDIN, IM_CHECKEDOUT, IM_NOTLOADED };

#define ASSERTVALIDINDEX(i) { ASSERT (i >= 0 && i < GetCount()); }

CToDoCtrlMgr::CToDoCtrlMgr(CTabCtrl& tabCtrl) : m_tabCtrl(tabCtrl)
{
}

CToDoCtrlMgr::~CToDoCtrlMgr()
{
}

void CToDoCtrlMgr::SetPrefs(const CPreferencesDlg* pPrefs)
{
	m_pPrefs = pPrefs;
}

const CPreferencesDlg& CToDoCtrlMgr::Prefs() const
{
	ASSERT (m_pPrefs);
	return *m_pPrefs;
}

CFilteredToDoCtrl& CToDoCtrlMgr::GetToDoCtrl(int nIndex)
{
	ASSERTVALIDINDEX(nIndex);

	return *(m_aToDoCtrls[nIndex].pTDC);
}

const CFilteredToDoCtrl& CToDoCtrlMgr::GetToDoCtrl(int nIndex) const
{
	ASSERTVALIDINDEX(nIndex);

	return *(m_aToDoCtrls[nIndex].pTDC);
}

CToDoCtrlMgr::TDCITEM& CToDoCtrlMgr::GetTDCItem(int nIndex)
{
	ASSERTVALIDINDEX(nIndex);

	return m_aToDoCtrls[nIndex];
}

const CToDoCtrlMgr::TDCITEM& CToDoCtrlMgr::GetTDCItem(int nIndex) const
{
	// hack to get around const problem
	CToDoCtrlMgr* pThis = const_cast<CToDoCtrlMgr*>(this);
	
	return pThis->m_aToDoCtrls[nIndex];
}

CString CToDoCtrlMgr::GetFilePath(int nIndex, BOOL bStrict) const
{
	ASSERTVALIDINDEX(nIndex);

	CString sPath = GetToDoCtrl(nIndex).GetFilePath();

	if (sPath.IsEmpty() && !bStrict)
	{
		TCITEM tci;
		char szText[51];

		tci.mask = TCIF_TEXT;
		tci.cchTextMax = 50;
		tci.pszText = szText;

		m_tabCtrl.GetItem(nIndex, &tci);

		sPath = tci.pszText;
		FileMisc::ValidateFilename(sPath);
	}

	return sPath;
}

CString CToDoCtrlMgr::GetFriendlyProjectName(int nIndex) const
{
	ASSERTVALIDINDEX(nIndex);

	return m_aToDoCtrls[nIndex].GetFriendlyProjectName();
}

void CToDoCtrlMgr::ClearFilePath(int nIndex)
{
	ASSERTVALIDINDEX(nIndex);

	GetToDoCtrl(nIndex).ClearFilePath();
}

BOOL CToDoCtrlMgr::IsFilePathEmpty(int nIndex) const
{
	ASSERTVALIDINDEX(nIndex);

	return GetFilePath(nIndex).IsEmpty();
}

TDCM_PATHTYPE CToDoCtrlMgr::GetFilePathType(int nIndex) const
{
	ASSERTVALIDINDEX(nIndex);

	// we do it this way because of const
	return m_aToDoCtrls[nIndex].GetPathType();
}

TDCM_PATHTYPE CToDoCtrlMgr::RefreshPathType(int nIndex) 
{
	ASSERTVALIDINDEX(nIndex);

	TDCITEM& tdci = GetTDCItem(nIndex);

	tdci.RefreshPathType();
	return tdci.nPathType;
}

BOOL CToDoCtrlMgr::IsPristine(int nIndex) const
{
	return IsFilePathEmpty(nIndex) && !GetModifiedStatus(nIndex);
}

BOOL CToDoCtrlMgr::IsLoaded(int nIndex) const
{
	ASSERTVALIDINDEX(nIndex);

	return GetTDCItem(nIndex).bLoaded;
}

void CToDoCtrlMgr::SetLoaded(int nIndex, BOOL bLoaded)
{
	ASSERTVALIDINDEX(nIndex);

	GetTDCItem(nIndex).bLoaded = bLoaded;
}

BOOL CToDoCtrlMgr::RefreshLastModified(int nIndex)
{
	ASSERTVALIDINDEX(nIndex);
	TDCITEM& tdci = GetTDCItem(nIndex);

	time_t timeNow = FileMisc::GetLastModified(tdci.pTDC->GetFilePath());
	time_t timePrev = tdci.tLastMod;

	tdci.tLastMod = timeNow;

	// if the tasklist is checked out then always return FALSE because
	// noone else should be able to modify it (by any means).
	if (tdci.pTDC->IsCheckedOut())
		return FALSE;

	// else
	return (timeNow > 0 && timePrev > 0 && timeNow != timePrev);
}

BOOL CToDoCtrlMgr::RefreshReadOnlyStatus(int nIndex)
{
	ASSERTVALIDINDEX(nIndex);

	TDCITEM& tdci = GetTDCItem(nIndex);

	BOOL bReadOnlyNow = CDriveInfo::IsReadonlyPath(tdci.pTDC->GetFilePath()) > 0;
	BOOL bReadOnlyPrev = tdci.bLastStatusReadOnly;

	GetTDCItem(nIndex).bLastStatusReadOnly = bReadOnlyNow;

	return (bReadOnlyNow != -1 && bReadOnlyPrev != -1 && bReadOnlyNow != bReadOnlyPrev);
}

int CToDoCtrlMgr::GetReadOnlyStatus(int nIndex) const
{
	ASSERTVALIDINDEX(nIndex);

	return GetTDCItem(nIndex).bLastStatusReadOnly;
}

void CToDoCtrlMgr::SetDueItemStatus(int nIndex, TDCM_DUESTATUS nStatus)
{
	ASSERTVALIDINDEX(nIndex);

	GetTDCItem(nIndex).nDueStatus = nStatus;
}

TDCM_DUESTATUS CToDoCtrlMgr::GetDueItemStatus(int nIndex) const
{
	ASSERTVALIDINDEX(nIndex);

	return GetTDCItem(nIndex).nDueStatus;
}

int CToDoCtrlMgr::GetLastCheckoutStatus(int nIndex) const
{
	ASSERTVALIDINDEX(nIndex);

	return GetTDCItem(nIndex).bLastCheckoutSuccess;
}

void CToDoCtrlMgr::SetLastCheckoutStatus(int nIndex, BOOL bStatus)
{
	ASSERTVALIDINDEX(nIndex);

	GetTDCItem(nIndex).bLastCheckoutSuccess = bStatus;
}

int CToDoCtrlMgr::CanCheckOut(int nIndex) const
{
	return (CanCheckInOut(nIndex) && !GetToDoCtrl(nIndex).IsCheckedOut());
}

int CToDoCtrlMgr::CanCheckIn(int nIndex) const
{
	return (CanCheckInOut(nIndex) && GetToDoCtrl(nIndex).IsCheckedOut());
}

int CToDoCtrlMgr::CanCheckInOut(int nIndex) const
{
	ASSERTVALIDINDEX(nIndex);

	if (!Prefs().GetEnableSourceControl())
		return FALSE;

	const CFilteredToDoCtrl& tdc = GetToDoCtrl(nIndex);
	
	BOOL bCanCheckInOut = (tdc.CompareFileFormat() != TDCFF_NEWER);
	
	if (bCanCheckInOut)
	{
		bCanCheckInOut &= PathSupportsSourceControl(nIndex);
		
		if (bCanCheckInOut)
			bCanCheckInOut &= !GetReadOnlyStatus(nIndex);
	}

	return bCanCheckInOut;
}

void CToDoCtrlMgr::SetModifiedStatus(int nIndex, BOOL bMod)
{
	ASSERTVALIDINDEX(nIndex);

	GetTDCItem(nIndex).bModified = bMod;
}

BOOL CToDoCtrlMgr::GetModifiedStatus(int nIndex) const
{
	ASSERTVALIDINDEX(nIndex);

	return GetTDCItem(nIndex).bModified;
}

void CToDoCtrlMgr::RefreshModifiedStatus(int nIndex)
{
	ASSERTVALIDINDEX(nIndex);

	TDCITEM& tdci = GetTDCItem(nIndex);
	tdci.bModified = tdci.pTDC->IsModified();
}

void CToDoCtrlMgr::UpdateToDoCtrlReadOnlyUIState(int nIndex)
{
	ASSERTVALIDINDEX(nIndex);

	CFilteredToDoCtrl& tdc = GetToDoCtrl(nIndex);
	UpdateToDoCtrlReadOnlyUIState(tdc);
}

void CToDoCtrlMgr::UpdateToDoCtrlReadOnlyUIState(CFilteredToDoCtrl& tdc)
{
    LPCTSTR szPath = tdc.GetFilePath();
	BOOL bReadOnly = CDriveInfo::IsReadonlyPath(szPath) >  0;
	
    if (!bReadOnly)
        bReadOnly = (tdc.CompareFileFormat() == TDCFF_NEWER);
	
	if (!bReadOnly)
		bReadOnly = (PathSupportsSourceControl(szPath) && !tdc.IsCheckedOut());
	
	if (!bReadOnly && !Prefs().GetEnableSourceControl())
		bReadOnly = tdc.IsSourceControlled();

	tdc.SetReadonly(bReadOnly);
}

int CToDoCtrlMgr::RemoveToDoCtrl(int nIndex, BOOL bDelete)
{
	ASSERTVALIDINDEX(nIndex);

	int nSel = GetSelToDoCtrl(), nNewSel = -1;

	CFilteredToDoCtrl& tdc = GetToDoCtrl(nIndex);
	TDCITEM& tdci = GetTDCItem(nIndex);

	// save state first
	SaveColumns(&tdci);
	SaveFilter(&tdc);

	if (bDelete)
	{
		// checkin as our final task
		if (Prefs().GetCheckinOnClose() && PathSupportsSourceControl(nIndex))
			tdc.CheckIn();
	}
	
	m_aToDoCtrls.RemoveAt(nIndex);
	m_tabCtrl.DeleteItem(nIndex);

	// set new selection as close to previous as possible
	// *before* deleting the tasklist
	if (GetCount())
	{
		if (nIndex <= nSel)
			nNewSel = max(0, nSel - 1);
		else
			nNewSel = nSel;

		m_tabCtrl.SetCurSel(nNewSel);
	}

	if (bDelete)
	{
		tdc.DestroyWindow();
		delete &tdc;
	}

   return nNewSel;
}

int CToDoCtrlMgr::AddToDoCtrl(CFilteredToDoCtrl* pCtrl, BOOL bLoaded)
{
	static int nNextIndex = 0;

	TDCITEM tdci(pCtrl, nNextIndex++, bLoaded);

	// restore previous state
	if (Prefs().GetRestoreTasklistFilters())
		RestoreFilter(pCtrl);

	RestoreColumns(&tdci);

	// add to tab
	int nSel = m_aToDoCtrls.Add(tdci);
	m_tabCtrl.InsertItem(nSel, "");

	UpdateTabItemText(nSel);
	RefreshPathType(nSel);


	return nSel;
}

void CToDoCtrlMgr::RestoreFilter(CFilteredToDoCtrl* pCtrl)
{
	CString sFilePath(pCtrl->GetFilePath());

	if (!sFilePath.IsEmpty())
	{
		CString sKey;
		sFilePath.Replace('\\', '_');
		sKey.Format("FileStates\\%s\\Filter", sFilePath);

		FTDCFILTER filter;

		filter.nFilter = (FILTER_TYPE)AfxGetApp()->GetProfileInt(sKey, "Filter", FT_ALL);
		filter.nPriority = AfxGetApp()->GetProfileInt(sKey, "Priority", FT_ANYPRIORITY);
		filter.nRisk = AfxGetApp()->GetProfileInt(sKey, "Risk", FT_ANYRISK);
		filter.sAllocBy = AfxGetApp()->GetProfileString(sKey, "AllocBy");
		filter.sStatus = AfxGetApp()->GetProfileString(sKey, "Status");

		// cats
		filter.SetFlag(FT_ANYCATEGORY, AfxGetApp()->GetProfileInt(sKey, "AnyCategory", FALSE));
		CString sCategory = AfxGetApp()->GetProfileString(sKey, "Category");
		Misc::ParseIntoArray(sCategory, filter.aCategories, TRUE);

		// alloc to
		filter.SetFlag(FT_ANYALLOCTO, AfxGetApp()->GetProfileInt(sKey, "AnyAllocTo", FALSE));
		CString sAllocTo = AfxGetApp()->GetProfileString(sKey, "AllocTo");
		Misc::ParseIntoArray(sAllocTo, filter.aAllocTo, TRUE);
		
		pCtrl->SetFilter(filter);
	}
}

void CToDoCtrlMgr::SaveFilter(const CFilteredToDoCtrl* pCtrl) const
{
	CString sFilePath(pCtrl->GetFilePath());

	if (!sFilePath.IsEmpty())
	{
		CString sKey;
		sFilePath.Replace('\\', '_');
		sKey.Format("FileStates\\%s\\Filter", sFilePath);

		FTDCFILTER filter;
		pCtrl->GetFilter(filter);

		AfxGetApp()->WriteProfileInt(sKey, "Filter", filter.nFilter);
		AfxGetApp()->WriteProfileInt(sKey, "Priority", filter.nPriority);
		AfxGetApp()->WriteProfileInt(sKey, "Risk", filter.nRisk);
		AfxGetApp()->WriteProfileString(sKey, "AllocBy", filter.sAllocBy);
		AfxGetApp()->WriteProfileString(sKey, "Status", filter.sStatus);
		AfxGetApp()->WriteProfileString(sKey, "AllocTo", Misc::FormatArray(filter.aAllocTo));
		AfxGetApp()->WriteProfileInt(sKey, "AnyAllocTo", filter.HasFlag(FT_ANYALLOCTO));
		AfxGetApp()->WriteProfileString(sKey, "Category", Misc::FormatArray(filter.aCategories));
		AfxGetApp()->WriteProfileInt(sKey, "AnyCategory", filter.HasFlag(FT_ANYCATEGORY));
	}
}

void CToDoCtrlMgr::RefreshColumns(int nIndex, CTDCColumnArray& aColumns /*out*/)
{
	ASSERTVALIDINDEX(nIndex);

	// if the todoctrl does not have its own columns we use the default
	// preferences set else we return it's own set.
	if (!HasOwnColumns(nIndex))
	{
		Prefs().GetVisibleColumns(aColumns);
		GetToDoCtrl(nIndex).SetVisibleColumns(aColumns);
	}
	else
		GetToDoCtrl(nIndex).GetVisibleColumns(aColumns);
}

BOOL CToDoCtrlMgr::HasOwnColumns(int nIndex) const
{
	ASSERTVALIDINDEX(nIndex);

	return GetTDCItem(nIndex).bHasOwnColumns;
}

void CToDoCtrlMgr::SetHasOwnColumns(int nIndex, BOOL bHas)
{
	ASSERTVALIDINDEX(nIndex);

	GetTDCItem(nIndex).bHasOwnColumns = bHas;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?