📄 ctrllibrarydetailview.cpp
字号:
//
// CtrlLibraryDetailView.cpp
//
// Copyright (c) Shareaza Development Team, 2002-2004.
// 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 "Library.h"
#include "SharedFolder.h"
#include "SharedFile.h"
#include "AlbumFolder.h"
#include "LiveList.h"
#include "XML.h"
#include "SHA.h"
#include "Schema.h"
#include "SchemaCache.h"
#include "CoolInterface.h"
#include "ShellIcons.h"
#include "CoolMenu.h"
#include "Skin.h"
#include "CtrlLibraryFrame.h"
#include "CtrlLibraryDetailView.h"
#include "DlgHitColumns.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
IMPLEMENT_DYNCREATE(CLibraryDetailView, CLibraryFileView)
IMPLEMENT_DYNCREATE(CLibraryListView, CLibraryDetailView)
IMPLEMENT_DYNCREATE(CLibraryIconView, CLibraryDetailView)
BEGIN_MESSAGE_MAP(CLibraryDetailView, CLibraryFileView)
//{{AFX_MSG_MAP(CLibraryDetailView)
ON_WM_CREATE()
ON_WM_DESTROY()
ON_WM_CONTEXTMENU()
ON_WM_MEASUREITEM()
ON_WM_DRAWITEM()
ON_UPDATE_COMMAND_UI(ID_LIBRARY_RENAME, OnUpdateLibraryRename)
ON_COMMAND(ID_LIBRARY_RENAME, OnLibraryRename)
ON_COMMAND(ID_LIBRARY_COLUMNS, OnLibraryColumns)
ON_UPDATE_COMMAND_UI(ID_LIBRARY_COLUMNS, OnUpdateLibraryColumns)
//}}AFX_MSG_MAP
ON_NOTIFY_REFLECT(LVN_ODCACHEHINT, OnCacheHint)
ON_NOTIFY_REFLECT(LVN_GETDISPINFOW, OnGetDispInfoW)
ON_NOTIFY_REFLECT(LVN_GETDISPINFOA, OnGetDispInfoA)
ON_NOTIFY_REFLECT(LVN_COLUMNCLICK, OnColumnClick)
ON_NOTIFY_REFLECT(LVN_BEGINLABELEDITW, OnBeginLabelEdit)
ON_NOTIFY_REFLECT(LVN_BEGINLABELEDITA, OnBeginLabelEdit)
ON_NOTIFY_REFLECT(LVN_ENDLABELEDITW, OnEndLabelEditW)
ON_NOTIFY_REFLECT(LVN_ENDLABELEDITA, OnEndLabelEditA)
ON_NOTIFY_REFLECT(LVN_BEGINDRAG, OnBeginDrag)
ON_NOTIFY_REFLECT(LVN_ITEMCHANGED, OnItemChanged)
ON_NOTIFY_REFLECT(LVN_ODSTATECHANGED, OnItemRangeChanged)
ON_NOTIFY_REFLECT(LVN_ODFINDITEMW, OnFindItemW)
ON_NOTIFY_REFLECT(LVN_ODFINDITEMA, OnFindItemA)
ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, OnCustomDraw)
ON_NOTIFY_REFLECT(NM_DBLCLK, OnDblClk)
ON_UPDATE_COMMAND_UI_RANGE(1000, 1100, OnUpdateBlocker)
END_MESSAGE_MAP()
#define GET_LIST() CListCtrl* pList = (CListCtrl*)this
#define DETAIL_COLUMNS 7
/////////////////////////////////////////////////////////////////////////////
// CLibraryDetailView construction
CLibraryDetailView::CLibraryDetailView(UINT nCommandID)
{
switch ( m_nCommandID = nCommandID )
{
case ID_LIBRARY_VIEW_DETAIL:
m_nStyle = LVS_REPORT;
break;
case ID_LIBRARY_VIEW_LIST:
m_nStyle = LVS_LIST;
break;
case ID_LIBRARY_VIEW_ICON:
m_nStyle = LVS_ICON;
break;
}
m_pCoolMenu = NULL;
m_pSchema = NULL;
}
CLibraryDetailView::~CLibraryDetailView()
{
}
/////////////////////////////////////////////////////////////////////////////
// CLibraryDetailView create and destroy
BOOL CLibraryDetailView::Create(CWnd* pParentWnd)
{
CRect rect( 0, 0, 0, 0 );
SelClear( FALSE );
DWORD nStyle = m_nStyle;
return CWnd::Create( WC_LISTVIEW, _T("CLibraryDetailView"),
WS_CHILD|LVS_ICON|LVS_AUTOARRANGE|LVS_SHOWSELALWAYS|nStyle|
LVS_SHAREIMAGELISTS|LVS_EDITLABELS|LVS_OWNERDATA, rect, pParentWnd, IDC_LIBRARY_VIEW );
}
int CLibraryDetailView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if ( CLibraryFileView::OnCreate( lpCreateStruct ) == -1 ) return -1;
SendMessage( LVM_SETEXTENDEDLISTVIEWSTYLE,
LVS_EX_FULLROWSELECT|LVS_EX_HEADERDRAGDROP,
LVS_EX_FULLROWSELECT|LVS_EX_HEADERDRAGDROP );
GET_LIST();
pList->InsertColumn( 0, _T("File"), LVCFMT_LEFT, 200, -1 );
pList->SetCallbackMask( LVIS_SELECTED );
if ( m_nStyle == LVS_REPORT )
{
pList->InsertColumn( 1, _T("Type"), LVCFMT_CENTER, 40, 0 );
pList->InsertColumn( 2, _T("Size"), LVCFMT_CENTER, 60, 1 );
pList->InsertColumn( 3, _T("Folder"), LVCFMT_LEFT, 0, 2 );
pList->InsertColumn( 4, _T("Hits"), LVCFMT_CENTER, 70, 3 );
pList->InsertColumn( 5, _T("Uploads"), LVCFMT_CENTER, 70, 4 );
pList->InsertColumn( 6, _T("Modified"), LVCFMT_CENTER, 0, 5 );
pList->SetImageList( ShellIcons.GetObject( 16 ), LVSIL_SMALL );
CHeaderCtrl* pHeader = (CHeaderCtrl*)GetWindow( GW_CHILD );
if ( pHeader ) Skin.Translate( _T("CLibraryWnd"), pHeader );
}
else if ( m_nStyle != LVS_ICON )
{
pList->SetImageList( ShellIcons.GetObject( 16 ), LVSIL_SMALL );
}
else
{
pList->SetImageList( ShellIcons.GetObject( 32 ), LVSIL_NORMAL );
}
pList->SetCallbackMask( LVIS_SELECTED );
m_pList = NULL;
m_nList = m_nBuffer = 0;
CString strSchemaURI = Settings.Library.FilterURI.GetLength() ?
Settings.Library.FilterURI : Settings.Library.SchemaURI;
if ( CSchema* pSchema = SchemaCache.Get( strSchemaURI ) )
{
CPtrList pColumns;
CSchemaColumnsDlg::LoadColumns( pSchema, &pColumns );
SetViewSchema( pSchema, &pColumns, FALSE, FALSE );
}
else
{
SetViewSchema( NULL, NULL, FALSE, FALSE );
}
m_bCreateDragImage = FALSE;
return 0;
}
void CLibraryDetailView::OnDestroy()
{
if ( m_pList )
{
for ( DWORD nItem = 0 ; nItem < m_nBuffer ; nItem++ )
{
if ( m_pList[ nItem ].pText ) delete m_pList[ nItem ].pText;
}
delete [] m_pList;
}
m_pList = NULL;
m_nList = m_nBuffer = 0;
if ( m_nStyle == LVS_REPORT )
{
if ( m_pSchema != NULL )
{
Settings.SaveList( _T("CLibraryDetailView.") + m_pSchema->m_sSingular, (CListCtrl*)this );
}
else
{
Settings.SaveList( _T("CLibraryDetailView"), (CListCtrl*)this );
}
}
CLibraryFileView::OnDestroy();
}
/////////////////////////////////////////////////////////////////////////////
// CLibraryDetailView schema setup
void CLibraryDetailView::SetViewSchema(CSchema* pSchema, CPtrList* pColumns, BOOL bSave, BOOL bUpdate)
{
GET_LIST();
pList->DeleteAllItems();
if ( m_nStyle != LVS_REPORT )
{
if ( bUpdate ) PostUpdate();
return;
}
if ( bSave )
{
if ( m_pSchema )
{
Settings.SaveList( _T("CLibraryDetailView.") + m_pSchema->m_sSingular, pList );
}
else
{
Settings.SaveList( _T("CLibraryDetailView"), pList );
}
}
m_pColumns.RemoveAll();
if ( m_pSchema = pSchema ) m_pColumns.AddTail( pColumns );
int nColumn = DETAIL_COLUMNS;
while ( pList->DeleteColumn( nColumn ) );
for ( POSITION pos = m_pColumns.GetHeadPosition() ; pos ; nColumn++ )
{
CSchemaMember* pMember = (CSchemaMember*)m_pColumns.GetNext( pos );
pList->InsertColumn( nColumn, pMember->m_sTitle, pMember->m_nColumnAlign, pMember->m_nColumnWidth, nColumn - 1 );
}
if ( m_pSchema )
Settings.LoadList( _T("CLibraryDetailView.") + m_pSchema->m_sSingular, pList, 1 );
else
Settings.LoadList( _T("CLibraryDetailView"), pList, 1 );
if ( bUpdate ) PostUpdate();
}
/////////////////////////////////////////////////////////////////////////////
// CLibraryDetailView update
void CLibraryDetailView::Update()
{
GET_LIST();
CSchema* pSchema = SchemaCache.Get( Settings.Library.FilterURI );
DWORD nCookie = GetFolderCookie();
if ( Settings.Library.ShowVirtual ) pSchema = NULL;
if ( m_nStyle == LVS_REPORT )
{
CLibraryTreeItem* pTree = GetFolderSelection();
if ( pTree != NULL && pTree->m_pVirtual != NULL && pTree->m_pSelNext == NULL &&
pTree->m_pVirtual->m_pSchema != NULL )
{
CString strURI = pTree->m_pVirtual->m_pSchema->GetContainedURI( CSchema::stFile );
if ( strURI.GetLength() && ( m_pSchema == NULL || m_pSchema->m_sURI != strURI ) )
{
if ( CSchema* pSchema = SchemaCache.Get( strURI ) )
{
CPtrList pColumns;
CSchemaColumnsDlg::LoadColumns( pSchema, &pColumns );
SetViewSchema( pSchema, &pColumns, TRUE, FALSE );
}
}
}
}
LDVITEM* pItem = m_pList + m_nList - 1;
for ( DWORD nCount = m_nList ; nCount ; nCount--, pItem-- )
{
CLibraryFile* pFile = Library.LookupFile( pItem->nIndex );
if ( pFile && pFile->m_nSelectCookie == nCookie && pFile->IsAvailable() &&
( ! pSchema || pSchema->Equals( pFile->m_pSchema ) ||
( ! pFile->m_pMetadata && pSchema->FilterType( pFile->m_sName ) ) ) )
{
pFile->m_nListCookie = nCookie;
}
else
{
SelRemove( pItem->nIndex );
CStringArray* pSaved = pItem->pText;
CopyMemory( pItem, pItem + 1, sizeof(LDVITEM) * ( m_nList - nCount ) );
pItem[ m_nList - nCount ].pText = pSaved;
m_nList--;
}
}
for ( POSITION pos = LibraryMaps.GetFileIterator() ; pos ; )
{
CLibraryFile* pFile = LibraryMaps.GetNextFile( pos );
if ( pFile->m_nSelectCookie == nCookie &&
pFile->m_nListCookie != nCookie &&
pFile->IsAvailable() &&
( ! pSchema || pSchema->Equals( pFile->m_pSchema ) ||
( ! pFile->m_pMetadata && pSchema->FilterType( pFile->m_sName ) ) ) )
{
if ( m_nList == m_nBuffer ) // MUST EQUAL
{
m_nBuffer += 64;
LDVITEM* pList = new LDVITEM[ m_nBuffer ];
if ( m_nList ) CopyMemory( pList, m_pList, m_nList * sizeof(LDVITEM) );
if ( m_pList ) delete [] m_pList;
ZeroMemory( pList + m_nList, ( m_nBuffer - m_nList ) * sizeof(LDVITEM) );
m_pList = pList;
}
m_pList[ m_nList ].nIndex = pFile->m_nIndex;
m_pList[ m_nList ].nState &= ~LDVI_SELECTED;
m_nList++;
pFile->m_nListCookie = nCookie;
}
}
m_nListCookie++;
SortItems();
}
BOOL CLibraryDetailView::Select(DWORD nObject)
{
GET_LIST();
for ( int nDeselect = -1 ; ; )
{
nDeselect = pList->GetNextItem( nDeselect, LVNI_SELECTED );
if ( nDeselect < 0 ) break;
pList->SetItemState( nDeselect, 0, LVIS_SELECTED );
}
LDVITEM* pItem = m_pList;
for ( DWORD nCount = 0 ; nCount < m_nList ; nCount++, pItem++ )
{
if ( pItem->nIndex == nObject )
{
LV_ITEM pItem;
pItem.mask = LVIF_STATE; pItem.state = 0xFFFFFFFF; pItem.stateMask = LVIS_SELECTED|LVIS_FOCUSED;
SendMessage( LVM_SETITEMSTATE, nCount, (LPARAM)&pItem );
PostMessage( LVM_ENSUREVISIBLE, nCount, FALSE );
return TRUE;
}
}
return FALSE;
}
void CLibraryDetailView::CacheItem(int nItem)
{
CLibraryFile* pFile = Library.LookupFile( m_pList[ nItem ].nIndex );
if ( ! pFile ) return;
LDVITEM* pItem = &m_pList[ nItem ];
pItem->nCookie = m_nListCookie;
if ( pItem->pText == NULL ) pItem->pText = new CStringArray();
CStringArray* pText = pItem->pText;
pText->SetSize( m_nStyle == LVS_REPORT ? DETAIL_COLUMNS + m_pColumns.GetCount() : 1 );
CString strName( pFile->m_sName );
int nDot = strName.ReverseFind( '.' );
if ( nDot >= 0 ) strName.SetAt( nDot, 0 );
pText->SetAt( 0, strName );
if ( m_nStyle == LVS_ICON )
{
pItem->nIcon = ShellIcons.Get( pFile->m_sName, 32 );
}
else
{
if ( pFile->m_nIcon16 >= 0 )
pItem->nIcon = pFile->m_nIcon16;
else
pItem->nIcon = pFile->m_nIcon16 = ShellIcons.Get( pFile->m_sName, 16 );
}
pItem->nState &= LDVI_SELECTED;
if ( ! pFile->IsShared() ) pItem->nState |= LDVI_PRIVATE;
if ( ! pFile->m_bSHA1 ) pItem->nState |= LDVI_UNSCANNED;
if ( pFile->m_bVerify == TS_FALSE ) pItem->nState |= LDVI_UNSAFE;
if ( m_nStyle != LVS_REPORT ) return;
if ( LPCTSTR pszType = _tcsrchr( pFile->m_sName, '.' ) )
pText->SetAt( 1, pszType + 1 );
else
pText->SetAt( 1, _T("") );
pText->SetAt( 2, Settings.SmartVolume( pFile->GetSize(), FALSE ) );
if ( pFile->m_pFolder != NULL ) pText->SetAt( 3, pFile->m_pFolder->m_sPath );
CString str;
str.Format( _T("%lu (%lu)"), pFile->m_nHitsToday, pFile->m_nHitsTotal );
pText->SetAt( 4, str );
str.Format( _T("%lu (%lu)"), pFile->m_nUploadsToday, pFile->m_nUploadsTotal );
pText->SetAt( 5, str );
TCHAR szModified[ 64 ];
SYSTEMTIME pTime;
FileTimeToSystemTime( &pFile->m_pTime, &pTime );
SystemTimeToTzSpecificLocalTime( NULL, &pTime, &pTime );
GetDateFormat( LOCALE_USER_DEFAULT, 0, &pTime, _T("yyyy-MM-dd"), szModified, 64 );
_tcscat( szModified, _T(" ") );
GetTimeFormat( LOCALE_USER_DEFAULT, 0, &pTime, _T("hh:mm tt"), szModified + _tcslen( szModified ), 64 - _tcslen( szModified ) );
pText->SetAt( 6, szModified );
if ( m_pSchema == NULL ) return;
int nColumn = DETAIL_COLUMNS;
BOOL bSource = pFile->m_pMetadata && m_pSchema->Equals( pFile->m_pSchema ) &&
m_pSchema->m_sSingular.CompareNoCase( pFile->m_pMetadata->GetName() ) == 0;
for ( POSITION pos = m_pColumns.GetHeadPosition() ; pos ; nColumn++ )
{
CSchemaMember* pMember = (CSchemaMember*)m_pColumns.GetNext( pos );
if ( pMember->m_sName.CompareNoCase( _T("SHA1") ) == 0 )
{
if ( pFile->m_bSHA1 )
{
pText->SetAt( nColumn, CSHA::HashToString( &pFile->m_pSHA1 ) );
}
else pText->SetAt( nColumn, _T("") );
}
else if ( bSource )
{
pText->SetAt( nColumn, pMember->GetValueFrom( pFile->m_pMetadata, NULL, TRUE ) );
}
else
{
pText->SetAt( nColumn, _T("") );
}
}
}
void CLibraryDetailView::OnCacheHint(NMLVCACHEHINT* pNotify, LRESULT* pResult)
{
if ( ! Library.Lock( 100 ) ) return;
for ( int nItem = pNotify->iFrom ; nItem <= pNotify->iTo ; nItem++ )
{
CacheItem( nItem );
}
Library.Unlock();
}
void CLibraryDetailView::OnGetDispInfoW(NMLVDISPINFO* pNotify, LRESULT* pResult)
{
*pResult = 0;
LDVITEM* pItem = &m_pList[ pNotify->item.iItem ];
if ( pNotify->item.mask & LVIF_STATE )
{
pNotify->item.state &= ~LVIS_SELECTED;
if ( pItem->nState & LDVI_SELECTED ) pNotify->item.state |= LVIS_SELECTED;
}
if ( pItem->nCookie != m_nListCookie )
{
if ( ! Library.Lock( 100 ) ) return;
CacheItem( pNotify->item.iItem );
Library.Unlock();
if ( pItem->nCookie != m_nListCookie ) return;
}
if ( pNotify->item.mask & LVIF_TEXT )
{
if ( pNotify->item.iSubItem < pItem->pText->GetSize() )
{
wcsncpy( (LPWSTR)pNotify->item.pszText, pItem->pText->GetAt( pNotify->item.iSubItem ), pNotify->item.cchTextMax );
}
}
if ( pNotify->item.mask & LVIF_IMAGE )
{
pNotify->item.iImage = pItem->nIcon;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -