📄 filedetaildialog.cpp
字号:
//this file is part of eMule
//Copyright (C)2002 Merkur ( devs@emule-project.net / http://www.emule-project.net )
//
//This program 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.
//
//This program 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 this program; if not, write to the Free Software
//Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#include "stdafx.h"
#include "emule.h"
#include "OtherFunctions.h"
#include "FileInfoDialog.h"
#include "FileDetailDialog.h"
#include "Preferences.h"
#include "UpDownClient.h"
#include "TitleMenu.h"
#include "MenuCmds.h"
#include "PartFile.h"
#include "StringConversion.h"
#include "shahashset.h"
#include "HighColorTab.hpp"
#include "UserMsgs.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
///////////////////////////////////////////////////////////////////////////////
// CFileDetailDialog
LPCTSTR CFileDetailDialog::m_pPshStartPage;
IMPLEMENT_DYNAMIC(CFileDetailDialog, CListViewWalkerPropertySheet)
BEGIN_MESSAGE_MAP(CFileDetailDialog, CListViewWalkerPropertySheet)
ON_WM_DESTROY()
ON_MESSAGE(UM_DATA_CHANGED, OnDataChanged)
END_MESSAGE_MAP()
CFileDetailDialog::CFileDetailDialog(const CSimpleArray<CPartFile*>* paFiles, UINT uPshInvokePage, CListCtrlItemWalk* pListCtrl)
: CListViewWalkerPropertySheet(pListCtrl)
{
m_uPshInvokePage = uPshInvokePage;
for (int i = 0; i < paFiles->GetSize(); i++)
m_aItems.Add((*paFiles)[i]);
m_psh.dwFlags &= ~PSH_HASHELP;
m_wndInfo.m_psp.dwFlags &= ~PSP_HASHELP;
m_wndInfo.m_psp.dwFlags |= PSP_USEICONID;
m_wndInfo.m_psp.pszIcon = _T("FILEINFO");
m_wndInfo.SetFiles(&m_aItems);
AddPage(&m_wndInfo);
if (paFiles->GetSize() == 1)
{
m_wndName.m_psp.dwFlags &= ~PSP_HASHELP;
m_wndName.m_psp.dwFlags |= PSP_USEICONID;
m_wndName.m_psp.pszIcon = _T("FILERENAME");
m_wndName.SetFiles(&m_aItems);
AddPage(&m_wndName);
m_wndComments.m_psp.dwFlags &= ~PSP_HASHELP;
m_wndComments.m_psp.dwFlags |= PSP_USEICONID;
m_wndComments.m_psp.pszIcon = _T("FILECOMMENTS");
m_wndComments.SetFiles(&m_aItems);
AddPage(&m_wndComments);
}
m_wndMediaInfo.m_psp.dwFlags &= ~PSP_HASHELP;
m_wndMediaInfo.m_psp.dwFlags |= PSP_USEICONID;
m_wndMediaInfo.m_psp.pszIcon = _T("MEDIAINFO");
m_wndMediaInfo.SetFiles(&m_aItems);
AddPage(&m_wndMediaInfo);
if (paFiles->GetSize() == 1)
{
if (thePrefs.IsExtControlsEnabled()){
m_wndMetaData.m_psp.dwFlags &= ~PSP_HASHELP;
m_wndMetaData.m_psp.dwFlags |= PSP_USEICONID;
m_wndMetaData.m_psp.pszIcon = _T("METADATA");
m_wndMetaData.SetFiles(&m_aItems);
AddPage(&m_wndMetaData);
}
}
m_wndFileLink.m_psp.dwFlags &= ~PSP_HASHELP;
m_wndFileLink.m_psp.dwFlags |= PSP_USEICONID;
m_wndFileLink.m_psp.pszIcon = _T("ED2KLINK");
m_wndFileLink.SetFiles(&m_aItems);
AddPage(&m_wndFileLink);
LPCTSTR pPshStartPage = m_pPshStartPage;
if (m_uPshInvokePage != 0)
pPshStartPage = MAKEINTRESOURCE(m_uPshInvokePage);
for (int i = 0; i < m_pages.GetSize(); i++)
{
CPropertyPage* pPage = GetPage(i);
if (pPage->m_psp.pszTemplate == pPshStartPage)
{
m_psh.nStartPage = i;
break;
}
}
}
CFileDetailDialog::~CFileDetailDialog()
{
}
void CFileDetailDialog::OnDestroy()
{
if (m_uPshInvokePage == 0)
m_pPshStartPage = GetPage(GetActiveIndex())->m_psp.pszTemplate;
CListViewWalkerPropertySheet::OnDestroy();
}
BOOL CFileDetailDialog::OnInitDialog()
{
EnableStackedTabs(FALSE);
BOOL bResult = CListViewWalkerPropertySheet::OnInitDialog();
HighColorTab::UpdateImageList(*this);
InitWindowStyles(this);
EnableSaveRestore(_T("FileDetailDialog")); // call this after(!) OnInitDialog
UpdateTitle();
return bResult;
}
LRESULT CFileDetailDialog::OnDataChanged(WPARAM, LPARAM)
{
UpdateTitle();
return 1;
}
void CFileDetailDialog::UpdateTitle()
{
if (m_aItems.GetSize() == 1)
SetWindowText(GetResString(IDS_DETAILS) + _T(": ") + STATIC_DOWNCAST(CKnownFile, m_aItems[0])->GetFileName());
else
SetWindowText(GetResString(IDS_DETAILS));
}
///////////////////////////////////////////////////////////////////////////////
// CFileDetailDialogInfo dialog
LPCTSTR CFileDetailDialogInfo::sm_pszNotAvail = _T("-");
IMPLEMENT_DYNAMIC(CFileDetailDialogInfo, CResizablePage)
BEGIN_MESSAGE_MAP(CFileDetailDialogInfo, CResizablePage)
ON_WM_TIMER()
ON_WM_DESTROY()
ON_MESSAGE(UM_DATA_CHANGED, OnDataChanged)
END_MESSAGE_MAP()
CFileDetailDialogInfo::CFileDetailDialogInfo()
: CResizablePage(CFileDetailDialogInfo::IDD, 0)
{
m_paFiles = NULL;
m_bDataChanged = false;
m_strCaption = GetResString(IDS_FILEINFORMATION);
m_psp.pszTitle = m_strCaption;
m_psp.dwFlags |= PSP_USETITLE;
m_timer = 0;
}
CFileDetailDialogInfo::~CFileDetailDialogInfo()
{
}
void CFileDetailDialogInfo::OnTimer(UINT nIDEvent)
{
RefreshData();
}
void CFileDetailDialogInfo::DoDataExchange(CDataExchange* pDX)
{
CResizablePage::DoDataExchange(pDX);
}
BOOL CFileDetailDialogInfo::OnInitDialog()
{
CResizablePage::OnInitDialog();
InitWindowStyles(this);
AddAnchor(IDC_FD_X0, TOP_LEFT, TOP_RIGHT);
AddAnchor(IDC_FD_X6, TOP_LEFT, TOP_RIGHT);
AddAnchor(IDC_FD_X8, TOP_LEFT, TOP_RIGHT);
AddAnchor(IDC_FNAME, TOP_LEFT, TOP_RIGHT);
AddAnchor(IDC_METFILE, TOP_LEFT, TOP_RIGHT);
AddAnchor(IDC_FHASH, TOP_LEFT, TOP_RIGHT);
AddAnchor(IDC_FSIZE, TOP_LEFT, TOP_RIGHT);
AddAnchor(IDC_FD_AICHHASH, TOP_LEFT, TOP_RIGHT);
AddAnchor(IDC_PARTCOUNT, TOP_LEFT, TOP_RIGHT);
AddAnchor(IDC_HASHSET, TOP_LEFT, TOP_RIGHT);
AddAnchor(IDC_COMPLSIZE, TOP_LEFT, TOP_RIGHT);
AddAnchor(IDC_DATARATE, TOP_LEFT, TOP_RIGHT);
AddAnchor(IDC_SOURCECOUNT, TOP_LEFT, TOP_RIGHT);
AddAnchor(IDC_RECOVERED, TOP_LEFT, TOP_RIGHT);
AddAnchor(IDC_FILECREATED, TOP_LEFT, TOP_RIGHT);
AddAnchor(IDC_DL_ACTIVE_TIME, TOP_LEFT, TOP_RIGHT);
AddAnchor(IDC_LASTSEENCOMPL, TOP_LEFT, TOP_RIGHT);
AddAnchor(IDC_LASTRECEIVED, TOP_LEFT, TOP_RIGHT);
Localize();
// no need to explicitly call 'RefreshData' here, 'OnSetActive' will be called right after 'OnInitDialog'
;
// start time for calling 'RefreshData'
VERIFY( (m_timer = SetTimer(301, 5000, 0)) != NULL );
return TRUE;
}
BOOL CFileDetailDialogInfo::OnSetActive()
{
if (!CResizablePage::OnSetActive())
return FALSE;
if (m_bDataChanged)
{
RefreshData();
m_bDataChanged = false;
}
return TRUE;
}
LRESULT CFileDetailDialogInfo::OnDataChanged(WPARAM, LPARAM)
{
m_bDataChanged = true;
return 1;
}
void CFileDetailDialogInfo::RefreshData()
{
CString str;
if (m_paFiles->GetSize() == 1)
{
const CPartFile* file = STATIC_DOWNCAST(CPartFile, (*m_paFiles)[0]);
// if file is completed, we output the 'file path' and not the 'part.met file path'
if (file->GetStatus(true) == PS_COMPLETE)
GetDlgItem(IDC_FD_X2)->SetWindowText(GetResString(IDS_DL_FILENAME));
SetDlgItemText(IDC_FNAME, file->GetFileName());
SetDlgItemText(IDC_METFILE, file->GetFullName());
SetDlgItemText(IDC_FHASH, md4str(file->GetFileHash()));
if (file->GetTransferringSrcCount() > 0)
str.Format(GetResString(IDS_PARTINFOS2), file->GetTransferringSrcCount());
else
str = file->getPartfileStatus();
SetDlgItemText(IDC_PFSTATUS, str);
str.Format(_T("%u; %s: %u (%.1f%%)"), file->GetPartCount(), GetResString(IDS_AVAILABLE) , file->GetAvailablePartCount(), (float)((file->GetAvailablePartCount()*100)/file->GetPartCount()));
SetDlgItemText(IDC_PARTCOUNT, str);
// date created
if (file->GetCrFileDate() != 0){
str.Format(_T("%s ") + GetResString(IDS_TIMEBEFORE),
file->GetCrCFileDate().Format(thePrefs.GetDateTimeFormat()),
CastSecondsToLngHM(time(NULL) - file->GetCrFileDate()));
}
else
str = GetResString(IDS_UNKNOWN);
SetDlgItemText(IDC_FILECREATED, str);
// active download time
uint32 nDlActiveTime = file->GetDlActiveTime();
if (nDlActiveTime)
str = CastSecondsToLngHM(nDlActiveTime);
else
str = GetResString(IDS_UNKNOWN);
SetDlgItemText(IDC_DL_ACTIVE_TIME, str);
// last seen complete
struct tm* ptimLastSeenComplete = file->lastseencomplete.GetLocalTm();
if (file->lastseencomplete == NULL || ptimLastSeenComplete == NULL)
str.Format(GetResString(IDS_NEVER));
else{
str.Format(_T("%s ") + GetResString(IDS_TIMEBEFORE),
file->lastseencomplete.Format(thePrefs.GetDateTimeFormat()),
CastSecondsToLngHM(time(NULL) - safe_mktime(ptimLastSeenComplete)));
}
SetDlgItemText(IDC_LASTSEENCOMPL, str);
// last receive
if (file->GetFileDate() != 0 && file->GetRealFileSize() > 0)
{
// 'Last Modified' sometimes is up to 2 seconds greater than the current time ???
// If it's related to the FAT32 seconds time resolution the max. failure should still be only 1 sec.
// Happens at least on FAT32 with very high download speed.
uint32 tLastModified = file->GetFileDate();
uint32 tNow = time(NULL);
uint32 tAgo;
if (tNow >= tLastModified)
tAgo = tNow - tLastModified;
else{
TRACE("tNow = %s\n", CTime(tNow).Format("%X"));
TRACE("tLMd = %s, +%u\n", CTime(tLastModified).Format("%X"), tLastModified - tNow);
TRACE("\n");
tAgo = 0;
}
str.Format(_T("%s ") + GetResString(IDS_TIMEBEFORE),
file->GetCFileDate().Format(thePrefs.GetDateTimeFormat()),
CastSecondsToLngHM(tAgo));
}
else
str = GetResString(IDS_NEVER);
SetDlgItemText(IDC_LASTRECEIVED, str);
// AICH Hash
switch(file->GetAICHHashset()->GetStatus()){
case AICH_TRUSTED:
case AICH_VERIFIED:
case AICH_HASHSETCOMPLETE:
if (file->GetAICHHashset()->HasValidMasterHash()){
SetDlgItemText(IDC_FD_AICHHASH, file->GetAICHHashset()->GetMasterHash().GetString());
break;
}
default:
SetDlgItemText(IDC_FD_AICHHASH, GetResString(IDS_UNKNOWN));
}
}
else
{
SetDlgItemText(IDC_FNAME, sm_pszNotAvail);
SetDlgItemText(IDC_METFILE, sm_pszNotAvail);
SetDlgItemText(IDC_FHASH, sm_pszNotAvail);
SetDlgItemText(IDC_PFSTATUS, sm_pszNotAvail);
SetDlgItemText(IDC_PARTCOUNT, sm_pszNotAvail);
SetDlgItemText(IDC_FILECREATED, sm_pszNotAvail);
SetDlgItemText(IDC_DL_ACTIVE_TIME, sm_pszNotAvail);
SetDlgItemText(IDC_LASTSEENCOMPL, sm_pszNotAvail);
SetDlgItemText(IDC_LASTRECEIVED, sm_pszNotAvail);
SetDlgItemText(IDC_FD_AICHHASH, sm_pszNotAvail);
}
uint64 uFileSize = 0;
uint64 uRealFileSize = 0;
uint64 uTransferred = 0;
uint64 uCorrupted = 0;
uint64 uRecovered = 0;
uint64 uCompression = 0;
uint64 uCompleted = 0;
int iHashsetAvailable = 0;
uint32 uDataRate = 0;
UINT uSources = 0;
UINT uValidSources = 0;
UINT uNNPSources = 0;
UINT uA4AFSources = 0;
for (int i = 0; i < m_paFiles->GetSize(); i++)
{
const CPartFile* file = STATIC_DOWNCAST(CPartFile, (*m_paFiles)[i]);
uFileSize += file->GetFileSize();
uRealFileSize += file->GetRealFileSize();
uTransferred += file->GetTransferred();
uCorrupted += file->GetCorruptionLoss();
uRecovered += file->GetRecoveredPartsByICH();
uCompression += file->GetCompressionGain();
uDataRate += file->GetDatarate();
uCompleted += file->GetCompletedSize();
iHashsetAvailable += (file->GetHashCount() == file->GetED2KPartHashCount()) ? 1 : 0;
if (file->IsPartFile())
{
uSources += file->GetSourceCount();
uValidSources += file->GetValidSourcesCount();
uNNPSources += file->GetSrcStatisticsValue(DS_NONEEDEDPARTS);
uA4AFSources += file->GetSrcA4AFCount();
}
}
if (iHashsetAvailable == 0)
SetDlgItemText(IDC_HASHSET, GetResString(IDS_NO));
else if (iHashsetAvailable == m_paFiles->GetSize())
SetDlgItemText(IDC_HASHSET, GetResString(IDS_YES));
else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -