classtreenodedata.cpp

来自「深入浅出Visual C++入门进阶与应用实例 随书光盘 作者 何志丹」· C++ 代码 · 共 1,113 行 · 第 1/2 页

CPP
1,113
字号
// ClassTreeNodeData.cpp: implementation of the CClassTreeNodeData class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "ClassTreeNodeData.h"

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

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

//==================================================================//
//              CClassTreeNodeData                                  //
//==================================================================//

CClassTreeNodeData::CClassTreeNodeData()
{
	m_pParentNode = NULL ;
}

CClassTreeNodeData::~CClassTreeNodeData()
{
	for(int i = m_arContentData.GetSize() -1 ; i>= 0 ; i-- )
	{
		CArticleData * pData = m_arContentData[i];
		ASSERT(NULL != pData);
		delete pData ;
	}
	m_arContentData.RemoveAll();
	
	for(i = m_pSubNode.GetSize() -1 ; i >= 0 ; i-- )
	{
		CClassTreeNodeData * pTreeNode = m_pSubNode[i];
		ASSERT(NULL != pTreeNode);
		delete pTreeNode ;
	}
	m_pSubNode.RemoveAll() ;
}


bool CClassTreeNodeData::ReadFromDB()
{
	CArray<CClassTreeNodeData*,CClassTreeNodeData*> pNodeDatas;
	if(!ReadFromClassTreeTable(pNodeDatas))
		return false;

	CArray<CArticleData *,CArticleData *> pContentDatas;
	if(!ReadFromArticleTable(pContentDatas))
		return false;

	//建立两者之间的关系
	for(int i = pNodeDatas.GetSize()-1 ; i >= 0 ; i--)
	{
		CClassTreeNodeData * pNodeData = pNodeDatas[i] ;
		ASSERT(NULL != pNodeData);
		for(int j = pContentDatas.GetSize() -1 ; j >= 0 ; j--)
		{
			CArticleData * pContentData = pContentDatas[j];
			ASSERT(NULL != pContentData);
			if(pNodeData->m_nID == pContentData->m_forumid)
			{
				pNodeData->m_arContentData.Add(pContentData);
				pContentDatas.RemoveAt(j);
			}
		}
	}

	//将没有联系的CContentData,从内存中删除
	ASSERT(0 == pContentDatas.GetSize());
	for(i = 0 ; i < pContentDatas.GetSize() ; i++ )
		delete pContentDatas[i] ;
	pContentDatas.RemoveAll();

	return true;
}

