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 "MetaList.h"
00025 #include "Schema.h"
00026 #include "XML.h"
00027 #include "Library.h"
00028 #include "LibraryFolders.h"
00029
00030 #ifdef _DEBUG
00031 #undef THIS_FILE
00032 static char THIS_FILE[]=__FILE__;
00033 #define new DEBUG_NEW
00034 #endif
00035
00036 CString strMultiple;
00037
00039
00040
00041 CMetaList::CMetaList()
00042 {
00043 LoadString( strMultiple, IDS_MULTIPLE );
00044 }
00045
00046 CMetaList::~CMetaList()
00047 {
00048 Clear();
00049 }
00050
00052
00053
00054 void CMetaList::Clear()
00055 {
00056 for ( POSITION pos = GetIterator() ; pos ; )
00057 {
00058 delete GetNext( pos );
00059 }
00060
00061 m_pItems.RemoveAll();
00062 }
00063
00065
00066
00067 CMetaItem* CMetaList::Add(LPCTSTR pszKey, LPCTSTR pszValue)
00068 {
00069 CMetaItem* pItem = new CMetaItem( NULL );
00070 pItem->m_sKey = pszKey;
00071 pItem->m_sValue = pszValue;
00072 m_pItems.AddTail( pItem );
00073 return pItem;
00074 }
00075
00077
00078
00079 CMetaItem* CMetaList::Find(LPCTSTR pszKey) const
00080 {
00081 for ( POSITION pos = GetIterator() ; pos ; )
00082 {
00083 CMetaItem* pItem = GetNext( pos );
00084 if ( pItem->m_sKey.CompareNoCase( pszKey ) == 0 ) return pItem;
00085 }
00086
00087 return NULL;
00088 }
00089
00091
00092
00093 void CMetaList::Remove(LPCTSTR pszKey)
00094 {
00095 for ( POSITION pos = GetIterator() ; pos ; )
00096 {
00097 POSITION posCur = pos;
00098
00099 CMetaItem* pItem = GetNext( pos );
00100
00101 if ( pItem->m_sKey.CompareNoCase( pszKey ) == 0 )
00102 {
00103 m_pItems.RemoveAt( posCur );
00104 delete pItem;
00105 }
00106 }
00107 }
00108
00110
00111
00112 void CMetaList::Shuffle()
00113 {
00114 if ( m_pItems.GetCount() < 2 ) return;
00115
00116 CMetaItem* pItem = (CMetaItem*)m_pItems.RemoveHead();
00117 m_pItems.AddTail( pItem );
00118 }
00119
00121
00122
00123 void CMetaList::Setup(CSchema* pSchema, BOOL bClear)
00124 {
00125 if ( bClear ) Clear();
00126 if ( ! pSchema ) return;
00127
00128 for ( POSITION pos = pSchema->GetMemberIterator() ; pos ; )
00129 {
00130 CSchemaMember* pMember = pSchema->GetNextMember( pos );
00131 m_pItems.AddTail( new CMetaItem( pMember ) );
00132 }
00133 }
00134
00136
00137
00138 void CMetaList::Combine(CXMLElement* pXML)
00139 {
00140 if ( pXML == NULL ) return;
00141
00142 for ( POSITION pos = GetIterator() ; pos ; )
00143 {
00144 GetNext( pos )->Combine( pXML );
00145 }
00146 }
00147
00149
00150
00151 void CMetaList::Vote()
00152 {
00153 for ( POSITION pos = GetIterator() ; pos ; )
00154 {
00155 GetNext( pos )->Vote();
00156 }
00157 }
00158
00160
00161
00162 void CMetaList::CreateLinks()
00163 {
00164 for ( POSITION pos = GetIterator() ; pos ; )
00165 {
00166 CMetaItem* pItem = GetNext( pos );
00167 pItem->CreateLink();
00168
00169 int nLink = pItem->m_sKey.Find( _T("Link") );
00170
00171 if ( nLink > 0 )
00172 {
00173 CString strBase( pItem->m_sKey.Left( nLink ) );
00174 strBase.TrimRight();
00175
00176 if ( CMetaItem* pBase = Find( strBase ) )
00177 {
00178 if ( pBase->m_sValue.GetLength() )
00179 {
00180 pItem->m_sKey = pBase->m_sKey;
00181 pItem->m_sValue = pBase->m_sValue;
00182 pBase->m_sKey.Empty();
00183 pBase->m_sValue.Empty();
00184 }
00185 }
00186 }
00187 }
00188 }
00189
00191
00192
00193 void CMetaList::Clean(int nMaxLength)
00194 {
00195 for ( POSITION pos = GetIterator() ; pos ; )
00196 {
00197 POSITION posCur = pos;
00198 CMetaItem* pItem = GetNext( pos );
00199
00200 if ( ! pItem->Limit( nMaxLength ) )
00201 {
00202 m_pItems.RemoveAt( posCur );
00203 delete pItem;
00204 }
00205 }
00206 }
00207
00209
00210
00211 void CMetaList::ComputeWidth(CDC* pDC, int& nKeyWidth, int& nValueWidth)
00212 {
00213 for ( POSITION pos = GetIterator() ; pos ; )
00214 {
00215 CMetaItem* pItem = GetNext( pos );
00216
00217 CSize szKey = pDC->GetTextExtent( pItem->m_sKey + ':' );
00218 CSize szValue = pDC->GetTextExtent( pItem->m_sValue );
00219
00220 nKeyWidth = max( nKeyWidth, int(szKey.cx) );
00221 nValueWidth = max( nValueWidth, int(szValue.cx) );
00222 }
00223 }
00224
00226
00227
00228 CMetaItem* CMetaList::HitTest(const CPoint& point, BOOL bLinksOnly)
00229 {
00230 for ( POSITION pos = GetIterator() ; pos ; )
00231 {
00232 CMetaItem* pItem = GetNext( pos );
00233 if ( pItem->m_rect.PtInRect( point ) )
00234 {
00235 if ( bLinksOnly && ! pItem->m_bLink ) return NULL;
00236 return pItem;
00237 }
00238 }
00239
00240 return NULL;
00241 }
00242
00244
00245
00246 BOOL CMetaList::OnSetCursor(CWnd* pWnd)
00247 {
00248 CPoint point;
00249 GetCursorPos( &point );
00250 pWnd->ScreenToClient( &point );
00251
00252 if ( HitTest( point, TRUE ) == NULL ) return FALSE;
00253
00254 SetCursor( AfxGetApp()->LoadCursor( IDC_HAND ) );
00255 return TRUE;
00256 }
00257
00258
00260
00261
00262 CMetaItem::CMetaItem(CSchemaMember* pMember) : m_rect( 0, 0, 0, 0 )
00263 {
00264 m_pMember = pMember;
00265 m_bLink = FALSE;
00266
00267 if ( m_pMember ) m_sKey = m_pMember->m_sTitle;
00268 }
00269
00271
00272
00273 BOOL CMetaItem::Combine(CXMLElement* pXML)
00274 {
00275 if ( ! m_pMember ) return FALSE;
00276
00277 CString strValue = m_pMember->GetValueFrom( pXML, NULL, TRUE );
00278
00279 strValue.TrimLeft();
00280 strValue.TrimRight();
00281
00282 if ( strValue.IsEmpty() ) return FALSE;
00283
00284 if ( m_sValue.IsEmpty() )
00285 {
00286 m_sValue = strValue;
00287 }
00288 else if ( m_sValue != strValue )
00289 {
00290 m_sValue = strMultiple;
00291 }
00292
00293 int nVote = 1;
00294 if ( m_pVote.Lookup( strValue, (void*&)nVote ) ) nVote ++;
00295 m_pVote.SetAt( strValue, (void*)nVote );
00296
00297 return TRUE;
00298 }
00299
00301
00302
00303 void CMetaItem::Vote()
00304 {
00305 if ( m_sValue != strMultiple ) return;
00306
00307 int nBest = 0;
00308
00309 for ( POSITION pos = m_pVote.GetStartPosition() ; pos ; )
00310 {
00311 CString strValue;
00312 int nVote;
00313
00314 m_pVote.GetNextAssoc( pos, strValue, (void*&)nVote );
00315
00316 if ( nVote > nBest )
00317 {
00318 nBest = nVote;
00319 m_sValue = strValue;
00320 }
00321 }
00322
00323 m_pVote.RemoveAll();
00324 }
00325
00327
00328
00329 BOOL CMetaItem::Limit(int nMaxLength)
00330 {
00331 if ( m_sValue.IsEmpty() )
00332 {
00333 return FALSE;
00334 }
00335 else if ( nMaxLength > 0 && m_sValue.GetLength() > nMaxLength )
00336 {
00337 m_sValue = m_sValue.Left( nMaxLength ) + _T("...");
00338 }
00339
00340 return TRUE;
00341 }
00342
00344
00345
00346 BOOL CMetaItem::CreateLink()
00347 {
00348 if ( m_sValue.Find( _T("http://") ) == 0 || m_sValue.Find( _T("www.") ) == 0 )
00349 {
00350 m_bLink = TRUE;
00351 m_sLink = m_sValue;
00352 return TRUE;
00353 }
00354
00355 if ( m_pMember == NULL ) return FALSE;
00356
00357 if ( m_pMember->m_sLinkURI.IsEmpty() ) return FALSE;
00358 if ( m_pMember->m_sLinkName.IsEmpty() ) return FALSE;
00359
00360 m_bLink = LibraryFolders.GetAlbumTarget( m_pMember->m_sLinkURI,
00361 m_pMember->m_sLinkName,
00362 m_sValue ) != NULL;
00363
00364 if ( m_bLink ) m_sLink = m_sValue;
00365
00366 return m_bLink;
00367 }
00368
00370
00371
00372 CAlbumFolder* CMetaItem::GetLinkTarget(BOOL bHTTP) const
00373 {
00374 if ( bHTTP )
00375 {
00376 if ( m_sLink.Find( _T("http://") ) == 0 )
00377 {
00378 ShellExecute( AfxGetMainWnd()->GetSafeHwnd(), _T("open"), m_sLink,
00379 NULL, NULL, SW_SHOWNORMAL );
00380 return NULL;
00381 }
00382 else if ( m_sLink.Find( _T("www.") ) == 0 )
00383 {
00384 ShellExecute( AfxGetMainWnd()->GetSafeHwnd(), _T("open"),
00385 _T("http://") + m_sLink, NULL, NULL, SW_SHOWNORMAL );
00386 return NULL;
00387 }
00388 }
00389
00390 if ( m_pMember == NULL || ! m_bLink ) return NULL;
00391 if ( m_pMember->m_sLinkURI.IsEmpty() ) return NULL;
00392 if ( m_pMember->m_sLinkName.IsEmpty() ) return NULL;
00393
00394 return LibraryFolders.GetAlbumTarget( m_pMember->m_sLinkURI,
00395 m_pMember->m_sLinkName,
00396 m_sLink );
00397 }