//
// DownloadGroup.h
//
// Copyright (c) Shareaza Development Team, 2002-2005.
// This file is part of SHAREAZA (www.shareaza.com)
//
// Shareaza is free software; you can redistribute it
// and/or modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Shareaza is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Shareaza; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
#pragma once
class CDownload;
/*
管理一个CDownload指针数组m_pDownloads,
还有一个过滤器数组m_pFilters,保存了本DownloadGroup
可以保存的过滤字符串,例如.rmvb等
*/
class CDownloadGroup
{
// Construction
public:
CDownloadGroup();
virtual ~CDownloadGroup();
// Attributes
protected:
CPtrList m_pDownloads;
public:
CString m_sName;
CString m_sSchemaURI;
CString m_sFolder;
CStringList m_pFilters;
public:
int m_nImage;
BOOL m_bRemoteSelected;
// Operations
public:
void Add(CDownload* pDownload);
void Remove(CDownload* pDownload);
void SetCookie(int nCookie);
void CopyList(CPtrList* pList);
BOOL Link(CDownload* pDownload);
int LinkAll();
void AddFilter(LPCTSTR pszFilter);
void SetSchema(LPCTSTR pszURI);
void Serialize(CArchive& ar, int nVersion);
// Inlines
public:
inline POSITION GetIterator() const
{
return m_pDownloads.GetHeadPosition();
}
inline CDownload* GetNext(POSITION& pos) const
{
return (CDownload*)m_pDownloads.GetNext( pos );
}
inline BOOL Contains(CDownload* pDownload) const
{
return m_pDownloads.Find( pDownload ) != NULL;
}
inline int GetCount() const
{
return m_pDownloads.GetCount();
}
};
//
// DownloadGroup.cpp
//
// Copyright (c) Shareaza Development Team, 2002-2005.
// This file is part of SHAREAZA (www.shareaza.com)
//
// Shareaza is free software; you can redistribute it
// and/or modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Shareaza is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Shareaza; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
#include "StdAfx.h"
#include "Shareaza.h"
#include "DownloadGroup.h"
#include "DownloadGroups.h"
#include "Downloads.h"
#include "Download.h"
#include "Schema.h"
#include "SchemaCache.h"
#include "ShellIcons.h"
#include "QuerySearch.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//
// CDownloadGroup construction
CDownloadGroup::CDownloadGroup()
{
//默认m_nImage为打开的文件夹,m_bRemoteSelected为真
m_nImage = SHI_FOLDER_OPEN;
m_bRemoteSelected = TRUE;
}
CDownloadGroup::~CDownloadGroup()
{
}
//
// CDownloadGroup add and remove
//如果在m_pDownloads中没有找到参数pDownload,则加入到m_pDownloads
//然后DownloadGroups.m_nBaseCookie增加1
void CDownloadGroup::Add(CDownload* pDownload)
{
if ( m_pDownloads.Find( pDownload ) == NULL )
{
m_pDownloads.AddTail( pDownload );
DownloadGroups.m_nBaseCookie ++;
}
}
//如果在m_pDownloads中找到了参数pDownload,则删除之
//然后DownloadGroups.m_nBaseCookie增加1
void CDownloadGroup::Remove(CDownload* pDownload)
{
if ( POSITION pos = m_pDownloads.Find( pDownload ) )
{
m_pDownloads.RemoveAt( pos );
DownloadGroups.m_nBaseCookie ++;
}
}
//
// CDownloadGroup set selection cookie
//将当前m_pDownloads中所有的CDownload对象的m_nGroupCookie
//设置为参数nCookie
void CDownloadGroup::SetCookie(int nCookie)
{
for ( POSITION pos = GetIterator() ; pos ; )
{
GetNext( pos )->m_nGroupCookie = nCookie;
}
}
//
// CDownloadGroup list copy
//将m_pDownloads中的所有内容拷贝到参数pList中
void CDownloadGroup::CopyList(CPtrList* pList)
{
for ( POSITION pos = GetIterator() ; pos ; )
{
pList->AddTail( GetNext( pos ) );
}
}
//
// CDownloadGroup conditional add
/*
在m_pFilters链表中遍历,如果pDownload是torrent而且过滤链表中有
torrent,则将参数pDownload加入到m_pDownloads链表中,如果
pDownload的RemoteName和过滤参数strFilter相同,则加入pDownLoad
*/
BOOL CDownloadGroup::Link(CDownload* pDownload)
{
if ( m_pFilters.IsEmpty() )//m_pFilters为空则直接返回
{
return FALSE;
}
for ( POSITION pos = m_pFilters.GetHeadPosition() ; pos ; )
{
CString strFilter = m_pFilters.GetNext( pos );
if ( ( pDownload->m_bBTH
&& strFilter.CompareNoCase( _T("torrent") ) == 0 )
|| CQuerySearch::WordMatch( pDownload->m_sRemoteName,
strFilter ) )
{
Add( pDownload );
return TRUE;
}
}
return FALSE;
}
//
// CDownloadGroup conditional add all downloads
//将Downloads数组中的所有符合条件的项加入到m_pDownloads中
//返回加入的CDownload的数目
int CDownloadGroup::LinkAll()
{
if ( m_pFilters.IsEmpty() )
{
return 0;
}
int nCount = 0;
for ( POSITION pos = Downloads.GetIterator() ; pos ; )
{
nCount += Link( Downloads.GetNext( pos ) );
}
return nCount;
}
//
// CDownloadGroup add a filter
//在m_pFilters中加入一个过滤参数字符串
void CDownloadGroup::AddFilter(LPCTSTR pszFilter)
{
m_pFilters.AddTail( pszFilter );
}
//
// CDownloadGroup schema
//根据参数pszURI设置m_nImage和m_sSchemaURI的值
void CDownloadGroup::SetSchema(LPCTSTR pszURI)
{
//将m_sSchemaURI设置为参数pszURI
if ( m_sSchemaURI != pszURI )
{
m_sSchemaURI = pszURI;
}
//如果在SchemaCache中能找到,则设置m_nImage为icon
//否则设置为打开的文件夹
if ( CSchema* pSchema = SchemaCache.Get( pszURI ) )
{
m_nImage = pSchema->m_nIcon16;
}
else
{
m_nImage = SHI_FOLDER_OPEN;
}
}
//
// CDownloadGroup serialise
void CDownloadGroup::Serialize(CArchive& ar, int nVersion)
{
if ( ar.IsStoring() )
{
ar << m_sName;
ar << m_sSchemaURI;
ar << m_sFolder;
//先写入过滤字符串的数目,然后写入各个过滤字符串
ar.WriteCount( m_pFilters.GetCount() );
for ( POSITION pos = m_pFilters.GetHeadPosition() ; pos ; )
{
ar << m_pFilters.GetNext( pos );
}
//先写入m_pDownLoads中的数目,然后写入各个CDownLoad的m_nSerID
ar.WriteCount( GetCount() );
for ( POSITION pos = GetIterator() ; pos ; )
{
DWORD nDownload = GetNext( pos )->m_nSerID;
ar << nDownload;
}
}
else
{
ar >> m_sName;
ar >> m_sSchemaURI;
ar >> m_sFolder;
if ( nVersion >= 3 ) // 版本3以上的版本,直接加入到过滤字符串链表中
{
for ( int nCount = ar.ReadCount() ; nCount > 0 ; nCount-- )
{
CString strFilter;
ar >> strFilter;
m_pFilters.AddTail( strFilter );
}
}
else // 版本3以下的版本
{
CString strFilters;
ar >> strFilters;
for ( strFilters += '|' ; strFilters.GetLength() ; )
{
CString strFilter = strFilters.SpanExcluding( _T(" |") );
strFilters = strFilters.Mid( strFilter.GetLength() + 1 );
strFilter.TrimLeft(); strFilter.TrimRight();
if ( strFilter.GetLength() )
{
m_pFilters.AddTail( strFilter );
}
}
}
//加入各个DownLoad对象,这里需要根据保存的m_nSerID在
//DownLoads数组中找到CDownload指针,然后加入到m_pDownLoads链表
for ( int nCount = ar.ReadCount() ; nCount > 0 ; nCount-- )
{
DWORD nDownload;
ar >> nDownload;
if ( CDownload* pDownload =
Downloads.FindBySID( nDownload ) )
{
Add( pDownload );
}
}
//设置Schma为m_sSchemaURI,这是因为m_nImage需要因为uri的不同
//而设置为不同的值,所以单独的加了个SetSchema方法来完成任务
SetSchema( m_sSchemaURI );
}
}
//
// DownloadGroups.h
//
// Copyright (c) Shareaza Development Team, 2002-2005.
// This file is part of SHAREAZA (www.shareaza.com)
//
// Shareaza is free software; you can redistribute it
// and/or modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Shareaza is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Shareaza; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
#if !defined(AFX_DOWNLOADGROUPS_H__3B37C337_3DD2_4335_BEF1_EA98F348286E__INCLUDED_)
#define AFX_DOWNLOADGROUPS_H__3B37C337_3DD2_4335_BEF1_EA98F348286E__INCLUDED_
#pragma once
class CDownload;
class CDownloadGroup;
/*
super 是一个指向第一个块的名字为all的一个DownloadGroup,
里面还默认加入了诸如video,music等的DownloadGroup;
m_pList保存了一个CDownLoadGroup链表
*/
class CDownloadGroups
{
// Construction
public:
CDownloadGroups();
virtual ~CDownloadGroups();
// Attributes
public:
//为了互斥访问DownloadGroups而设立的互斥变量
CCriticalSection m_pSection;
protected:
CPtrList m_pList;
CDownloadGroup* m_pSuper;
int m_nBaseCookie;
int m_nSaveCookie;
int m_nGroupCookie;
// Operations
public:
CDownloadGroup* GetSuperGroup();
CDownloadGroup* Add(LPCTSTR pszName = NULL);
void Remove(CDownloadGroup* pGroup);
void Link(CDownload* pDownload);
void Unlink(CDownload* pDownload, BOOL bAndSuper = TRUE);
void CreateDefault();
CString GetCompletedPath(CDownload* pDownload);
public:
void Clear();
BOOL Load();
BOOL Save(BOOL bForce = TRUE);
protected:
void Serialize(CArchive& ar);
// Inlines
public:
inline POSITION GetIterator() const
{
return m_pList.GetHeadPosition();
}
inline CDownloadGroup* GetNext(POSITION& pos) const
{
return (CDownloadGroup*)m_pList.GetNext( pos );
}
inline int GetCount() const
{
return m_pList.GetCount();
}
inline BOOL Check(CDownloadGroup* pGroup) const
{
return m_pList.Find( pGroup ) != NULL;
}
inline int GetGroupCookie() const
{
return m_nGroupCookie;
}
inline void IncBaseCookie()
{
m_nBaseCookie ++;
}
friend class CDownloadGroup;
};
extern CDownloadGroups DownloadGroups;
#endif // !defined(AFX_DOWNLOADGROUPS_H__3B37C337_3DD2_4335_BEF1_EA98F348286E__INCLUDED_)
//
// DownloadGroups.cpp
//
// Copyright (c) Shareaza Development Team, 2002-2005.
// This file is part of SHAREAZA (www.shareaza.com)
//
// Shareaza is free software; you can redistribute it
// and/or modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Shareaza is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Shareaza; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
#include "StdAfx.h"
#include "Shareaza.h"
#include "Settings.h"
#include "DownloadGroup.h"
#include "DownloadGroups.h"
#include "Downloads.h"
#include "Download.h"
#include "Schema.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
CDownloadGroups DownloadGroups;
//
// CDownloadGroups construction
CDownloadGroups::CDownloadGroups()
{
m_pSuper = NULL;
m_nBaseCookie = 1;
m_nSaveCookie = 0;
m_nGroupCookie = 0;
}
CDownloadGroups::~CDownloadGroups()
{
Clear();
}
//
// CDownloadGroups supergroup
//返回CDownloadGroup指针m_pSuper,如果为空则加入一个all字符串,然后返回之
CDownloadGroup* CDownloadGroups::GetSuperGroup()
{
CSingleLock pLock( &m_pSection, TRUE );
if ( m_pSuper != NULL )
{
return m_pSuper;
}
return m_pSuper = Add( _T("All") );
}
//
// CDownloadGroups add group
//创建一个新的CDownloadGroup对象,m_sName设置为参数pszName,然后加入到
//m_pList的最后
CDownloadGroup* CDownloadGroups::Add(LPCTSTR pszName)
{
CSingleLock pLock( &m_pSection, TRUE );
CDownloadGroup* pGroup = new CDownloadGroup();
if ( pszName != NULL )
{
pGroup->m_sName = pszName;
}
m_pList.AddTail( pGroup );
m_nBaseCookie ++;
m_nGroupCookie ++;
return pGroup;
}
//
// CDownloadGroups remove group
/*
在m_pList中删除参数指定的CDownloadGroup对象
释放空间,m_nBaseCookie 和m_nGroupCookie不管加入一个
DownloadGroup还是减少一个都++,为什么?
super块不能删除
*/
void CDownloadGroups::Remove(CDownloadGroup* pGroup)
{
CSingleLock pLock( &m_pSection, TRUE );
if ( POSITION pos = m_pList.Find( pGroup ) )
{
if ( pGroup == m_pSuper )
{
return;
}
m_pList.RemoveAt( pos );
delete pGroup;
m_nBaseCookie ++;
m_nGroupCookie ++;
}
}
//
// CDownloadGroups link a download to the appropriate groups
//在m_pList的每一个DownloadGroup中link参数指定的pDownload对象
//首先在superGroup中加入pDownload对象
void CDownloadGroups::Link(CDownload* pDownload)
{
CSingleLock pLock( &m_pSection, TRUE );
GetSuperGroup()->Add( pDownload );
for ( POSITION pos = GetIterator() ; pos ; )
{
CDownloadGroup* pGroup = GetNext( pos );
pGroup->Link( pDownload );
}
}
//
// CDownloadGroups unlink a download from all groups
//从m_pList中的所有的DownloadGroup中删除CDownload类的pDownload对象
void CDownloadGroups::Unlink(CDownload* pDownload, BOOL bAndSuper)
{
CSingleLock pLock( &m_pSection, TRUE );
for ( POSITION pos = GetIterator() ; pos ; )
{
CDownloadGroup* pGroup = GetNext( pos );
if ( bAndSuper || pGroup != m_pSuper )
{
pGroup->Remove( pDownload );
}
}
}
//
// CDownloadGroups default
/*
在m_pList中加入几个默认的CDownLoadGroup对象,
设置这些DownloadGroup对象的Filter和name,schema等
audio,对应的是mp3,wav,ogg,wma,Schema为音乐集合;
video,对应的是asf,avi,mov,mpg,mpeg,ogm,wmv,Schema为uriVideo
Torrent,对应的是torrent,Schema为uriROM
*/
void CDownloadGroups::CreateDefault()
{
CSingleLock pLock( &m_pSection, TRUE );
CDownloadGroup* pGroup = GetSuperGroup();
pGroup = Add( _T("Audio") );
pGroup->AddFilter( _T(".mp3") );
pGroup->AddFilter( _T(".ogg") );
pGroup->AddFilter( _T(".wav") );
pGroup->AddFilter( _T(".wma") );
pGroup->SetSchema( CSchema::uriMusicAlbum );
pGroup = Add( _T("Video") );
pGroup->AddFilter( _T(".asf") );
pGroup->AddFilter( _T(".avi") );
pGroup->AddFilter( _T(".mov") );
pGroup->AddFilter( _T(".mpg") );
pGroup->AddFilter( _T(".mpeg") );
pGroup->AddFilter( _T(".ogm") );
pGroup->AddFilter( _T(".wmv") );
pGroup->SetSchema( CSchema::uriVideo );
pGroup = Add( _T("BitTorrent") );
pGroup->AddFilter( _T("torrent") );
pGroup->SetSchema( CSchema::uriROM );
}
//
// CDownloadGroups completed path
/*
在m_pList中寻找含有pDownload的那个CDownloadGroup,如果
找到了,而且这个CDownloadGroup的m_sFolder不是空,则返回
m_sFolder
*/
CString CDownloadGroups::GetCompletedPath(CDownload* pDownload)
{
CSingleLock pLock( &m_pSection, TRUE );
for ( POSITION pos = GetIterator() ; pos ; )
{
CDownloadGroup* pGroup = GetNext( pos );
if ( pGroup != m_pSuper
&& pGroup->Contains( pDownload ) )
{
if ( pGroup->m_sFolder.GetLength() )
{
return pGroup->m_sFolder;
}
}
}
return Settings.Downloads.CompletePath;
}
//
// CDownloadGroups clear
//删除m_pList中的所有元素,将super设置为NULL
void CDownloadGroups::Clear()
{
CSingleLock pLock( &m_pSection, TRUE );
for ( POSITION pos = GetIterator() ; pos ; )
{
delete GetNext( pos );
}
m_pList.RemoveAll();
m_pSuper = NULL;
m_nBaseCookie ++;
m_nGroupCookie ++;
}
//
// CDownloadGroups load and save
//打开//Data//DownloadGroups.dat文件,装载进CDownloadGroups对象
BOOL CDownloadGroups::Load()
{
CSingleLock pLock( &m_pSection, TRUE );
CFile pFile;
CString strPath = Settings.General.UserPath + _T("//Data//DownloadGroups.dat");
if ( ! pFile.Open( strPath, CFile::modeRead ) )
{
return FALSE;
}
try
{
CArchive ar( &pFile, CArchive::load );
Serialize( ar );
}
catch ( CException* pException )
{
pException->Delete();
return FALSE;
}
m_nSaveCookie = m_nBaseCookie;
return TRUE;
}
//将当前的DownloadGroups对象保存到//Data//DownloadGroups.dat文件中
//为了防止对原来文件的破坏,先写入tmp文件,然后将文件重新命名为strPath
BOOL CDownloadGroups::Save(BOOL bForce)
{
CSingleLock pLock( &m_pSection, TRUE );
if ( ! bForce && m_nBaseCookie == m_nSaveCookie )
{
return FALSE;
}
m_nSaveCookie = m_nBaseCookie;
CString strPath = Settings.General.UserPath + _T("//Data//DownloadGroups.dat");
//首先删除原来的tmp文件
DeleteFile( strPath + _T(".tmp") );
//创建一个strPath。tmp文件
CFile pFile;
if ( ! pFile.Open( strPath + _T(".tmp"),
CFile::modeWrite | CFile::modeCreate ) )
{
return FALSE;
}
//保存到文件pFile中,同时保存4096字节到pBuffer中
BYTE* pBuffer = new BYTE[ 4096 ];//Buffer没有什么用
//主要是为了异常处理而设置的东东
try
{
CArchive ar( &pFile, CArchive::store, 4096, pBuffer );
Serialize( ar );
}
catch ( CException* pException )
{
delete [] pBuffer;
pException->Delete();
return FALSE;
}
delete [] pBuffer;
pFile.Close();
//删除原来的strPath文件
DeleteFile( strPath );
//将strPath.tmp更名为strPath
MoveFile( strPath + _T(".tmp"), strPath );
return TRUE;
}
//
// CDownloadGroups serialize
#define GROUPS_SER_VERSION 3
void CDownloadGroups::Serialize(CArchive& ar)
{
int nVersion = GROUPS_SER_VERSION;
BYTE nState;
if ( ar.IsStoring() )
{
//首先将GROUPS_SER_VERSION保存起来
ar << nVersion;
//将Downloads中的所有CDownloads项的
ar.WriteCount( Downloads.GetCount() );
//将Downloads中的各个CDownload的m_nSerID保存起来
for ( POSITION pos = Downloads.GetIterator() ; pos ; )
{
ar << Downloads.GetNext( pos )->m_nSerID;
}
//将当前的m_pList的数目保存起来
ar.WriteCount( GetCount() );
//将状态和各个DownloadGroup保存好
for ( POSITION pos = GetIterator() ; pos ; )
{
CDownloadGroup* pGroup = GetNext( pos );
nState = ( pGroup == m_pSuper ) ? 1 : 0;
ar << nState;
pGroup->Serialize( ar, nVersion );
}
}
else
{
ar >> nVersion;
if ( nVersion <= 1
|| nVersion > GROUPS_SER_VERSION )
{
AfxThrowUserException(); // Version错误了
}
int nCount = ar.ReadCount();
for ( ; nCount > 0 ; nCount-- )
{
DWORD nDownload;
ar >> nDownload;
//在Downloads中根据编号找到CDownload指针,记录下来
if ( CDownload* pDownload = Downloads.FindBySID( nDownload ) )
{
Downloads.Reorder( pDownload, NULL );
}
}
//首先将原来m_pList的内容清0
if ( nCount = ar.ReadCount() )
{
Clear();
}
//读取各个CDownloadGroup对象到m-pList中
for ( ; nCount > 0 ; nCount-- )
{
CDownloadGroup* pGroup = Add();
ar >> nState;
if ( nState == 1 )
{
m_pSuper = pGroup;
}
pGroup->Serialize( ar, nVersion );
}
//初始化supergroup m_pSuper的内容
GetSuperGroup();
//在m_pSuper中加入Downloads中的各个CDownload对象
for ( POSITION pos = Downloads.GetIterator() ; pos ; )
{
m_pSuper->Add( Downloads.GetNext( pos ) );
}
}
}