bool CClassTreeNodeData::ReadFromClassTreeTable(CArray<CClassTreeNodeData*,CClassTreeNodeData*>& pNodeDatas)
{
	pNodeDatas.RemoveAll();

	CClassSet rsRoot(CDB::GetDefaultDB());

	//寻找根结点
	rsRoot.m_strFilter = "ParentID=-1" ;
	rsRoot.Open();
	ASSERT(1 == rsRoot.GetRecordCount());//有且只能有一个根节点
	if(rsRoot.GetRecordCount() == 0)
	{
		rsRoot.Close();
		return false;
	}
	m_nID = rsRoot.m_nID ;
	m_strText = rsRoot.m_strText ;
	m_strDirName = rsRoot.m_strDir ;
	rsRoot.Close();

	//将非根节点,读进内存
	CClassSet rs(CDB::GetDefaultDB());
	rs.m_strFilter = "ParentID<>-1" ;
    rs.Open();//重新打开一下
	CUIntArray pParentID ;
	while(!rs.IsEOF())
	{
		CClassTreeNodeData * pNodeData= new CClassTreeNodeData;
		if(NULL == pNodeData)
		{
			rs.Close();
			return false;
		}
		pNodeData->m_nID			= rs.m_nID ;
		pNodeData->m_strText		= rs.m_strText;
		pNodeData->m_strDirName		= rs.m_strDir ;
		pNodeDatas.Add(pNodeData);
		pParentID.Add(rs.m_nParentID) ;	
		rs.MoveNext();
	}
	
	//理顺父子关系
	const int nRecordCount = pNodeDatas.GetSize() ;
	for(int i = 0 ; i < nRecordCount ; i++ )
	{
		CClassTreeNodeData * pData = pNodeDatas[i] ;
		if(m_nID == pParentID[i])//节点的子节点
		{
			pData->m_pParentNode = this ;
			m_pSubNode.Add(pData);
			continue;
		}
		for(int j = 0 ; j < nRecordCount ; j++ )
		{
			CClassTreeNodeData * pParentData = pNodeDatas[j] ;
			if(pParentData->m_nID == pParentID[i])
			{
				pData->m_pParentNode = pParentData ;
				pParentData->m_pSubNode.Add(pData);
				break;
			}
		}
		ASSERT(j != nRecordCount) ;//非根节点必须有次节点
	
	}    

	//检验非法数据,并释放所占内存
	//检验所有节点的祖宗节点的父ID是不是-1.
	for(i = nRecordCount-1 ; i >=0  ; i-- )
	{
		CClassTreeNodeData * pData = pNodeDatas[i] ;
		ASSERT(NULL != pData);
		CClassTreeNodeData * pParentData = NULL ;
		do 
		{
			pParentData = pData->m_pParentNode ;
			if(NULL == pParentData)
				break;
			pData = pParentData ;
		} while(true);
		if(pData->m_nID != m_nID )
		{
			ASSERT(false);//此节点的祖宗节点不是合法的根节点
			delete pData ;
			pNodeDatas.RemoveAt(i) ;
		}
	}	

	rs.Close();
	
	return true ;
}

bool CClassTreeNodeData::ReadFromArticleTable(CArray<CArticleData *,CArticleData *>& pContentDatas)
{
	pContentDatas.RemoveAll();

	CArticleSet rs;
	rs.m_strSort = "ArticleID DESC" ;
	try
	{
		rs.Open();
	}
	catch(CDBException * e )
	{
		e->m_strError ;
		ASSERT(false);
	}
	//将数据读到内存中
    while(!rs.IsEOF())
	{		
		CArticleData * pData = new CArticleData ;
		if(NULL == pData)
		{
			ASSERT(false);
			rs.Close();
			return false;
		}		
		pData->m_ArticleID	= rs.m_ArticleID ;
		pData->m_content	= rs.m_content ;
		pData->m_FileName	= rs.m_FileName ;
		pData->m_forumid    = rs.m_forumid ;
		pData->m_topic		= rs.m_topic;

		pContentDatas.Add(pData);
		rs.MoveNext();
	}		
	rs.Close();

	return true ;
}

