00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "StdAfx.h"
00023 #include "Shareaza.h"
00024 #include "Settings.h"
00025 #include "Library.h"
00026 #include "SharedFolder.h"
00027 #include "SharedFile.h"
00028 #include "AlbumFolder.h"
00029 #include "LiveList.h"
00030 #include "XML.h"
00031 #include "SHA.h"
00032 #include "Schema.h"
00033 #include "SchemaCache.h"
00034
00035 #include "CoolInterface.h"
00036 #include "ShellIcons.h"
00037 #include "CoolMenu.h"
00038 #include "Skin.h"
00039 #include "CtrlLibraryFrame.h"
00040 #include "CtrlLibraryDetailView.h"
00041 #include "DlgHitColumns.h"
00042
00043 #ifdef _DEBUG
00044 #define new DEBUG_NEW
00045 #undef THIS_FILE
00046 static char THIS_FILE[] = __FILE__;
00047 #endif
00048
00049 IMPLEMENT_DYNCREATE(CLibraryDetailView, CLibraryFileView)
00050 IMPLEMENT_DYNCREATE(CLibraryListView, CLibraryDetailView)
00051 IMPLEMENT_DYNCREATE(CLibraryIconView, CLibraryDetailView)
00052
00053 BEGIN_MESSAGE_MAP(CLibraryDetailView, CLibraryFileView)
00054
00055 ON_WM_CREATE()
00056 ON_WM_DESTROY()
00057 ON_WM_CONTEXTMENU()
00058 ON_WM_MEASUREITEM()
00059 ON_WM_DRAWITEM()
00060 ON_UPDATE_COMMAND_UI(ID_LIBRARY_RENAME, OnUpdateLibraryRename)
00061 ON_COMMAND(ID_LIBRARY_RENAME, OnLibraryRename)
00062 ON_COMMAND(ID_LIBRARY_COLUMNS, OnLibraryColumns)
00063 ON_UPDATE_COMMAND_UI(ID_LIBRARY_COLUMNS, OnUpdateLibraryColumns)
00064
00065 ON_NOTIFY_REFLECT(LVN_ODCACHEHINT, OnCacheHint)
00066 ON_NOTIFY_REFLECT(LVN_GETDISPINFOW, OnGetDispInfoW)
00067 ON_NOTIFY_REFLECT(LVN_GETDISPINFOA, OnGetDispInfoA)
00068 ON_NOTIFY_REFLECT(LVN_COLUMNCLICK, OnColumnClick)
00069 ON_NOTIFY_REFLECT(LVN_BEGINLABELEDITW, OnBeginLabelEdit)
00070 ON_NOTIFY_REFLECT(LVN_BEGINLABELEDITA, OnBeginLabelEdit)
00071 ON_NOTIFY_REFLECT(LVN_ENDLABELEDITW, OnEndLabelEditW)
00072 ON_NOTIFY_REFLECT(LVN_ENDLABELEDITA, OnEndLabelEditA)
00073 ON_NOTIFY_REFLECT(LVN_BEGINDRAG, OnBeginDrag)
00074 ON_NOTIFY_REFLECT(LVN_ITEMCHANGED, OnItemChanged)
00075 ON_NOTIFY_REFLECT(LVN_ODSTATECHANGED, OnItemRangeChanged)
00076 ON_NOTIFY_REFLECT(LVN_ODFINDITEMW, OnFindItemW)
00077 ON_NOTIFY_REFLECT(LVN_ODFINDITEMA, OnFindItemA)
00078 ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, OnCustomDraw)
00079 ON_NOTIFY_REFLECT(NM_DBLCLK, OnDblClk)
00080 ON_UPDATE_COMMAND_UI_RANGE(1000, 1100, OnUpdateBlocker)
00081 END_MESSAGE_MAP()
00082
00083 #define GET_LIST() CListCtrl* pList = (CListCtrl*)this
00084 #define DETAIL_COLUMNS 7
00085
00086
00088
00089
00090 CLibraryDetailView::CLibraryDetailView(UINT nCommandID)
00091 {
00092 switch ( m_nCommandID = nCommandID )
00093 {
00094 case ID_LIBRARY_VIEW_DETAIL:
00095 m_nStyle = LVS_REPORT;
00096 break;
00097 case ID_LIBRARY_VIEW_LIST:
00098 m_nStyle = LVS_LIST;
00099 break;
00100 case ID_LIBRARY_VIEW_ICON:
00101 m_nStyle = LVS_ICON;
00102 break;
00103 }
00104
00105 m_pCoolMenu = NULL;
00106 m_pSchema = NULL;
00107 }
00108
00109 CLibraryDetailView::~CLibraryDetailView()
00110 {
00111 }
00112
00114
00115
00116 BOOL CLibraryDetailView::Create(CWnd* pParentWnd)
00117 {
00118 CRect rect( 0, 0, 0, 0 );
00119 SelClear( FALSE );
00120 DWORD nStyle = m_nStyle;
00121 DWORD dwStyle = theApp.m_bRTL ? WS_EX_RTLREADING : 0;
00122
00123 return CWnd::CreateEx( dwStyle, WC_LISTVIEW, _T("CLibraryDetailView"),
00124 WS_CHILD|LVS_ICON|LVS_AUTOARRANGE|LVS_SHOWSELALWAYS|nStyle|
00125 LVS_SHAREIMAGELISTS|LVS_EDITLABELS|LVS_OWNERDATA, rect, pParentWnd, IDC_LIBRARY_VIEW );
00126 }
00127
00128 int CLibraryDetailView::OnCreate(LPCREATESTRUCT lpCreateStruct)
00129 {
00130 if ( CLibraryFileView::OnCreate( lpCreateStruct ) == -1 ) return -1;
00131
00132 SendMessage( LVM_SETEXTENDEDLISTVIEWSTYLE,
00133 LVS_EX_FULLROWSELECT|LVS_EX_HEADERDRAGDROP,
00134 LVS_EX_FULLROWSELECT|LVS_EX_HEADERDRAGDROP );
00135
00136 GET_LIST();
00137
00138 pList->InsertColumn( 0, _T("File"), LVCFMT_LEFT, 200, -1 );
00139 pList->SetCallbackMask( LVIS_SELECTED );
00140
00141 if ( m_nStyle == LVS_REPORT )
00142 {
00143 pList->InsertColumn( 1, _T("Extension"), LVCFMT_CENTER, 40, 0 );
00144 pList->InsertColumn( 2, _T("Size"), LVCFMT_CENTER, 60, 1 );
00145 pList->InsertColumn( 3, _T("Folder"), LVCFMT_LEFT, 0, 2 );
00146 pList->InsertColumn( 4, _T("Hits"), LVCFMT_CENTER, 70, 3 );
00147 pList->InsertColumn( 5, _T("Uploads"), LVCFMT_CENTER, 70, 4 );
00148 pList->InsertColumn( 6, _T("Modified"), LVCFMT_CENTER, 0, 5 );
00149 pList->SetImageList( ShellIcons.GetObject( 16 ), LVSIL_SMALL );
00150
00151 CHeaderCtrl* pHeader = (CHeaderCtrl*)GetWindow( GW_CHILD );
00152 if ( pHeader ) Skin.Translate( _T("CLibraryWnd"), pHeader );
00153 }
00154 else if ( m_nStyle != LVS_ICON )
00155 {
00156 pList->SetImageList( ShellIcons.GetObject( 16 ), LVSIL_SMALL );
00157 }
00158 else
00159 {
00160 pList->SetImageList( ShellIcons.GetObject( 32 ), LVSIL_NORMAL );
00161 }
00162
00163 pList->SetCallbackMask( LVIS_SELECTED );
00164
00165 m_pList = NULL;
00166 m_nList = m_nBuffer = 0;
00167
00168 CString strSchemaURI = Settings.Library.FilterURI.GetLength() ?
00169 Settings.Library.FilterURI : Settings.Library.SchemaURI;
00170
00171 if ( CSchema* pSchema = SchemaCache.Get( strSchemaURI ) )
00172 {
00173 CPtrList pColumns;
00174 CSchemaColumnsDlg::LoadColumns( pSchema, &pColumns );
00175 SetViewSchema( pSchema, &pColumns, FALSE, FALSE );
00176 }
00177 else
00178 {
00179 SetViewSchema( NULL, NULL, FALSE, FALSE );
00180 }
00181
00182 m_bCreateDragImage = FALSE;
00183
00184 return 0;
00185 }
00186
00187 void CLibraryDetailView::OnDestroy()
00188 {
00189 if ( m_pList )
00190 {
00191 for ( DWORD nItem = 0 ; nItem < m_nBuffer ; nItem++ )
00192 {
00193 if ( m_pList[ nItem ].pText ) delete m_pList[ nItem ].pText;
00194 }
00195
00196 delete [] m_pList;
00197 }
00198
00199 m_pList = NULL;
00200 m_nList = m_nBuffer = 0;
00201
00202 if ( m_nStyle == LVS_REPORT )
00203 {
00204 if ( m_pSchema != NULL )
00205 {
00206 Settings.SaveList( _T("CLibraryDetailView.") + m_pSchema->m_sSingular, (CListCtrl*)this );
00207 }
00208 else
00209 {
00210 Settings.SaveList( _T("CLibraryDetailView"), (CListCtrl*)this );
00211 }
00212 }
00213
00214 CLibraryFileView::OnDestroy();
00215 }
00216
00218
00219
00220 void CLibraryDetailView::SetViewSchema(CSchema* pSchema, CPtrList* pColumns, BOOL bSave, BOOL bUpdate)
00221 {
00222 GET_LIST();
00223
00224 pList->DeleteAllItems();
00225
00226 if ( m_nStyle != LVS_REPORT )
00227 {
00228 if ( bUpdate ) PostUpdate();
00229 return;
00230 }
00231
00232 if ( bSave )
00233 {
00234 if ( m_pSchema )
00235 {
00236 Settings.SaveList( _T("CLibraryDetailView.") + m_pSchema->m_sSingular, pList );
00237 }
00238 else
00239 {
00240 Settings.SaveList( _T("CLibraryDetailView"), pList );
00241 }
00242 }
00243
00244 m_pColumns.RemoveAll();
00245 if ( m_pSchema = pSchema ) m_pColumns.AddTail( pColumns );
00246
00247 int nColumn = DETAIL_COLUMNS;
00248 while ( pList->DeleteColumn( nColumn ) );
00249
00250 for ( POSITION pos = m_pColumns.GetHeadPosition() ; pos ; nColumn++ )
00251 {
00252 CSchemaMember* pMember = (CSchemaMember*)m_pColumns.GetNext( pos );
00253 pList->InsertColumn( nColumn, pMember->m_sTitle, pMember->m_nColumnAlign, pMember->m_nColumnWidth, nColumn - 1 );
00254 }
00255
00256 if ( m_pSchema )
00257 Settings.LoadList( _T("CLibraryDetailView.") + m_pSchema->m_sSingular, pList, 1 );
00258 else
00259 Settings.LoadList( _T("CLibraryDetailView"), pList, 1 );
00260
00261 if ( bUpdate ) PostUpdate();
00262 }
00263
00265
00266
00267 void CLibraryDetailView::Update()
00268 {
00269 GET_LIST();
00270
00271 CSchema* pSchema = SchemaCache.Get( Settings.Library.FilterURI );
00272 DWORD nCookie = GetFolderCookie();
00273
00274 if ( Settings.Library.ShowVirtual ) pSchema = NULL;
00275
00276 if ( m_nStyle == LVS_REPORT )
00277 {
00278 CLibraryTreeItem* pTree = GetFolderSelection();
00279
00280 if ( pTree != NULL && pTree->m_pVirtual != NULL && pTree->m_pSelNext == NULL &&
00281 pTree->m_pVirtual->m_pSchema != NULL )
00282 {
00283 CString strURI = pTree->m_pVirtual->m_pSchema->GetContainedURI( CSchema::stFile );
00284
00285 if ( strURI.GetLength() && ( m_pSchema == NULL || m_pSchema->m_sURI != strURI ) )
00286 {
00287 if ( CSchema* pSchema = SchemaCache.Get( strURI ) )
00288 {
00289 CPtrList pColumns;
00290 CSchemaColumnsDlg::LoadColumns( pSchema, &pColumns );
00291 SetViewSchema( pSchema, &pColumns, TRUE, FALSE );
00292 }
00293 }
00294 }
00295 }
00296
00297 LDVITEM* pItem = m_pList + m_nList - 1;
00298
00299 for ( DWORD nCount = m_nList ; nCount ; nCount--, pItem-- )
00300 {
00301 CLibraryFile* pFile = Library.LookupFile( pItem->nIndex );
00302
00303 if ( pFile && pFile->m_nSelectCookie == nCookie && pFile->IsAvailable() &&
00304 ( ! pSchema || pSchema->Equals( pFile->m_pSchema ) ||
00305 ( ! pFile->m_pMetadata && pSchema->FilterType( pFile->m_sName ) ) ) )
00306 {
00307 pFile->m_nListCookie = nCookie;
00308 }
00309 else
00310 {
00311 SelRemove( pItem->nIndex );
00312 CStringArray* pSaved = pItem->pText;
00313 CopyMemory( pItem, pItem + 1, sizeof(LDVITEM) * ( m_nList - nCount ) );
00314 pItem[ m_nList - nCount ].pText = pSaved;
00315 m_nList--;
00316 }
00317 }
00318
00319 for ( POSITION pos = LibraryMaps.GetFileIterator() ; pos ; )
00320 {
00321 CLibraryFile* pFile = LibraryMaps.GetNextFile( pos );
00322
00323 if ( pFile->m_nSelectCookie == nCookie &&
00324 pFile->m_nListCookie != nCookie &&
00325 pFile->IsAvailable() &&
00326 ( ! pSchema || pSchema->Equals( pFile->m_pSchema ) ||
00327 ( ! pFile->m_pMetadata && pSchema->FilterType( pFile->m_sName ) ) ) )
00328 {
00329 if ( m_nList == m_nBuffer )
00330 {
00331 m_nBuffer += 64;
00332 LDVITEM* pList = new LDVITEM[ m_nBuffer ];
00333 if ( m_nList ) CopyMemory( pList, m_pList, m_nList * sizeof(LDVITEM) );
00334 if ( m_pList ) delete [] m_pList;
00335 ZeroMemory( pList + m_nList, ( m_nBuffer - m_nList ) * sizeof(LDVITEM) );
00336 m_pList = pList;
00337 }
00338
00339 m_pList[ m_nList ].nIndex = pFile->m_nIndex;
00340 m_pList[ m_nList ].nState &= ~LDVI_SELECTED;
00341 m_nList++;
00342
00343 pFile->m_nListCookie = nCookie;
00344 }
00345 }
00346
00347 m_nListCookie++;
00348
00349 SortItems();
00350 }
00351
00352 BOOL CLibraryDetailView::Select(DWORD nObject)
00353 {
00354 GET_LIST();
00355
00356 for ( int nDeselect = -1 ; ; )
00357 {
00358 nDeselect = pList->GetNextItem( nDeselect, LVNI_SELECTED );
00359 if ( nDeselect < 0 ) break;
00360 pList->SetItemState( nDeselect, 0, LVIS_SELECTED );
00361 }
00362
00363 LDVITEM* pItem = m_pList;
00364
00365 for ( DWORD nCount = 0 ; nCount < m_nList ; nCount++, pItem++ )
00366 {
00367 if ( pItem->nIndex == nObject )
00368 {
00369 LV_ITEM pItem;
00370
00371 pItem.mask = LVIF_STATE; pItem.state = 0xFFFFFFFF; pItem.stateMask = LVIS_SELECTED|LVIS_FOCUSED;
00372 SendMessage( LVM_SETITEMSTATE, nCount, (LPARAM)&pItem );
00373 PostMessage( LVM_ENSUREVISIBLE, nCount, FALSE );
00374
00375 return TRUE;
00376 }
00377 }
00378
00379 return FALSE;
00380 }
00381
00382 void CLibraryDetailView::CacheItem(int nItem)
00383 {
00384 CLibraryFile* pFile = Library.LookupFile( m_pList[ nItem ].nIndex );
00385 if ( ! pFile ) return;
00386
00387 LDVITEM* pItem = &m_pList[ nItem ];
00388 pItem->nCookie = m_nListCookie;
00389
00390 if ( pItem->pText == NULL ) pItem->pText = new CStringArray();
00391
00392 CStringArray* pText = pItem->pText;
00393 pText->SetSize( m_nStyle == LVS_REPORT ? DETAIL_COLUMNS + m_pColumns.GetCount() : 1 );
00394
00395 CString strName( pFile->m_sName );
00396 int nDot = strName.ReverseFind( '.' );
00397 if ( nDot >= 0 ) strName.SetAt( nDot, 0 );
00398 pText->SetAt( 0, strName );
00399
00400 if ( m_nStyle == LVS_ICON )
00401 {
00402 pItem->nIcon = ShellIcons.Get( pFile->m_sName, 32 );
00403 }
00404 else
00405 {
00406 if ( pFile->m_nIcon16 >= 0 )
00407 pItem->nIcon = pFile->m_nIcon16;
00408 else
00409 pItem->nIcon = pFile->m_nIcon16 = ShellIcons.Get( pFile->m_sName, 16 );
00410 }
00411
00412 pItem->nState &= LDVI_SELECTED;
00413 if ( ! pFile->IsShared() ) pItem->nState |= LDVI_PRIVATE;
00414 if ( ! pFile->m_bSHA1 ) pItem->nState |= LDVI_UNSCANNED;
00415 if ( pFile->m_bVerify == TS_FALSE ) pItem->nState |= LDVI_UNSAFE;
00416
00417 if ( m_nStyle != LVS_REPORT ) return;
00418
00419 if ( LPCTSTR pszType = _tcsrchr( pFile->m_sName, '.' ) )
00420 pText->SetAt( 1, pszType + 1 );
00421 else
00422 pText->SetAt( 1, _T("") );
00423
00424 pText->SetAt( 2, Settings.SmartVolume( pFile->GetSize(), FALSE ) );
00425 if ( pFile->m_pFolder != NULL ) pText->SetAt( 3, pFile->m_pFolder->m_sPath );
00426
00427 CString str;
00428 str.Format( _T("%lu (%lu)"), pFile->m_nHitsToday, pFile->m_nHitsTotal );
00429 pText->SetAt( 4, str );
00430 str.Format( _T("%lu (%lu)"), pFile->m_nUploadsToday, pFile->m_nUploadsTotal );
00431 pText->SetAt( 5, str );
00432
00433 TCHAR szModified[ 64 ];
00434 SYSTEMTIME pTime;
00435
00436 FileTimeToSystemTime( &pFile->m_pTime, &pTime );
00437 SystemTimeToTzSpecificLocalTime( NULL, &pTime, &pTime );
00438
00439 GetDateFormat( LOCALE_USER_DEFAULT, 0, &pTime, _T("yyyy-MM-dd"), szModified, 64 );
00440 _tcscat( szModified, _T(" ") );
00441 GetTimeFormat( LOCALE_USER_DEFAULT, 0, &pTime, _T("hh:mm tt"), szModified + _tcslen( szModified ), 64 - _tcslen( szModified ) );
00442
00443 pText->SetAt( 6, szModified );
00444
00445 if ( m_pSchema == NULL ) return;
00446
00447 int nColumn = DETAIL_COLUMNS;
00448
00449 BOOL bSource = pFile->m_pMetadata && m_pSchema->Equals( pFile->m_pSchema ) &&
00450 m_pSchema->m_sSingular.CompareNoCase( pFile->m_pMetadata->GetName() ) == 0;
00451
00452 for ( POSITION pos = m_pColumns.GetHeadPosition() ; pos ; nColumn++ )
00453 {
00454 CSchemaMember* pMember = (CSchemaMember*)m_pColumns.GetNext( pos );
00455
00456 if ( pMember->m_sName.CompareNoCase( _T("SHA1") ) == 0 )
00457 {
00458 if ( pFile->m_bSHA1 )
00459 {
00460 pText->SetAt( nColumn, CSHA::HashToString( &pFile->m_pSHA1 ) );
00461 }
00462 else pText->SetAt( nColumn, _T("") );
00463 }
00464 else if ( bSource )
00465 {
00466 pText->SetAt( nColumn, pMember->GetValueFrom( pFile->m_pMetadata, NULL, TRUE ) );
00467 }
00468 else
00469 {
00470 pText->SetAt( nColumn, _T("") );
00471 }
00472 }
00473 }
00474
00475 void CLibraryDetailView::OnCacheHint(NMLVCACHEHINT* pNotify, LRESULT* pResult)
00476 {
00477 CSingleLock oLock( &Library.m_pSection );
00478 if ( !oLock.Lock( 100 ) ) return;
00479
00480 for ( int nItem = pNotify->iFrom ; nItem <= pNotify->iTo ; nItem++ )
00481 {
00482 CacheItem( nItem );
00483 }
00484 }
00485
00486 void CLibraryDetailView::OnGetDispInfoW(NMLVDISPINFO* pNotify, LRESULT* pResult)
00487 {
00488 *pResult = 0;
00489
00490 LDVITEM* pItem = &m_pList[ pNotify->item.iItem ];
00491
00492 if ( pNotify->item.mask & LVIF_STATE )
00493 {
00494 pNotify->item.state &= ~LVIS_SELECTED;
00495 if ( pItem->nState & LDVI_SELECTED ) pNotify->item.state |= LVIS_SELECTED;
00496 }
00497
00498 if ( pItem->nCookie != m_nListCookie )
00499 {
00500 {
00501 CSingleLock oLock( &Library.m_pSection );
00502 if ( !oLock.Lock( 100 ) ) return;
00503 CacheItem( pNotify->item.iItem );
00504 }
00505 if ( pItem->nCookie != m_nListCookie ) return;
00506 }
00507
00508 if ( pNotify->item.mask & LVIF_TEXT )
00509 {
00510 if ( pNotify->item.iSubItem < pItem->pText->GetSize() )
00511 {
00512 wcsncpy( (LPWSTR)pNotify->item.pszText, pItem->pText->GetAt( pNotify->item.iSubItem ), pNotify->item.cchTextMax );
00513 }
00514 }
00515
00516 if ( pNotify->item.mask & LVIF_IMAGE )
00517 {
00518 pNotify->item.iImage = pItem->nIcon;
00519 }
00520 }
00521
00522 void CLibraryDetailView::OnGetDispInfoA(NMLVDISPINFO* pNotify, LRESULT* pResult)
00523 {
00524 *pResult = 0;
00525
00526 LDVITEM* pItem = &m_pList[ pNotify->item.iItem ];
00527
00528 if ( pNotify->item.mask & LVIF_STATE )
00529 {
00530 pNotify->item.state &= ~LVIS_SELECTED;
00531 if ( pItem->nState & LDVI_SELECTED ) pNotify->item.state |= LVIS_SELECTED;
00532 }
00533
00534 if ( pItem->nCookie != m_nListCookie )
00535 {
00536 {
00537 CSingleLock oLock( &Library.m_pSection );
00538 if ( !oLock.Lock( 100 ) ) return;
00539 CacheItem( pNotify->item.iItem );
00540 }
00541 if ( pItem->nCookie != m_nListCookie ) return;
00542 }
00543
00544 if ( pNotify->item.mask & LVIF_TEXT )
00545 {
00546 if ( pNotify->item.iSubItem < pItem->pText->GetSize() )
00547 {
00548 WideCharToMultiByte( CP_ACP, 0, pItem->pText->GetAt( pNotify->item.iSubItem ), -1, (LPSTR)pNotify->item.pszText, pNotify->item.cchTextMax, NULL, NULL );
00549 }
00550 }
00551
00552 if ( pNotify->item.mask & LVIF_IMAGE )
00553 {
00554 pNotify->item.iImage = pItem->nIcon;
00555 }
00556 }
00557
00559
00560
00561 CLibraryDetailView* CLibraryDetailView::m_pThis;
00562
00563 void CLibraryDetailView::SortItems(int nColumn)
00564 {
00565 GET_LIST();
00566
00567 CLiveList::Sort( pList, nColumn );
00568 nColumn = ( m_nStyle == LVS_REPORT ) ? GetWindowLong( GetSafeHwnd(), GWL_USERDATA ) : -1;
00569
00570 if ( nColumn != 0 )
00571 {
00572 m_nSortColumn = abs( nColumn ) - 1;
00573 m_bSortFlip = nColumn < 0;
00574 m_pThis = this;
00575 qsort( m_pList, m_nList, sizeof(m_pList[0]), ListCompare );
00576 }
00577
00578 pList->SetItemCount( m_nList );
00579 }
00580
00581 int CLibraryDetailView::ListCompare(LPCVOID pA, LPCVOID pB)
00582 {
00583 LDVITEM* ppA = (LDVITEM*)pA;
00584 LDVITEM* ppB = (LDVITEM*)pB;
00585 int nTest = 0;
00586
00587 CLibraryFile* pfA = Library.LookupFile( ppA->nIndex );
00588 CLibraryFile* pfB = Library.LookupFile( ppB->nIndex );
00589
00590 if ( ! pfA || ! pfB ) return 0;
00591
00592 switch ( m_pThis->m_nSortColumn )
00593 {
00594 case 0:
00595 nTest = _tcsicoll( pfA->m_sName, pfB->m_sName );
00596 break;
00597 case 1:
00598 {
00599 LPCTSTR pszA = _tcsrchr( pfA->m_sName, '.' );
00600 LPCTSTR pszB = _tcsrchr( pfB->m_sName, '.' );
00601 if ( ! pszA || ! pszB ) return 0;
00602 nTest = _tcsicoll( pszA, pszB );
00603 break;
00604 }
00605 case 2:
00606 if ( pfA->GetSize() == pfB->GetSize() )
00607 nTest = 0;
00608 else if ( pfA->GetSize() < pfB->GetSize() )
00609 nTest = -1;
00610 else
00611 nTest = 1;
00612 break;
00613 case 3:
00614 if ( pfA->m_pFolder == NULL || pfB->m_pFolder == NULL ) return 0;
00615 nTest = _tcsicoll( pfA->m_pFolder->m_sPath, pfB->m_pFolder->m_sPath );
00616 break;
00617 case 4:
00618 if ( pfA->m_nHitsTotal == pfB->m_nHitsTotal )
00619 nTest = 0;
00620 else if ( pfA->m_nHitsTotal < pfB->m_nHitsTotal )
00621 nTest = -1;
00622 else
00623 nTest = 1;
00624 break;
00625 case 5:
00626 if ( pfA->m_nUploadsTotal == pfB->m_nUploadsTotal )
00627 nTest = 0;
00628 else if ( pfA->m_nUploadsTotal < pfB->m_nUploadsTotal )
00629 nTest = -1;
00630 else
00631 nTest = 1;
00632 break;
00633 case 6:
00634 nTest = CompareFileTime( &pfA->m_pTime, &pfB->m_pTime );
00635 break;
00636 default:
00637 {
00638 int nColumn = m_pThis->m_nSortColumn - DETAIL_COLUMNS;
00639 if ( nColumn >= m_pThis->m_pColumns.GetCount() ) return 0;
00640 POSITION pos = m_pThis->m_pColumns.FindIndex( nColumn );
00641 if ( pos == NULL ) return 0;
00642 CSchemaMember* pMember = (CSchemaMember*)m_pThis->m_pColumns.GetAt( pos );
00643
00644 CString strA, strB;
00645 if ( pfA->m_pMetadata ) strA = pMember->GetValueFrom( pfA->m_pMetadata, NULL, TRUE );
00646 if ( pfB->m_pMetadata ) strB = pMember->GetValueFrom( pfB->m_pMetadata, NULL, TRUE );
00647
00648 if ( *(LPCTSTR)strA && *(LPCTSTR)strB &&
00649 ( ((LPCTSTR)strA)[ _tcslen( strA ) - 1 ] == 'k' || ((LPCTSTR)strA)[ _tcslen( strA ) - 1 ] == '~' )
00650 &&
00651 ( ((LPCTSTR)strB)[ _tcslen( strB ) - 1 ] == 'k' || ((LPCTSTR)strB)[ _tcslen( strB ) - 1 ] == '~' ) )
00652 {
00653 nTest = CLiveList::SortProc( strA, strB, TRUE );
00654 }
00655 else
00656 {
00657 nTest = _tcsicoll( strA, strB );
00658 }
00659 }
00660 }
00661
00662 if ( ! m_pThis->m_bSortFlip ) nTest = -nTest;
00663
00664 return nTest;
00665 }
00666
00668
00669
00670 void CLibraryDetailView::CacheSelection()
00671 {
00672 GET_LIST();
00673 SelClear( FALSE );
00674
00675 for ( int nItem = -1 ; ( nItem = pList->GetNextItem( nItem, LVNI_SELECTED ) ) >= 0 ; )
00676 {
00677 SelAdd( pList->GetItemData( nItem ), FALSE );
00678 }
00679 }
00680
00681 DWORD CLibraryDetailView::HitTestIndex(const CPoint& point) const
00682 {
00683 GET_LIST();
00684 int nItem = pList->HitTest( point );
00685 if ( nItem < 0 ) return 0;
00686 return m_pList[ nItem ].nIndex;
00687 }
00688
00689 void CLibraryDetailView::OnItemChanged(NM_LISTVIEW* pNotify, LRESULT* pResult)
00690 {
00691 *pResult = 0;
00692
00693 if ( pNotify->iItem >= 0 )
00694 {
00695 if ( ( pNotify->uOldState & LVIS_SELECTED ) != ( pNotify->uNewState & LVIS_SELECTED ) )
00696 {
00697 if ( pNotify->uNewState & LVIS_SELECTED )
00698 {
00699 SelAdd( m_pList[ pNotify->iItem ].nIndex );
00700 m_pList[ pNotify->iItem ].nState |= LDVI_SELECTED;
00701 }
00702 else
00703 {
00704 SelRemove( m_pList[ pNotify->iItem ].nIndex );
00705 m_pList[ pNotify->iItem ].nState &= ~LDVI_SELECTED;
00706 }
00707 }
00708 }
00709 else
00710 {
00711 SelClear();
00712
00713 LDVITEM* pItem = m_pList;
00714 for ( DWORD nCount = m_nList ; nCount ; nCount--, pItem++ ) pItem->nState &= ~LDVI_SELECTED;
00715 }
00716 }
00717
00718 void CLibraryDetailView::OnItemRangeChanged(NMLVODSTATECHANGE* pNotify, LRESULT* pResult)
00719 {
00720 *pResult = 0;
00721
00722 for ( int nItem = pNotify->iFrom ; nItem <= pNotify->iTo ; nItem++ )
00723 {
00724 if ( pNotify->uNewState & LVIS_SELECTED )
00725 {
00726 SelAdd( m_pList[ nItem ].nIndex );
00727 m_pList[ nItem ].nState |= LDVI_SELECTED;
00728 }
00729 else
00730 {
00731 SelRemove( m_pList[ nItem ].nIndex );
00732 m_pList[ nItem ].nState &= ~LDVI_SELECTED;
00733 }
00734 }
00735 }
00736
00738
00739
00740 void CLibraryDetailView::OnColumnClick(NM_LISTVIEW* pNotify, LRESULT* pResult)
00741 {
00742 *pResult = 0;
00743 SortItems( pNotify->iSubItem );
00744 }
00745
00746 void CLibraryDetailView::OnBeginLabelEdit(LV_DISPINFO* pNotify, LRESULT* pResult)
00747 {
00748 m_bEditing = TRUE;
00749 *pResult = 0;
00750 }
00751
00752 void CLibraryDetailView::OnEndLabelEditW(LV_DISPINFO* pNotify, LRESULT* pResult)
00753 {
00754 *pResult = 0;
00755
00756 if ( pNotify->item.pszText && *pNotify->item.pszText )
00757 {
00758 CSingleLock oLock( &Library.m_pSection, TRUE );
00759 if ( CLibraryFile* pFile = Library.LookupFile( m_pList[ pNotify->item.iItem ].nIndex ) )
00760 {
00761 m_pList[ pNotify->item.iItem ].nState &= ~LDVI_SELECTED;
00762 CString strName = (LPCWSTR)pNotify->item.pszText;
00763 LPCTSTR pszType = _tcsrchr( pFile->m_sName, '.' );
00764 if ( pszType ) strName += pszType;
00765 *pResult = pFile->Rename( strName );
00766 Library.Update();
00767 oLock.Unlock();
00768
00769 if ( *pResult == FALSE )
00770 {
00771 CString strFormat, strMessage, strError = theApp.GetErrorString();
00772 LoadString( strFormat, IDS_LIBRARY_RENAME_FAIL );
00773 strMessage.Format( strFormat, (LPCTSTR)pFile->m_sName, (LPCTSTR)strName );
00774 strMessage += _T("\r\n\r\n") + strError;
00775 AfxMessageBox( strMessage, MB_ICONEXCLAMATION );
00776 }
00777 }
00778 }
00779
00780 m_bEditing = FALSE;
00781 }
00782
00783 void CLibraryDetailView::OnEndLabelEditA(LV_DISPINFO* pNotify, LRESULT* pResult)
00784 {
00785 *pResult = 0;
00786
00787 if ( pNotify->item.pszText && *pNotify->item.pszText )
00788 {
00789 CSingleLock oLock( &Library.m_pSection, TRUE );
00790 if ( CLibraryFile* pFile = Library.LookupFile( m_pList[ pNotify->item.iItem ].nIndex ) )
00791 {
00792 m_pList[ pNotify->item.iItem ].nState &= ~LDVI_SELECTED;
00793 CString strName = (LPCSTR)pNotify->item.pszText;
00794 LPCTSTR pszType = _tcsrchr( pFile->m_sName, '.' );
00795 if ( pszType ) strName += pszType;
00796 *pResult = pFile->Rename( strName );
00797 Library.Update();
00798 oLock.Unlock();
00799
00800 if ( *pResult == FALSE )
00801 {
00802 CString strFormat, strMessage, strError = theApp.GetErrorString();
00803 LoadString( strFormat, IDS_LIBRARY_RENAME_FAIL );
00804 strMessage.Format( strFormat, (LPCTSTR)pFile->m_sName, (LPCTSTR)strName );
00805 strMessage += _T("\r\n\r\n") + strError;
00806 AfxMessageBox( strMessage, MB_ICONEXCLAMATION );
00807 }
00808 }
00809 }
00810
00811 m_bEditing = FALSE;
00812 }
00813
00814 void CLibraryDetailView::OnFindItemW(NMLVFINDITEM* pNotify, LRESULT* pResult)
00815 {
00816 USES_CONVERSION;
00817 LPCTSTR pszFind = W2CT( (LPCWSTR)pNotify->lvfi.psz );
00818
00819 GET_LIST();
00820 CQuickLock oLock( Library.m_pSection );
00821
00822 for ( int nLoop = 0 ; nLoop < 2 ; nLoop++ )
00823 {
00824 for ( int nItem = pNotify->iStart ; nItem < pList->GetItemCount() ; nItem++ )
00825 {
00826 if ( CLibraryFile* pFile = Library.LookupFile( m_pList[ nItem ].nIndex ) )
00827 {
00828 if ( pNotify->lvfi.flags & LVFI_STRING )
00829 {
00830 if ( _tcsnicmp( pszFind, pFile->m_sName, _tcslen( pszFind ) ) == 0 )
00831 {
00832 *pResult = nItem;
00833 return;
00834 }
00835 }
00836 }
00837 }
00838 pNotify->iStart = 0;
00839 }
00840
00841 *pResult = -1;
00842 }
00843
00844 void CLibraryDetailView::OnFindItemA(NMLVFINDITEM* pNotify, LRESULT* pResult)
00845 {
00846 USES_CONVERSION;
00847 LPCTSTR pszFind = A2CT( (LPCSTR)pNotify->lvfi.psz );
00848
00849 GET_LIST();
00850 CQuickLock oLock( Library.m_pSection );
00851
00852 for ( int nLoop = 0 ; nLoop < 2 ; nLoop++ )
00853 {
00854 for ( int nItem = pNotify->iStart ; nItem < pList->GetItemCount() ; nItem++ )
00855 {
00856 if ( CLibraryFile* pFile = Library.LookupFile( m_pList[ nItem ].nIndex ) )
00857 {
00858 if ( pNotify->lvfi.flags & LVFI_STRING )
00859 {
00860 if ( _tcsnicmp( pszFind, pFile->m_sName, _tcslen( pszFind ) ) == 0 )
00861 {
00862 *pResult = nItem;
00863 return;
00864 }
00865 }
00866 }
00867 }
00868 pNotify->iStart = 0;
00869 }
00870
00871 *pResult = -1;
00872 }
00873
00874 void CLibraryDetailView::OnCustomDraw(NMLVCUSTOMDRAW* pNotify, LRESULT* pResult)
00875 {
00876 if ( pNotify->nmcd.dwDrawStage == CDDS_PREPAINT )
00877 {
00878 *pResult = CDRF_NOTIFYITEMDRAW;
00879 }
00880 else if ( pNotify->nmcd.dwDrawStage == CDDS_ITEMPREPAINT &&
00881 pNotify->nmcd.dwItemSpec < m_nList )
00882 {
00883 LDVITEM* pItem = m_pList + pNotify->nmcd.dwItemSpec;
00884
00885 if ( pItem->nState & LDVI_SELECTED )
00886 {
00887 pNotify->clrText = CoolInterface.m_crHiText;
00888 pNotify->clrTextBk = CoolInterface.m_crHighlight;
00889 }
00890 else if ( pItem->nState & LDVI_UNSAFE ) pNotify->clrText = RGB( 255, 0, 0 );
00891 else if ( pItem->nState & LDVI_UNSCANNED ) pNotify->clrText = CoolInterface.m_crDisabled;
00892 else if ( pItem->nState & LDVI_PRIVATE ) pNotify->clrText = CoolInterface.m_crHighlight;
00893
00894 if ( m_bCreateDragImage )
00895 {
00896 pNotify->clrTextBk = RGB( 250, 255, 250 );
00897 }
00898
00899 *pResult = CDRF_DODEFAULT;
00900 }
00901 else
00902 {
00903 *pResult = 0;
00904 }
00905 }
00906
00907 void CLibraryDetailView::OnDblClk(NMHDR* pNotify, LRESULT* pResult)
00908 {
00909 *pResult = 0;
00910 SendMessage( WM_COMMAND, ID_LIBRARY_LAUNCH );
00911 }
00912
00914
00915
00916 void CLibraryDetailView::OnContextMenu(CWnd* pWnd, CPoint point)
00917 {
00918 CRect rcHeader;
00919
00920 if ( CWnd* pHeader = GetWindow( GW_CHILD ) )
00921 {
00922 pHeader->GetWindowRect( &rcHeader );
00923 }
00924
00925 if ( m_pSchema == NULL || rcHeader.PtInRect( point ) == FALSE || m_nStyle != LVS_REPORT )
00926 {
00927 CLibraryFileView::OnContextMenu( pWnd, point );
00928 return;
00929 }
00930
00931 CMenu* pMenu = CSchemaColumnsDlg::BuildColumnMenu( m_pSchema, &m_pColumns );
00932
00933 pMenu->AppendMenu( MF_SEPARATOR, ID_SEPARATOR, (LPCTSTR)NULL );
00934 CString strSchemas;
00935 LoadString( strSchemas, IDS_SCHEMAS );
00936 pMenu->AppendMenu( MF_STRING, ID_LIBRARY_COLUMNS, strSchemas + _T("...") );
00937
00938 m_pCoolMenu = new CCoolMenu();
00939 m_pCoolMenu->AddMenu( pMenu, TRUE );
00940 m_pCoolMenu->SetWatermark( Skin.GetWatermark( _T("CCoolMenu") ) );
00941
00942 UINT nCmd = pMenu->TrackPopupMenu( TPM_LEFTALIGN|TPM_LEFTBUTTON|TPM_RIGHTBUTTON|
00943 TPM_RETURNCMD, point.x, point.y, this );
00944
00945 delete pMenu;
00946 delete m_pCoolMenu;
00947 m_pCoolMenu = NULL;
00948
00949 if ( nCmd == ID_LIBRARY_COLUMNS )
00950 {
00951 OnLibraryColumns();
00952 }
00953 else if ( nCmd )
00954 {
00955 CPtrList pColumns;
00956 CSchemaColumnsDlg::ToggleColumnHelper( m_pSchema, &m_pColumns, &pColumns, nCmd, TRUE );
00957 SetViewSchema( m_pSchema, &pColumns, TRUE, TRUE );
00958 }
00959 }
00960
00961 void CLibraryDetailView::OnUpdateBlocker(CCmdUI* pCmdUI)
00962 {
00963 if ( m_pCoolMenu ) pCmdUI->Enable( TRUE );
00964 else pCmdUI->ContinueRouting();
00965 }
00966
00967 void CLibraryDetailView::OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct)
00968 {
00969 if ( m_pCoolMenu ) m_pCoolMenu->OnMeasureItem( lpMeasureItemStruct );
00970 }
00971
00972 void CLibraryDetailView::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct)
00973 {
00974 if ( m_pCoolMenu ) m_pCoolMenu->OnDrawItem( lpDrawItemStruct );
00975 }
00976
00978
00979
00980 void CLibraryDetailView::OnBeginDrag(NM_LISTVIEW* pNotify, LRESULT* pResult)
00981 {
00982 GET_LIST();
00983
00984 CPoint ptAction( pNotify->ptAction );
00985
00986 m_bCreateDragImage = TRUE;
00987 CImageList* pImage = CLiveList::CreateDragImage( pList, ptAction );
00988 m_bCreateDragImage = FALSE;
00989
00990 if ( pImage == NULL ) return;
00991
00992 UpdateWindow();
00993
00994 ClientToScreen( &ptAction );
00995 DragObjects( pImage, ptAction );
00996 }
00997
00999
01000
01001 void CLibraryDetailView::OnUpdateLibraryRename(CCmdUI* pCmdUI)
01002 {
01003 pCmdUI->Enable( GetSelectedCount() == 1 );
01004 }
01005
01006 void CLibraryDetailView::OnLibraryRename()
01007 {
01008 int nItem = ListView_GetNextItem( GetSafeHwnd(), -1, LVNI_SELECTED );
01009 if ( nItem >= 0 ) ListView_EditLabel( GetSafeHwnd(), nItem );
01010 }
01011
01012 void CLibraryDetailView::OnUpdateLibraryColumns(CCmdUI* pCmdUI)
01013 {
01014 pCmdUI->Enable( m_nStyle == LVS_REPORT );
01015 }
01016
01017 void CLibraryDetailView::OnLibraryColumns()
01018 {
01019 CSchemaColumnsDlg dlg;
01020
01021 dlg.m_pSchema = m_pSchema;
01022 dlg.m_pColumns.AddTail( &m_pColumns );
01023
01024 if ( dlg.DoModal() != IDOK ) return;
01025
01026 if ( Settings.Library.FilterURI.IsEmpty() )
01027 {
01028 Settings.Library.SchemaURI.Empty();
01029 if ( dlg.m_pSchema ) Settings.Library.SchemaURI = dlg.m_pSchema->m_sURI;
01030 }
01031
01032 SetViewSchema( dlg.m_pSchema, &dlg.m_pColumns, TRUE, TRUE );
01033 }
01034