Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members

CtrlLibraryDetailView.cpp

Go to the documentation of this file.
00001 //
00002 // CtrlLibraryDetailView.cpp
00003 //
00004 // Copyright (c) Shareaza Development Team, 2002-2005.
00005 // This file is part of SHAREAZA (www.shareaza.com)
00006 //
00007 // Shareaza is free software; you can redistribute it
00008 // and/or modify it under the terms of the GNU General Public License
00009 // as published by the Free Software Foundation; either version 2 of
00010 // the License, or (at your option) any later version.
00011 //
00012 // Shareaza is distributed in the hope that it will be useful,
00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 // GNU General Public License for more details.
00016 //
00017 // You should have received a copy of the GNU General Public License
00018 // along with Shareaza; if not, write to the Free Software
00019 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
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         //{{AFX_MSG_MAP(CLibraryDetailView)
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         //}}AFX_MSG_MAP
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 // CLibraryDetailView construction
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 // CLibraryDetailView create and destroy
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 // CLibraryDetailView schema setup
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 // CLibraryDetailView update
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 )     // MUST EQUAL
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 // CLibraryDetailView sorting
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 // CLibraryDetailView selection operations
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 // CLibraryDetailView list coupling
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 // CLibraryDetailView column context menu
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 // CLibraryDetailView drag / drop
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 // CLibraryDetailView command handlers
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 

Generated on Thu Dec 15 10:39:35 2005 for Shareaza 2.2.1.0 by  doxygen 1.4.2