bool CClassTreeNodeData::DeleteTreeNode(int nID)
{
	CClassTreeNodeData * pNode = NULL ;
	CClassTreeNodeData * pParentNode = NULL ;
	
	pNode = GetTreeNodeByID(nID);
	if(NULL == pNode)
	{
		ASSERT(false);
		return false;
	}

	//为了减少误操作,当此节点有文章或子节点,给出提示
	{
		CString strMess = "你确认要删除此节点及其子节点和所属的文章吗?";
		CWnd * pMainFrm = AfxGetMainWnd();
		HWND hWnd = NULL ;
		if(NULL != pMainFrm )
			hWnd = pMainFrm->GetSafeHwnd() ;
		if(IDOK != MessageBox(hWnd,strMess,"确认",MB_OKCANCEL))
			return false ;
	}

	//父节点为空,是根节点无法删除
	pParentNode = pNode->m_pParentNode ;
	if(NULL == pParentNode)
	{
		ASSERT(false);
		return false;
	}
	
	for(int i = pParentNode->m_pSubNode.GetSize()-1 ; i >= 0 ; i-- )
	{
		CClassTreeNodeData * pSubNode = pParentNode->m_pSubNode[i];
		if(NULL == pSubNode)
		{
			ASSERT(false);
			continue;
		}
		if(pSubNode->m_nID = nID )//要删除的子项
		{
			delete pSubNode ;//释放内存
			pParentNode->m_pSubNode.RemoveAt(i);
			CClassSet::DeleteTreeNode(nID);//从数据库中删除
			return true;
		}
	}

	return false ;//未找到删除的项
}

 bool CClassTreeNodeData::EditTreeNode(int nID, CString strContent, CString strDir, int nParentID)
{
	CClassTreeNodeData * pNode = GetTreeNodeByID(nID);
	if(NULL == pNode)
	{
		ASSERT(false);
		return false ;
	}    

	pNode->m_strText	= strContent ;
	pNode->m_strDirName = strDir ;
	CClassTreeNodeData * pParentNode = pNode->m_pParentNode ;
	if(NULL != pParentNode && pParentNode->m_nID != nParentID)//不能更改根节点的父节点
	{//更改了父节点
		//原父节点中删除子节点
		for(int i = pParentNode->m_pSubNode.GetSize()-1 ; i >= 0 ; i-- )
		{
			CClassTreeNodeData * pSubNode = pParentNode->m_pSubNode[i] ;
			if(NULL == pSubNode)
			{
				ASSERT(false);
				continue;
			}
			if(pSubNode->m_nID == nID )
			{
				pParentNode->m_pSubNode.RemoveAt(i);
				break;
			}
		}	
		ASSERT(i >= 0 );//原父节点中没有找到此节点

		//在此节点加到新父节点中
		CClassTreeNodeData * pNewParentNode = GetTreeNodeByID(nParentID);
		if(NULL == pNewParentNode)
		{
			ASSERT(false);
			return false;
		}
		pNewParentNode->m_pSubNode.Add(pNode);
		
		pNode->m_pParentNode = pNewParentNode ;//设置父节点
	 }	

	CClassSet::EditTreeNode(nID,strContent,nParentID,strDir);//修改数据库

	return true ;

}

bool CClassTreeNodeData::AddTreeNode(const CString strText, int nParentID, CString strDir, int &nID)
{
	//存数据库时才分配ID
	if(!CClassSet::AddTreeNode(strText,nParentID,strDir,nID))
		return false ;

	CClassTreeNodeData * pParentNode = GetTreeNodeByID(nParentID);
	if(NULL == pParentNode)
	{
		ASSERT(false);
		return false;
	}
	CClassTreeNodeData * pNode = new CClassTreeNodeData ;
	pNode->m_nID		= nID ;
	pNode->m_strText	= strText ;
	pNode->m_strDirName = strDir ;
	pNode->m_pParentNode= pParentNode ;

	pParentNode->m_pSubNode.Add(pNode);

	return true ;
}

//=======================================================//
//                CMainData                              //
//=======================================================//

CMainData::CMainData()
{
	m_pCurTreeNode = NULL ;	
}

CMainData::~CMainData()
{
	WriteToFile();	
}

bool CMainData::CanMovePre()
{
	if(NULL == m_pCurTreeNode)
	{
		ASSERT(false);
		return false;
	}
	
	ASSERT(m_pCurTreeNode >= 0 );

	if(0 == m_nCurContentIndex)
		return false;//已经到最前面了
	
	return true;
}

bool CMainData::CanMoveNext()
{
	if(NULL == m_pCurTreeNode)
	{
		ASSERT(false);
		return false;
	}
	
	if(m_nCurContentIndex >= m_pCurTreeNode->m_arContentData.GetSize())
		return false;//已经到最后了.注意有一条空记录,便于用户增加新记录
	
	return true ;
}

bool CMainData::CanMoveLast()
{
	if(NULL == m_pCurTreeNode)
	{
		ASSERT(false);
		return false;
	}
	
	if(m_nCurContentIndex >= m_pCurTreeNode->m_arContentData.GetSize()-1)
		return false;//已经到最后了.
	
	return true ;	
}

bool CMainData::MovePre()
{
	if(!CanMovePre())
		return false ;
	
	m_nCurContentIndex-- ;	
	AdjustRecentArticleAClass();

	return true;
}

