2 // This file is part of the aMule Project.
4 // Copyright (c) 2003-2008 aMule Team ( admin@amule.org / http://www.amule.org )
5 // Copyright (c) 2002 Merkur ( devs@emule-project.net / http://www.emule-project.net )
7 // Any parts of this program derived from the xMule, lMule or eMule project,
8 // or contributed by third-party developers are copyrighted by their
11 // This program is free software; you can redistribute it and/or modify
12 // it under the terms of the GNU General Public License as published by
13 // the Free Software Foundation; either version 2 of the License, or
14 // (at your option) any later version.
16 // This program is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 // GNU General Public License for more details.
21 // You should have received a copy of the GNU General Public License
22 // along with this program; if not, write to the Free Software
23 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 #include "ClientListCtrl.h"
28 #include <protocol/ed2k/ClientSoftware.h>
29 #include <common/MenuIDs.h>
33 #include "BarShader.h" // Needed for CBarShader
35 #include "ClientDetailDialog.h"
36 #include "ClientList.h"
37 #include "DataToText.h"
38 #ifdef ENABLE_IP2COUNTRY
39 #include "IP2Country.h" // Needed for IP2Country
41 #include "KnownFile.h"
42 #include "Preferences.h"
43 #include "updownclient.h"
44 #include "UploadQueue.h"
47 #include <wx/textdlg.h>
49 #include <wx/settings.h>
51 ////////////////////////////////////////////////////////////
54 int CompareVersions(const CUpDownClient
* client1
, const CUpDownClient
* client2
)
56 if (client1
->GetClientSoft() != client2
->GetClientSoft()) {
57 return client1
->GetSoftStr().Cmp(client2
->GetSoftStr());
60 if (client1
->GetVersion() != client2
->GetVersion()) {
61 return CmpAny(client1
->GetVersion(), client2
->GetVersion());
64 return client1
->GetClientModString().Cmp(client2
->GetClientModString());
68 ////////////////////////////////////////////////////////////
72 BEGIN_EVENT_TABLE( CClientListCtrl
, CMuleListCtrl
)
73 EVT_RIGHT_DOWN(CClientListCtrl::OnRightClick
)
74 EVT_LIST_ITEM_MIDDLE_CLICK(-1, CClientListCtrl::OnMiddleClick
)
76 EVT_MENU( MP_DETAIL
, CClientListCtrl::OnShowDetails
)
77 EVT_MENU( MP_ADDFRIEND
, CClientListCtrl::OnAddFriend
)
78 EVT_MENU( MP_SHOWLIST
, CClientListCtrl::OnViewFiles
)
79 EVT_MENU( MP_SENDMESSAGE
, CClientListCtrl::OnSendMessage
)
80 EVT_MENU( MP_UNBAN
, CClientListCtrl::OnUnbanClient
)
81 EVT_MENU_RANGE( MP_SWITCHCTRL_0
, MP_SWITCHCTRL_9
, CClientListCtrl::OnChangeView
)
85 #define m_imagelist theApp->amuledlg->m_imagelist
89 * This struct is used to keep track of the different view-types.
91 * Each view has a number of attributes, namely a title and serveral functions
92 * which are used by the CClientListCtrl class. This struct is used to store these
95 * Please note that none of the values are required, however for a fully functional
96 * view, it is nescesarry to specificy all of them.
100 //! The name of the view, this is used to load and save column-preferences.
103 //! Pointer to the initialization function.
104 void (*m_init
)(CClientListCtrl
*);
106 //! Pointer to the drawing function
107 void (*m_draw
)(CUpDownClient
*, int, wxDC
*, const wxRect
&);
109 //! Pointer to the sorting function.
110 MuleListCtrlCompare m_sort
;
114 //! This is the list of currently usable views, in the same order as the ViewType enum.
115 ClientListView g_listViews
[] =
117 //! None: This view does nothing at all.
125 //! Uploading: The clients currently being uploaded to.
128 CUploadingView::Initialize
,
129 CUploadingView::DrawCell
,
130 CUploadingView::SortProc
,
133 //! Queued: The clients currently queued for uploading.
136 CQueuedView::Initialize
,
137 CQueuedView::DrawCell
,
138 CQueuedView::SortProc
,
141 //! Clients The complete list of all known clients.
144 CClientsView::Initialize
,
145 CClientsView::DrawCell
,
146 CClientsView::SortProc
,
152 CClientListCtrl::CClientListCtrl( wxWindow
*parent
, wxWindowID winid
, const wxPoint
&pos
, const wxSize
&size
, long style
, const wxValidator
& validator
, const wxString
& name
)
154 CMuleListCtrl( parent
, winid
, pos
, size
, style
| wxLC_OWNERDRAW
, validator
, name
)
160 m_hilightBrush
= *(wxTheBrushList
->FindOrCreateBrush( CMuleColour(wxSYS_COLOUR_HIGHLIGHT
).Blend(125), wxSOLID
));
162 m_hilightUnfocusBrush
= *(wxTheBrushList
->FindOrCreateBrush( CMuleColour(wxSYS_COLOUR_BTNSHADOW
).Blend(125), wxSOLID
));
164 // We show the uploading-list initially
165 SetListView( vtUploading
);
169 CClientListCtrl::~CClientListCtrl()
175 ViewType
CClientListCtrl::GetListView()
181 void CClientListCtrl::SetListView( ViewType newView
)
183 if ( m_viewType
!= newView
) {
184 if (m_viewType
!= vtNone
) {
189 m_viewType
= newView
;
191 const ClientListView
& view
= g_listViews
[ (int)newView
];
193 // Initialize the selected view
198 SetTableName( view
.m_title
);
199 SetSortFunc( view
.m_sort
);
201 if (newView
!= vtNone
) {
208 void CClientListCtrl::ToggleView()
210 // Disallow toggling if the list is disabled
211 if ( m_viewType
== vtNone
) {
215 unsigned int view
= (int)m_viewType
+ 1;
217 if ( view
< itemsof(g_listViews
) ) {
218 SetListView( (ViewType
)(view
) );
220 SetListView( (ViewType
)(1) );
225 /////////////////////////////////////////////////////////////////////////////////////////////
226 void CClientListCtrl::OnRightClick(wxMouseEvent
& event
)
228 long index
= CheckSelection(event
);
230 if ( m_menu
== NULL
) {
233 bool validIP
= false;
234 bool isfriend
= false;
235 bool hasdisabledsharedfiles
= false;
237 // Check if the client is banned
239 CUpDownClient
*client
= reinterpret_cast<CUpDownClient
*>(GetItemData( index
));
241 banned
= client
->IsBanned();
242 validIP
= (client
->GetIP() != 0);
243 isfriend
= client
->IsFriend();
244 hasdisabledsharedfiles
= client
->HasDisabledSharedFiles();
247 m_menu
= new wxMenu(_("Clients"));
248 m_menu
->Append( MP_DETAIL
, _("Show &Details") );
249 m_menu
->Append( MP_ADDFRIEND
, isfriend
? _("Remove from friends") : _("Add to Friends") );
250 m_menu
->Append( MP_SHOWLIST
, _("View Files") );
251 m_menu
->Append( MP_SENDMESSAGE
, _("Send message") );
252 m_menu
->Append( MP_UNBAN
, _("Unban") );
254 m_menu
->AppendSeparator();
256 wxMenu
* view
= new wxMenu();
257 view
->Append( MP_SWITCHCTRL_0
+ 1, _("Show Uploads") );
258 view
->Append( MP_SWITCHCTRL_0
+ 2, _("Show Queue") );
259 view
->Append( MP_SWITCHCTRL_0
+ 3, _("Show Clients") );
261 view
->Enable( MP_SWITCHCTRL_0
+ (int)m_viewType
, false );
263 m_menu
->Append( 0, _("Select View"), view
);
265 m_menu
->Enable( MP_DETAIL
, index
> -1 );
266 m_menu
->Enable( MP_SHOWLIST
, index
> -1 );
268 m_menu
->Enable( MP_UNBAN
, banned
);
269 m_menu
->Enable( MP_SHOWLIST
, !hasdisabledsharedfiles
);
270 m_menu
->Enable( MP_ADDFRIEND
, validIP
);
271 m_menu
->Enable( MP_SENDMESSAGE
, validIP
);
273 PopupMenu( m_menu
, event
.GetPosition() );
282 void CClientListCtrl::OnMiddleClick(wxListEvent
& event
)
284 long index
= CheckSelection(event
);
287 CUpDownClient
*client
= reinterpret_cast<CUpDownClient
*>(GetItemData( index
));
289 CClientDetailDialog
dialog(this, client
);
296 void CClientListCtrl::OnChangeView( wxCommandEvent
& event
)
298 int view
= event
.GetId() - MP_SWITCHCTRL_0
;
300 SetListView( (ViewType
)view
);
304 void CClientListCtrl::OnAddFriend( wxCommandEvent
& WXUNUSED(event
) )
306 long index
= GetNextItem( -1, wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED
);
308 while ( index
!= -1 ) {
309 CUpDownClient
*client
= reinterpret_cast<CUpDownClient
*>(GetItemData( index
));
310 if (client
->IsFriend()) {
311 theApp
->amuledlg
->m_chatwnd
->RemoveFriend(client
->GetUserHash(), client
->GetIP(), client
->GetUserPort());
313 theApp
->amuledlg
->m_chatwnd
->AddFriend( client
);
315 index
= GetNextItem( index
, wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED
);
320 void CClientListCtrl::OnShowDetails( wxCommandEvent
& WXUNUSED(event
) )
322 long index
= GetNextItem( -1, wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED
);
325 CUpDownClient
*client
= reinterpret_cast<CUpDownClient
*>(GetItemData( index
));
326 CClientDetailDialog
dialog(this, client
);
332 void CClientListCtrl::OnViewFiles( wxCommandEvent
& WXUNUSED(event
) )
334 long index
= GetNextItem( -1, wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED
);
337 CUpDownClient
*client
= reinterpret_cast<CUpDownClient
*>(GetItemData( index
));
338 client
->RequestSharedFileList();
343 void CClientListCtrl::OnSendMessage( wxCommandEvent
& WXUNUSED(event
) )
345 long index
= GetNextItem( -1, wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED
);
348 CUpDownClient
*client
= reinterpret_cast<CUpDownClient
*>(GetItemData( index
));
350 // These values are cached, since calling wxGetTextFromUser will
351 // start an event-loop, in which the client may be deleted.
352 wxString userName
= client
->GetUserName();
353 uint64 userID
= GUI_ID(client
->GetIP(),client
->GetUserPort());
355 wxString message
= ::wxGetTextFromUser( _("Send message to user"), _("Message to send:") );
357 if (!message
.IsEmpty()) {
358 theApp
->amuledlg
->m_chatwnd
->SendMessage(message
, userName
, userID
);
364 void CClientListCtrl::OnUnbanClient( wxCommandEvent
& WXUNUSED(event
) )
366 long index
= GetNextItem( -1, wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED
);
369 CUpDownClient
*client
= reinterpret_cast<CUpDownClient
*>(GetItemData( index
));
370 if ( client
->IsBanned() ) {
377 void CClientListCtrl::InsertClient( CUpDownClient
* client
, ViewType view
)
379 wxCHECK_RET(client
, wxT("Attempted to add NULL client pointer."));
381 if ( ( m_viewType
!= view
) || ( view
== vtNone
) ) {
385 long index
= InsertItem( GetItemCount(), wxEmptyString
);
386 SetItemPtrData( index
, reinterpret_cast<wxUIntPtr
>(client
) );
389 myitem
.SetId( index
);
390 myitem
.SetBackgroundColour( CMuleColour(wxSYS_COLOUR_LISTBOX
) );
394 RefreshItem( index
);
398 void CClientListCtrl::RemoveClient( CUpDownClient
* client
, ViewType view
)
400 wxCHECK_RET(client
, wxT("Attempted to remove NULL client pointer."));
402 if ( ( m_viewType
!= view
) || ( view
== vtNone
) ) {
406 long index
= FindItem( -1, reinterpret_cast<wxUIntPtr
>(client
) );
414 void CClientListCtrl::UpdateClient( CUpDownClient
* client
, ViewType view
)
416 wxCHECK_RET(client
, wxT("Attempted to update NULL client pointer."));
418 if ( ( m_viewType
!= view
) || ( view
== vtNone
) ) {
422 if ( theApp
->amuledlg
->IsDialogVisible( CamuleDlg::DT_TRANSFER_WND
) ) {
423 // Visible lines, default to all because not all platforms support the GetVisibleLines function
424 long first
= 0, last
= GetItemCount();
425 long result
= FindItem( -1, reinterpret_cast<wxUIntPtr
>(client
) );
428 GetVisibleLines( &first
, &last
);
430 if ( result
>= first
&& result
<= last
) {
438 void CClientListCtrl::OnDrawItem( int item
, wxDC
* dc
, const wxRect
& rect
, const wxRect
& rectHL
, bool highlighted
)
440 // Don't do any drawing if we not being watched.
441 if ( !theApp
->amuledlg
|| !theApp
->amuledlg
->IsDialogVisible( CamuleDlg::DT_TRANSFER_WND
) ) {
447 dc
->SetBackground(m_hilightBrush
);
448 dc
->SetTextForeground( CMuleColour(wxSYS_COLOUR_HIGHLIGHTTEXT
) );
450 dc
->SetBackground(m_hilightUnfocusBrush
);
451 dc
->SetTextForeground( CMuleColour(wxSYS_COLOUR_HIGHLIGHTTEXT
));
454 CMuleColour colour
= GetFocus() ? m_hilightBrush
.GetColour() : m_hilightUnfocusBrush
.GetColour();
455 dc
->SetPen( *(wxThePenList
->FindOrCreatePen( colour
.Blend(65), 1, wxSOLID
) ));
457 dc
->SetBackground( *(wxTheBrushList
->FindOrCreateBrush( CMuleColour(wxSYS_COLOUR_LISTBOX
), wxSOLID
) ));
458 dc
->SetTextForeground( CMuleColour(wxSYS_COLOUR_WINDOWTEXT
) );
459 dc
->SetPen(*wxTRANSPARENT_PEN
);
462 dc
->SetBrush(dc
->GetBackground());
463 dc
->DrawRectangle(rectHL
);
464 dc
->SetPen(*wxTRANSPARENT_PEN
);
466 CUpDownClient
* client
= reinterpret_cast<CUpDownClient
*>(GetItemData(item
));
467 wxRect cur_rect
= rect
;
470 const ClientListView
& view
= g_listViews
[ (int)m_viewType
];
473 for ( int i
= 0; i
< GetColumnCount(); i
++ ) {
474 int width
= GetColumnWidth( i
);
476 cur_rect
.width
= width
- 8;
478 wxDCClipper
clipper( *dc
, cur_rect
);
480 view
.m_draw( client
, i
, dc
, cur_rect
);
488 wxString
CClientListCtrl::GetTTSText(unsigned item
) const
490 CUpDownClient
*client
= reinterpret_cast<CUpDownClient
*>(GetItemData( item
));
492 return client
->GetUserName();
496 /////////////////////////////////////////////////////////////////////////////////////////////
497 void CUploadingView::Initialize( CClientListCtrl
* list
)
499 list
->InsertColumn( 0, _("Username"), wxLIST_FORMAT_LEFT
, 150 );
500 list
->InsertColumn( 1, _("File"), wxLIST_FORMAT_LEFT
, 275 );
501 list
->InsertColumn( 2, _("Client Software"), wxLIST_FORMAT_LEFT
, 100 );
502 list
->InsertColumn( 3, _("Speed"), wxLIST_FORMAT_LEFT
, 60 );
503 list
->InsertColumn( 4, _("Transferred"), wxLIST_FORMAT_LEFT
, 65 );
504 list
->InsertColumn( 5, _("Waited"), wxLIST_FORMAT_LEFT
, 60 );
505 list
->InsertColumn( 6, _("Upload Time"), wxLIST_FORMAT_LEFT
, 60 );
506 list
->InsertColumn( 7, _("Status"), wxLIST_FORMAT_LEFT
, 110 );
507 list
->InsertColumn( 8, _("Obtained Parts"), wxLIST_FORMAT_LEFT
, 100 );
508 list
->InsertColumn( 9, _("Upload/Download"), wxLIST_FORMAT_LEFT
, 100 );
509 list
->InsertColumn( 10, _("Remote Status"), wxLIST_FORMAT_LEFT
, 100 );
511 // Insert any existing items on the list
512 const CClientPtrList
& uploading
= theApp
->uploadqueue
->GetUploadingList();
513 CClientPtrList::const_iterator it
= uploading
.begin();
514 for (; it
!= uploading
.end(); ++it
) {
515 list
->InsertClient( *it
, list
->GetListView() );
520 void CUploadingView::DrawCell( CUpDownClient
* client
, int column
, wxDC
* dc
, const wxRect
& rect
)
528 if ( client
->IsFriend() ) {
529 clientImage
= Client_Friend_Smiley
;
531 switch (client
->GetClientSoft()) {
533 clientImage
= Client_aMule_Smiley
;
536 case SO_NEW_MLDONKEY
:
537 case SO_NEW2_MLDONKEY
:
538 clientImage
= Client_mlDonkey_Smiley
;
541 case SO_EDONKEYHYBRID
:
542 // Maybe we would like to make different icons?
543 clientImage
= Client_eDonkeyHybrid_Smiley
;
546 clientImage
= Client_eMule_Smiley
;
549 clientImage
= Client_lphant_Smiley
;
552 case SO_NEW_SHAREAZA
:
553 case SO_NEW2_SHAREAZA
:
554 clientImage
= Client_Shareaza_Smiley
;
557 clientImage
= Client_xMule_Smiley
;
560 // cDonkey, Compat Unk
561 // No icon for those yet. Using the eMule one + '?'
562 clientImage
= Client_Unknown
;
567 m_imagelist
.Draw(clientImage
, *dc
, rect
.x
, rect
.y
+ 1,
568 wxIMAGELIST_DRAW_TRANSPARENT
);
570 if (client
->GetScoreRatio() > 1) {
571 // Has credits, draw the gold star
572 m_imagelist
.Draw(Client_CreditsYellow_Smiley
, *dc
, rect
.x
, rect
.y
+ 1,
573 wxIMAGELIST_DRAW_TRANSPARENT
);
574 } else if (client
->ExtProtocolAvailable()) {
575 // Ext protocol -> Draw the '+'
576 m_imagelist
.Draw(Client_ExtendedProtocol_Smiley
, *dc
, rect
.x
, rect
.y
+ 1,
577 wxIMAGELIST_DRAW_TRANSPARENT
);
580 if (client
->IsIdentified()) {
582 m_imagelist
.Draw(Client_SecIdent_Smiley
, *dc
, rect
.x
, rect
.y
+ 1,
583 wxIMAGELIST_DRAW_TRANSPARENT
);
584 } else if (client
->IsBadGuy()) {
586 m_imagelist
.Draw(Client_BadGuy_Smiley
, *dc
, rect
.x
, rect
.y
+ 1,
587 wxIMAGELIST_DRAW_TRANSPARENT
);
590 if (client
->HasObfuscatedConnectionBeenEstablished()) {
591 // the "¿" except it's a key
592 m_imagelist
.Draw(Client_Encryption_Smiley
, *dc
, rect
.x
, rect
.y
+ 1,
593 wxIMAGELIST_DRAW_TRANSPARENT
);
597 #ifdef ENABLE_IP2COUNTRY
599 const CountryData
& countrydata
=
600 theApp
->amuledlg
->m_IP2Country
->GetCountryData(client
->GetFullIP());
601 dc
->DrawBitmap(countrydata
.Flag
, rect
.x
+ 20, rect
.y
+ 5,
602 wxIMAGELIST_DRAW_TRANSPARENT
);
604 userName
<< countrydata
.Name
;
605 userName
<< wxT(" - ");
606 #endif // ENABLE_IP2COUNTRY
607 userName
<< client
->GetUserName();
608 dc
->DrawText(userName
, rect
.x
+ 40, rect
.y
+ 3);
614 if ( client
->GetUploadFile() ) {
615 buffer
= client
->GetUploadFile()->GetFileName().GetPrintable();
622 buffer
= client
->GetClientVerString();
626 buffer
= wxString::Format( wxT("%.1f"), client
->GetUploadDatarate() / 1024.0f
);
633 buffer
= CastItoXBytes(client
->GetSessionUp());
637 buffer
= CastSecondsToHM((client
->GetWaitTime())/1000);
641 buffer
= CastSecondsToHM((client
->GetUpStartTimeDelay())/1000);
645 switch ( client
->GetUploadState() ) {
647 buffer
= _("Connecting");
650 case US_WAITCALLBACK
:
651 buffer
= _("Connecting via server");
655 buffer
= wxT("<-- ");
656 buffer
.Append(_("Transferring"));
658 if (client
->GetDownloadState() == DS_DOWNLOADING
) {
659 buffer
.Append(wxT(" -->"));
663 case US_ONUPLOADQUEUE
:
664 buffer
= _("On Queue");
668 buffer
= _("Unknown");
673 if ( client
->GetUpPartCount() ) {
674 CUploadingView::DrawStatusBar( client
, dc
, rect
);
679 buffer
= CastItoXBytes( client
->GetUploadedTotal() ) +
680 wxT(" / ") + CastItoXBytes(client
->GetDownloadedTotal());
684 if ( client
->GetDownloadState() == DS_ONQUEUE
) {
685 if ( client
->IsRemoteQueueFull() ) {
686 buffer
= _("Queue Full");
688 if (client
->GetRemoteQueueRank()) {
689 buffer
= wxString::Format(_("QR: %u"), client
->GetRemoteQueueRank());
691 buffer
= _("Unknown");
694 } else if ( client
->GetDownloadState() == DS_DOWNLOADING
) {
695 buffer
+= wxString::Format( wxT("%.1f"), client
->GetKBpsDown() );
699 buffer
= _("Unknown");
704 dc
->DrawText( buffer
, rect
.x
, rect
.y
+ 3 );
708 int CUploadingView::SortProc(wxUIntPtr item1
, wxUIntPtr item2
, long sortData
)
710 CUpDownClient
* client1
= (CUpDownClient
*)item1
;
711 CUpDownClient
* client2
= (CUpDownClient
*)item2
;
713 // Sorting ascending or decending
714 int mode
= (sortData
& CMuleListCtrl::SORT_DES
) ? -1 : 1;
716 switch (sortData
& CMuleListCtrl::COLUMN_MASK
) {
718 case 0: return mode
* client1
->GetUserName().CmpNoCase( client2
->GetUserName() );
721 // Sort by requested file
723 const CKnownFile
* file1
= client1
->GetUploadFile();
724 const CKnownFile
* file2
= client2
->GetUploadFile();
726 if ( file1
&& file2
) {
727 return mode
* CmpAny(file1
->GetFileName(), file2
->GetFileName());
730 return mode
* CmpAny( file1
, file2
);
733 // Sort by client software
734 case 2: return mode
* CompareVersions(client1
, client2
);
737 case 3: return mode
* CmpAny( client1
->GetUploadDatarate(), client2
->GetUploadDatarate() );
739 // Sort by transferred
740 case 4: return mode
* CmpAny( client1
->GetSessionUp(), client2
->GetSessionUp() );
743 case 5: return mode
* CmpAny( client1
->GetWaitTime(), client2
->GetWaitTime() );
745 // Sort by upload time
746 case 6: return mode
* CmpAny( client1
->GetUpStartTimeDelay(), client2
->GetUpStartTimeDelay() );
749 case 7: return mode
* CmpAny( client1
->GetUploadState(), client2
->GetUploadState() );
752 case 8: return mode
* CmpAny( client1
->GetUpPartCount(), client2
->GetUpPartCount() );
755 case 9: return mode
* CmpAny( client2
->GetDownloadedTotal(), client1
->GetDownloadedTotal() );
757 // Sort by remote rank
758 case 10: return mode
* CmpAny( client2
->GetRemoteQueueRank(), client1
->GetRemoteQueueRank() );
765 static const CMuleColour
crUnavailable(240, 240, 240);
766 static const CMuleColour
crFlatUnavailable(224, 224, 224);
768 static const CMuleColour
crAvailable(104, 104, 104);
769 static const CMuleColour
crFlatAvailable(0, 0, 0);
771 void CUploadingView::DrawStatusBar( CUpDownClient
* client
, wxDC
* dc
, const wxRect
& rect1
)
777 wxPen old_pen
= dc
->GetPen();
778 wxBrush old_brush
= dc
->GetBrush();
779 bool bFlat
= thePrefs::UseFlatBar();
781 wxRect barRect
= rect
;
782 if (!bFlat
) { // round bar has a black border, the bar itself is 1 pixel less on each border
788 static CBarShader
s_StatusBar(16);
790 uint32 partCount
= client
->GetUpPartCount();
792 // Seems the partfile in the client object is not necessarily valid when bar is drawn for the first time.
793 // Keep it simple and make all parts same size.
794 s_StatusBar
.SetFileSize(partCount
* PARTSIZE
);
795 s_StatusBar
.SetHeight(barRect
.height
);
796 s_StatusBar
.SetWidth(barRect
.width
);
797 s_StatusBar
.Set3dDepth( thePrefs::Get3DDepth() );
800 for ( uint64 i
= 0; i
< partCount
; i
++ ) {
801 uint64 uStart
= PARTSIZE
* i
;
802 uEnd
= uStart
+ PARTSIZE
- 1;
804 s_StatusBar
.FillRange(uStart
, uEnd
, client
->IsUpPartAvailable(i
) ? (bFlat
? crFlatAvailable
: crAvailable
) : (bFlat
? crFlatUnavailable
: crUnavailable
));
806 // fill the rest (if partStatus is empty)
807 s_StatusBar
.FillRange(uEnd
+ 1, partCount
* PARTSIZE
- 1, bFlat
? crFlatUnavailable
: crUnavailable
);
808 s_StatusBar
.Draw(dc
, barRect
.x
, barRect
.y
, bFlat
);
812 dc
->SetPen( *wxBLACK_PEN
);
813 dc
->SetBrush( *wxTRANSPARENT_BRUSH
);
814 dc
->DrawRectangle(rect
);
817 dc
->SetPen( old_pen
);
818 dc
->SetBrush( old_brush
);
822 /////////////////////////////////////////////////////////////////////////////////////////////
823 void CQueuedView::Initialize( CClientListCtrl
* list
)
825 list
->InsertColumn( 0, _("Username"), wxLIST_FORMAT_LEFT
, 150 );
826 list
->InsertColumn( 1, _("File"), wxLIST_FORMAT_LEFT
, 275 );
827 list
->InsertColumn( 2, _("Client Software"), wxLIST_FORMAT_LEFT
, 100 );
828 list
->InsertColumn( 3, _("File Priority"), wxLIST_FORMAT_LEFT
, 110 );
829 list
->InsertColumn( 4, _("Rating"), wxLIST_FORMAT_LEFT
, 60 );
830 list
->InsertColumn( 5, _("Score"), wxLIST_FORMAT_LEFT
, 60 );
831 list
->InsertColumn( 6, _("Asked"), wxLIST_FORMAT_LEFT
, 60 );
832 list
->InsertColumn( 7, _("Last Seen"), wxLIST_FORMAT_LEFT
, 110 );
833 list
->InsertColumn( 8, _("Entered Queue"), wxLIST_FORMAT_LEFT
, 110 );
834 list
->InsertColumn( 9, _("Banned"), wxLIST_FORMAT_LEFT
, 60 );
835 list
->InsertColumn( 10, _("Obtained Parts"), wxLIST_FORMAT_LEFT
, 100 );
837 // Insert any existing items on the list
838 // Insert any existing items on the list
839 const CClientPtrList
& uploading
= theApp
->uploadqueue
->GetWaitingList();
840 CClientPtrList::const_iterator it
= uploading
.begin();
841 for (; it
!= uploading
.end(); ++it
) {
842 list
->InsertClient( *it
, list
->GetListView() );
847 void CQueuedView::DrawCell( CUpDownClient
* client
, int column
, wxDC
* dc
, const wxRect
& rect
)
852 // These 3 are the same for both lists
856 CUploadingView::DrawCell( client
, column
, dc
, rect
);
860 if ( client
->GetUploadFile() ) {
861 buffer
= PriorityToStr( client
->GetUploadFile()->GetUpPriority(), false );
863 buffer
= _("Unknown");
869 buffer
= wxString::Format( wxT("%.1f"), (float)client
->GetScore(false,false,true) );
873 if ( client
->HasLowID() ) {
874 buffer
= wxString::Format( wxT("%i %s"), client
->GetScore(false), _("LowID") );
876 buffer
= wxString::Format(wxT("%i"),client
->GetScore(false));
881 buffer
= wxString::Format( wxT("%i"), client
->GetAskedCount() );
886 buffer
= CastSecondsToHM((::GetTickCount() - client
->GetLastUpRequest())/1000);
890 buffer
= CastSecondsToHM((::GetTickCount() - client
->GetWaitStartTime())/1000);
894 buffer
= CastSecondsToHM(client
->GetLastUpRequest()/1000);
898 buffer
= CastSecondsToHM(client
->GetWaitStartTime()/1000);
902 if ( client
->IsBanned() ) {
911 if ( client
->GetUpPartCount() ) {
912 CUploadingView::DrawStatusBar( client
, dc
, rect
);
918 dc
->DrawText( buffer
, rect
.x
, rect
.y
+ 3 );
922 int CQueuedView::SortProc(wxUIntPtr item1
, wxUIntPtr item2
, long sortData
)
924 CUpDownClient
* client1
= (CUpDownClient
*)item1
;
925 CUpDownClient
* client2
= (CUpDownClient
*)item2
;
927 // Ascending or decending?
928 int mode
= (sortData
& CMuleListCtrl::SORT_DES
) ? -1 : 1;
930 switch (sortData
& CMuleListCtrl::COLUMN_MASK
) {
932 case 0: return mode
* client1
->GetUserName().CmpNoCase( client2
->GetUserName() );
936 const CKnownFile
* file1
= client1
->GetUploadFile();
937 const CKnownFile
* file2
= client2
->GetUploadFile();
939 if ( file1
&& file2
) {
940 return mode
* CmpAny(file1
->GetFileName(), file2
->GetFileName());
943 // Place files with filenames on top
944 return -mode
* CmpAny( file1
, file2
);
947 // Sort by client software
948 case 2: return mode
* CompareVersions(client1
, client2
);
950 // Sort by file upload-priority
952 const CKnownFile
* file1
= client1
->GetUploadFile();
953 const CKnownFile
* file2
= client2
->GetUploadFile();
955 if ( file1
&& file2
) {
956 int8 prioA
= file1
->GetUpPriority();
957 int8 prioB
= file2
->GetUpPriority();
959 // Work-around for PR_VERYLOW which has value 4. See KnownFile.h for that stupidity ...
960 return mode
* CmpAny( ( prioA
!= PR_VERYLOW
? prioA
: -1 ), ( prioB
!= PR_VERYLOW
? prioB
: -1 ) );
963 // Place files with priorities on top
964 return -mode
* CmpAny( file1
, file2
);
968 case 4: return mode
* CmpAny( client1
->GetScore(false,false,true), client2
->GetScore(false,false,true) );
971 case 5: return mode
* CmpAny( client1
->GetScore(false), client2
->GetScore(false) );
973 // Sort by Asked count
974 case 6: return mode
* CmpAny( client1
->GetAskedCount(), client2
->GetAskedCount() );
977 case 7: return mode
* CmpAny( client1
->GetLastUpRequest(), client2
->GetLastUpRequest() );
979 // Sort by entered time
980 case 8: return mode
* CmpAny( client1
->GetWaitStartTime(), client2
->GetWaitStartTime() );
983 case 9: return mode
* CmpAny( client1
->IsBanned(), client2
->IsBanned() );
990 /////////////////////////////////////////////////////////////////////////////////////////////
991 void CClientsView::Initialize( CClientListCtrl
* list
)
993 list
->InsertColumn( 0, _("Username"), wxLIST_FORMAT_LEFT
, 150 );
994 list
->InsertColumn( 1, _("Upload Status"), wxLIST_FORMAT_LEFT
, 150 );
995 list
->InsertColumn( 2, _("Transferred Up"), wxLIST_FORMAT_LEFT
, 150 );
996 list
->InsertColumn( 3, _("Download Status"), wxLIST_FORMAT_LEFT
, 150 );
997 list
->InsertColumn( 4, _("Transferred Down"), wxLIST_FORMAT_LEFT
, 150 );
998 list
->InsertColumn( 5, _("Client Software"), wxLIST_FORMAT_LEFT
, 150 );
999 list
->InsertColumn( 6, _("Connected"), wxLIST_FORMAT_LEFT
, 150 );
1000 list
->InsertColumn( 7, _("Userhash"), wxLIST_FORMAT_LEFT
, 150 );
1001 list
->InsertColumn( 8, _("Encrypted"), wxLIST_FORMAT_LEFT
, 100 );
1002 list
->InsertColumn( 9, _("Hide shared files"), wxLIST_FORMAT_LEFT
, 100 );
1004 const CClientList::IDMap
& clist
= theApp
->clientlist
->GetClientList();
1005 CClientList::IDMap::const_iterator it
= clist
.begin();
1007 for ( ; it
!= clist
.end(); ++it
) {
1008 list
->InsertClient( it
->second
, list
->GetListView() );
1013 void CClientsView::DrawCell( CUpDownClient
* client
, int column
, wxDC
* dc
, const wxRect
& rect
)
1019 CUploadingView::DrawCell( client
, column
, dc
, rect
);
1023 CUploadingView::DrawCell( client
, 7, dc
, rect
);
1027 buffer
= CastItoXBytes( client
->GetUploadedTotal() );
1032 buffer
= DownloadStateToStr( client
->GetDownloadState(),
1033 client
->IsRemoteQueueFull() );
1037 buffer
= CastItoXBytes( client
->GetDownloadedTotal() );
1041 buffer
= client
->GetClientVerString();
1045 if ( client
->IsConnected() ) {
1054 buffer
= client
->GetUserHash().Encode();
1058 buffer
= client
->HasObfuscatedConnectionBeenEstablished() ?
1063 buffer
= client
->GetUserName().IsEmpty() ?
1065 (client
->HasDisabledSharedFiles() ? _("Yes") : _("No"));
1069 dc
->DrawText( buffer
, rect
.x
, rect
.y
+ 3 );
1073 int CClientsView::SortProc(wxUIntPtr item1
, wxUIntPtr item2
, long sortData
)
1075 CUpDownClient
* client1
= (CUpDownClient
*)item1
;
1076 CUpDownClient
* client2
= (CUpDownClient
*)item2
;
1078 // Ascending or decending?
1079 int mode
= (sortData
& CMuleListCtrl::SORT_DES
) ? -1 : 1;
1081 switch (sortData
& CMuleListCtrl::COLUMN_MASK
) {
1083 case 0: return mode
* client1
->GetUserName().CmpNoCase( client2
->GetUserName() );
1085 // Sort by Uploading-state
1086 case 1: return mode
* CmpAny( client1
->GetUploadState(), client2
->GetUploadState() );
1088 // Sort by data-uploaded
1090 return mode
* CmpAny( client1
->GetUploadedTotal(), client2
->GetUploadedTotal() );
1092 // Sort by Downloading-state
1094 if( client1
->GetDownloadState() == client2
->GetDownloadState() ){
1095 if( client1
->IsRemoteQueueFull() && client2
->IsRemoteQueueFull() ) {
1097 } else if( client1
->IsRemoteQueueFull() ) {
1099 } else if( client2
->IsRemoteQueueFull() ) {
1105 return mode
* CmpAny( client1
->GetDownloadState(), client2
->GetDownloadState() );
1107 // Sort by data downloaded
1109 return mode
* CmpAny( client1
->GetDownloadedTotal(), client2
->GetDownloadedTotal() );
1111 // Sort by client-software
1112 case 5: return mode
* CompareVersions(client1
, client2
);
1114 // Sort by connection
1115 case 6: return mode
* CmpAny( client1
->IsConnected(), client2
->IsConnected() );
1117 // Sort by user-hash
1118 case 7: return mode
* CmpAny( client1
->GetUserHash(), client2
->GetUserHash() );
1120 // Sort by Obfuscation state
1121 case 8: return mode
* CmpAny( client2
->HasObfuscatedConnectionBeenEstablished(), client1
->HasObfuscatedConnectionBeenEstablished() );
1123 // Sort by Shared Files DISabled
1124 case 9: return mode
* CmpAny( client2
->HasDisabledSharedFiles(), client1
->HasDisabledSharedFiles() );
1131 // File_checked_for_headers