bool CMainData::MoveNext()
{
	if(!CanMoveNext())
		return false;

	m_nCurContentIndex++ ;
	AdjustRecentArticleAClass();

	return true;
}



bool CMainData::MoveFirst()
{
	if(!CanMovePre())
		return false;

	m_nCurContentIndex = 0 ;
	AdjustRecentArticleAClass();
	
	return true;
}

bool CMainData::MoveLast()
{
	if(!CanMoveNext())
		return false;

	m_nCurContentIndex = m_pCurTreeNode->m_arContentData.GetSize()-1 ;
	AdjustRecentArticleAClass();

	return true;
}

CClassTreeNodeData* CMainData::GetCurTreeNode()
{
	return m_pCurTreeNode ;
}

CArticleData* CMainData::GetCurArticleData()
{
	if(NULL == m_pCurTreeNode)
		return NULL;
	if(m_nCurContentIndex < 0 || m_nCurContentIndex >= m_pCurTreeNode->m_arContentData.GetSize())
		return NULL;
	
	return m_pCurTreeNode->m_arContentData[m_nCurContentIndex];
}


CClassTreeNodeData* CClassTreeNodeData::GetTreeNodeByID(int nID)
{
	if(nID == m_nID)
		return this ;

	for(int i = m_pSubNode.GetSize()-1 ; i >= 0 ; i-- )
	{
		CClassTreeNodeData * pNode = m_pSubNode[i]->GetTreeNodeByID(nID);
		if(NULL != pNode )
			return pNode ;
	}

	return NULL ;
}

bool CMainData::SetCurTreeNode(int nID)
{
	if(NULL != m_pCurTreeNode && nID == m_pCurTreeNode->m_nID )
		return true ;//节点没有改变,无须修改

	CClassTreeNodeData * pNode = m_ClassTreeRoot.GetTreeNodeByID(nID);
	if(NULL == pNode)
	{
		ASSERT(false);
		return false ;
	}


	m_pCurTreeNode = pNode ;
	m_nCurContentIndex = m_mRecentArticleID[nID] ;
	return true;
}

bool CMainData::DeleteTreeNode(int nID)
{
	if(NULL != m_pCurTreeNode && nID == m_pCurTreeNode->m_nID)
		m_pCurTreeNode = NULL ;

	return m_ClassTreeRoot.DeleteTreeNode(nID);
}

bool CMainData::EditTreeNode(int nID, CString strContent, CString strDir, int nParentID)
{
	//不影响当前分类及当前内容
	return m_ClassTreeRoot.EditTreeNode(nID,strContent,strDir,nParentID);
}


bool CMainData::AddTreeNode(const CString strText, int nParentID, CString strDir, int &nID)
{
	if(!m_ClassTreeRoot.AddTreeNode(strText,nParentID,strDir,nID))
		return false;

	if(!SetCurTreeNode(nID))
		return false;

	return true;
}

bool CMainData::Init()
{
	if(!m_ClassTreeRoot.ReadFromDB())
		return false ;

	ReadFromFile();
	
	return true ;
}

CClassTreeNodeData* CMainData::GetTreeNodeByID(int nID)
{
	return m_ClassTreeRoot.GetTreeNodeByID(nID);
}


bool CMainData::DeleteCurArticle()
{
	if(NULL == m_pCurTreeNode )
	{
		ASSERT(false);
		return false ;
	}
	if(m_nCurContentIndex < 0 || m_nCurContentIndex >= m_pCurTreeNode->m_arContentData.GetSize())
	{
		ASSERT(false);
		return false ;
	}
	//先从内存中删除,再从数据库中删除
	CArticleData * pData = m_pCurTreeNode->m_arContentData[m_nCurContentIndex];
	int nID = pData->m_ArticleID ;
	delete pData ;	
	m_pCurTreeNode->m_arContentData.RemoveAt(m_nCurContentIndex);

	CArticleSet::DeleteArticle(nID);

	return true ;
}

bool CMainData::CanDeleteArticle()
{

⌨️ 快捷键说明

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