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>
34 #include "ClientDetailDialog.h"
35 #include "ClientList.h"
37 #include "DataToText.h"
38 #ifdef ENABLE_IP2COUNTRY
39 #include "IP2Country.h" // Needed for IP2Country
41 #include "KnownFile.h"
42 #include "updownclient.h"
43 #include "UploadQueue.h"
46 #include <wx/textdlg.h>
48 #include <wx/settings.h>
50 ////////////////////////////////////////////////////////////
53 int CompareVersions(const CUpDownClient
* client1
, const CUpDownClient
* client2
)
55 if (client1
->GetClientSoft() != client2
->GetClientSoft()) {
56 return client1
->GetSoftStr().Cmp(client2
->GetSoftStr());
59 if (client1
->GetVersion() != client2
->GetVersion()) {
60 return CmpAny(client1
->GetVersion(), client2
->GetVersion());
63 return client1
->GetClientModString().Cmp(client2
->GetClientModString());
67 ////////////////////////////////////////////////////////////
71 BEGIN_EVENT_TABLE( CClientListCtrl
, CMuleListCtrl
)
72 EVT_RIGHT_DOWN(CClientListCtrl::OnRightClick
)
73 EVT_LIST_ITEM_MIDDLE_CLICK(-1, CClientListCtrl::OnMiddleClick
)
75 EVT_MENU( MP_DETAIL
, CClientListCtrl::OnShowDetails
)
76 EVT_MENU( MP_ADDFRIEND
, CClientListCtrl::OnAddFriend
)
77 EVT_MENU( MP_SHOWLIST
, CClientListCtrl::OnViewFiles
)
78 EVT_MENU( MP_SENDMESSAGE
, CClientListCtrl::OnSendMessage
)
79 EVT_MENU( MP_UNBAN
, CClientListCtrl::OnUnbanClient
)
80 EVT_MENU_RANGE( MP_SWITCHCTRL_0
, MP_SWITCHCTRL_9
, CClientListCtrl::OnChangeView
)
84 #define m_imagelist theApp->amuledlg->m_imagelist
88 * This struct is used to keep track of the different view-types.
90 * Each view has a number of attributes, namely a title and serveral functions
91 * which are used by the CClientListCtrl class. This struct is used to store these
94 * Please note that none of the values are required, however for a fully functional
95 * view, it is nescesarry to specificy all of them.
99 //! The name of the view, this is used to load and save column-preferences.
102 //! Pointer to the initialization function.
103 void (*m_init
)(CClientListCtrl
*);
105 //! Pointer to the drawing function
106 void (*m_draw
)(CUpDownClient
*, int, wxDC
*, const wxRect
&);
108 //! Pointer to the sorting function.
109 MuleListCtrlCompare m_sort
;
113 //! This is the list of currently usable views, in the same order as the ViewType enum.
114 ClientListView g_listViews
[] =
116 //! None: This view does nothing at all.
124 //! Uploading: The clients currently being uploaded to.
127 CUploadingView::Initialize
,
128 CUploadingView::DrawCell
,
129 CUploadingView::SortProc
,
132 //! Queued: The clients currently queued for uploading.
135 CQueuedView::Initialize
,
136 CQueuedView::DrawCell
,
137 CQueuedView::SortProc
,
140 //! Clients The complete list of all known clients.
143 CClientsView::Initialize
,
144 CClientsView::DrawCell
,
145 CClientsView::SortProc
,
151 CClientListCtrl::CClientListCtrl( wxWindow
*parent
, wxWindowID winid
, const wxPoint
&pos
, const wxSize
&size
, long style
, const wxValidator
& validator
, const wxString
& name
)
153 CMuleListCtrl( parent
, winid
, pos
, size
, style
| wxLC_OWNERDRAW
, validator
, name
)
159 wxColour col
= SYSCOLOR( wxSYS_COLOUR_HIGHLIGHT
);
160 m_hilightBrush
= new wxBrush( BLEND( col
, 125), wxSOLID
);
162 col
= SYSCOLOR( wxSYS_COLOUR_BTNSHADOW
);
163 m_hilightUnfocusBrush
= new wxBrush( BLEND( col
, 125), wxSOLID
);
166 // We show the uploading-list initially
167 SetListView( vtUploading
);
171 CClientListCtrl::~CClientListCtrl()
173 delete m_hilightBrush
;
174 delete m_hilightUnfocusBrush
;
178 ViewType
CClientListCtrl::GetListView()
184 void CClientListCtrl::SetListView( ViewType newView
)
186 if ( m_viewType
!= newView
) {
187 if (m_viewType
!= vtNone
) {
192 m_viewType
= newView
;
194 const ClientListView
& view
= g_listViews
[ (int)newView
];
196 // Initialize the selected view
201 SetTableName( view
.m_title
);
202 SetSortFunc( view
.m_sort
);
204 if (newView
!= vtNone
) {
211 void CClientListCtrl::ToggleView()
213 // Disallow toggling if the list is disabled
214 if ( m_viewType
== vtNone
) {
218 unsigned int view
= (int)m_viewType
+ 1;
220 if ( view
< itemsof(g_listViews
) ) {
221 SetListView( (ViewType
)(view
) );
223 SetListView( (ViewType
)(1) );
228 /////////////////////////////////////////////////////////////////////////////////////////////
229 void CClientListCtrl::OnRightClick(wxMouseEvent
& event
)
231 long index
= CheckSelection(event
);
233 if ( m_menu
== NULL
) {
236 bool validIP
= false;
237 bool isfriend
= false;
238 bool hasdisabledsharedfiles
= false;
240 // Check if the client is banned
242 CUpDownClient
*client
= reinterpret_cast<CUpDownClient
*>(GetItemData( index
));
244 banned
= client
->IsBanned();
245 validIP
= (client
->GetIP() != 0);
246 isfriend
= client
->IsFriend();
247 hasdisabledsharedfiles
= client
->HasDisabledSharedFiles();
250 m_menu
= new wxMenu(_("Clients"));
251 m_menu
->Append( MP_DETAIL
, _("Show &Details") );
252 m_menu
->Append( MP_ADDFRIEND
, isfriend
? _("Remove from friends") : _("Add to Friends") );
253 m_menu
->Append( MP_SHOWLIST
, _("View Files") );
254 m_menu
->Append( MP_SENDMESSAGE
, _("Send message") );
255 m_menu
->Append( MP_UNBAN
, _("Unban") );
257 m_menu
->AppendSeparator();
259 wxMenu
* view
= new wxMenu();
260 view
->Append( MP_SWITCHCTRL_0
+ 1, _("Show Uploads") );
261 view
->Append( MP_SWITCHCTRL_0
+ 2, _("Show Queue") );
262 view
->Append( MP_SWITCHCTRL_0
+ 3, _("Show Clients") );
264 view
->Enable( MP_SWITCHCTRL_0
+ (int)m_viewType
, false );
266 m_menu
->Append( 0, _("Select View"), view
);
268 m_menu
->Enable( MP_DETAIL
, index
> -1 );
269 m_menu
->Enable( MP_SHOWLIST
, index
> -1 );
271 m_menu
->Enable( MP_UNBAN
, banned
);
272 m_menu
->Enable( MP_SHOWLIST
, !hasdisabledsharedfiles
);
273 m_menu
->Enable( MP_ADDFRIEND
, validIP
);
274 m_menu
->Enable( MP_SENDMESSAGE
, validIP
);
276 PopupMenu( m_menu
, event
.GetPosition() );
285 void CClientListCtrl::OnMiddleClick(wxListEvent
& event
)
287 long index
= CheckSelection(event
);
290 CUpDownClient
*client
= reinterpret_cast<CUpDownClient
*>(GetItemData( index
));
292 CClientDetailDialog
dialog(this, client
);
299 void CClientListCtrl::OnChangeView( wxCommandEvent
& event
)
301 int view
= event
.GetId() - MP_SWITCHCTRL_0
;
303 SetListView( (ViewType
)view
);
307 void CClientListCtrl::OnAddFriend( wxCommandEvent
& WXUNUSED(event
) )
309 long index
= GetNextItem( -1, wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED
);
311 while ( index
!= -1 ) {
312 CUpDownClient
*client
= reinterpret_cast<CUpDownClient
*>(GetItemData( index
));
313 if (client
->IsFriend()) {
314 theApp
->amuledlg
->m_chatwnd
->RemoveFriend(client
->GetUserHash(), client
->GetIP(), client
->GetUserPort());
316 theApp
->amuledlg
->m_chatwnd
->AddFriend( client
);
318 index
= GetNextItem( index
, wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED
);
323 void CClientListCtrl::OnShowDetails( wxCommandEvent
& WXUNUSED(event
) )
325 long index
= GetNextItem( -1, wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED
);
328 CUpDownClient
*client
= reinterpret_cast<CUpDownClient
*>(GetItemData( index
));
329 CClientDetailDialog
dialog(this, client
);
335 void CClientListCtrl::OnViewFiles( wxCommandEvent
& WXUNUSED(event
) )
337 long index
= GetNextItem( -1, wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED
);
340 CUpDownClient
*client
= reinterpret_cast<CUpDownClient
*>(GetItemData( index
));
341 client
->RequestSharedFileList();
346 void CClientListCtrl::OnSendMessage( wxCommandEvent
& WXUNUSED(event
) )
348 long index
= GetNextItem( -1, wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED
);
351 CUpDownClient
*client
= reinterpret_cast<CUpDownClient
*>(GetItemData( index
));
353 // These values are cached, since calling wxGetTextFromUser will
354 // start an event-loop, in which the client may be deleted.
355 wxString userName
= client
->GetUserName();
356 uint64 userID
= GUI_ID(client
->GetIP(),client
->GetUserPort());
358 wxString message
= ::wxGetTextFromUser( _("Send message to user"), _("Message to send:") );
360 if (!message
.IsEmpty()) {
361 theApp
->amuledlg
->m_chatwnd
->SendMessage(message
, userName
, userID
);
367 void CClientListCtrl::OnUnbanClient( wxCommandEvent
& WXUNUSED(event
) )
369 long index
= GetNextItem( -1, wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED
);
372 CUpDownClient
*client
= reinterpret_cast<CUpDownClient
*>(GetItemData( index
));
373 if ( client
->IsBanned() ) {
380 void CClientListCtrl::InsertClient( CUpDownClient
* client
, ViewType view
)
382 wxCHECK_RET(client
, wxT("Attempted to add NULL client pointer."));
384 if ( ( m_viewType
!= view
) || ( view
== vtNone
) ) {
388 long index
= InsertItem( GetItemCount(), wxEmptyString
);
389 SetItemPtrData( index
, reinterpret_cast<wxUIntPtr
>(client
) );
392 myitem
.SetId( index
);
393 myitem
.SetBackgroundColour( SYSCOLOR(wxSYS_COLOUR_LISTBOX
) );
397 RefreshItem( index
);
401 void CClientListCtrl::RemoveClient( CUpDownClient
* client
, ViewType view
)
403 wxCHECK_RET(client
, wxT("Attempted to remove NULL client pointer."));
405 if ( ( m_viewType
!= view
) || ( view
== vtNone
) ) {
409 long index
= FindItem( -1, reinterpret_cast<wxUIntPtr
>(client
) );
417 void CClientListCtrl::UpdateClient( CUpDownClient
* client
, ViewType view
)
419 wxCHECK_RET(client
, wxT("Attempted to update NULL client pointer."));
421 if ( ( m_viewType
!= view
) || ( view
== vtNone
) ) {
425 if ( theApp
->amuledlg
->IsDialogVisible( CamuleDlg::DT_TRANSFER_WND
) ) {
426 // Visible lines, default to all because not all platforms support the GetVisibleLines function
427 long first
= 0, last
= GetItemCount();
428 long result
= FindItem( -1, reinterpret_cast<wxUIntPtr
>(client
) );
431 GetVisibleLines( &first
, &last
);
433 if ( result
>= first
&& result
<= last
) {
441 void CClientListCtrl::OnDrawItem( int item
, wxDC
* dc
, const wxRect
& rect
, const wxRect
& rectHL
, bool highlighted
)
443 // Don't do any drawing if we not being watched.
444 if ( !theApp
->amuledlg
|| !theApp
->amuledlg
->IsDialogVisible( CamuleDlg::DT_TRANSFER_WND
) ) {
450 dc
->SetBackground(*m_hilightBrush
);
451 dc
->SetTextForeground( SYSCOLOR(wxSYS_COLOUR_HIGHLIGHTTEXT
) );
453 dc
->SetBackground(*m_hilightUnfocusBrush
);
454 dc
->SetTextForeground( SYSCOLOR(wxSYS_COLOUR_HIGHLIGHTTEXT
));
457 wxColour colour
= GetFocus() ? m_hilightBrush
->GetColour() : m_hilightUnfocusBrush
->GetColour();
458 dc
->SetPen( wxPen( BLEND(colour
, 65), 1, wxSOLID
) );
460 dc
->SetBackground( wxBrush( SYSCOLOR(wxSYS_COLOUR_LISTBOX
), wxSOLID
) );
461 dc
->SetTextForeground( SYSCOLOR(wxSYS_COLOUR_WINDOWTEXT
) );
462 dc
->SetPen(*wxTRANSPARENT_PEN
);
465 dc
->SetBrush(dc
->GetBackground());
466 dc
->DrawRectangle(rectHL
);
467 dc
->SetPen(*wxTRANSPARENT_PEN
);
469 CUpDownClient
* client
= reinterpret_cast<CUpDownClient
*>(GetItemData(item
));
470 wxRect cur_rect
= rect
;
473 const ClientListView
& view
= g_listViews
[ (int)m_viewType
];
476 for ( int i
= 0; i
< GetColumnCount(); i
++ ) {
477 int width
= GetColumnWidth( i
);
479 cur_rect
.width
= width
- 8;
481 wxDCClipper
clipper( *dc
, cur_rect
);
483 view
.m_draw( client
, i
, dc
, cur_rect
);
491 wxString
CClientListCtrl::GetTTSText(unsigned item
) const
493 CUpDownClient
*client
= reinterpret_cast<CUpDownClient
*>(GetItemData( item
));
495 return client
->GetUserName();
499 /////////////////////////////////////////////////////////////////////////////////////////////
500 void CUploadingView::Initialize( CClientListCtrl
* list
)
502 list
->InsertColumn( 0, _("Username"), wxLIST_FORMAT_LEFT
, 150 );
503 list
->InsertColumn( 1, _("File"), wxLIST_FORMAT_LEFT
, 275 );
504 list
->InsertColumn( 2, _("Client Software"), wxLIST_FORMAT_LEFT
, 100 );
505 list
->InsertColumn( 3, _("Speed"), wxLIST_FORMAT_LEFT
, 60 );
506 list
->InsertColumn( 4, _("Transferred"), wxLIST_FORMAT_LEFT
, 65 );
507 list
->InsertColumn( 5, _("Waited"), wxLIST_FORMAT_LEFT
, 60 );
508 list
->InsertColumn( 6, _("Upload Time"), wxLIST_FORMAT_LEFT
, 60 );
509 list
->InsertColumn( 7, _("Status"), wxLIST_FORMAT_LEFT
, 110 );
510 list
->InsertColumn( 8, _("Obtained Parts"), wxLIST_FORMAT_LEFT
, 100 );
511 list
->InsertColumn( 9, _("Upload/Download"), wxLIST_FORMAT_LEFT
, 100 );
512 list
->InsertColumn( 10, _("Remote Status"), wxLIST_FORMAT_LEFT
, 100 );
514 // Insert any existing items on the list
515 const CClientPtrList
& uploading
= theApp
->uploadqueue
->GetUploadingList();
516 CClientPtrList::const_iterator it
= uploading
.begin();
517 for (; it
!= uploading
.end(); ++it
) {
518 list
->InsertClient( *it
, list
->GetListView() );
523 void CUploadingView::DrawCell( CUpDownClient
* client
, int column
, wxDC
* dc
, const wxRect
& rect
)
531 if ( client
->IsFriend() ) {
532 clientImage
= Client_Friend_Smiley
;
534 switch (client
->GetClientSoft()) {
536 clientImage
= Client_aMule_Smiley
;
539 case SO_NEW_MLDONKEY
:
540 case SO_NEW2_MLDONKEY
:
541 clientImage
= Client_mlDonkey_Smiley
;
544 case SO_EDONKEYHYBRID
:
545 // Maybe we would like to make different icons?
546 clientImage
= Client_eDonkeyHybrid_Smiley
;
549 clientImage
= Client_eMule_Smiley
;
552 clientImage
= Client_lphant_Smiley
;
555 case SO_NEW_SHAREAZA
:
556 case SO_NEW2_SHAREAZA
:
557 clientImage
= Client_Shareaza_Smiley
;
560 clientImage
= Client_xMule_Smiley
;
563 // cDonkey, Compat Unk
564 // No icon for those yet. Using the eMule one + '?'
565 clientImage
= Client_Unknown
;
570 m_imagelist
.Draw(clientImage
, *dc
, rect
.x
, rect
.y
+ 1,
571 wxIMAGELIST_DRAW_TRANSPARENT
);
573 if (client
->GetScoreRatio() > 1) {
574 // Has credits, draw the gold star
575 m_imagelist
.Draw(Client_CreditsYellow_Smiley
, *dc
, rect
.x
, rect
.y
+ 1,
576 wxIMAGELIST_DRAW_TRANSPARENT
);
577 } else if (client
->ExtProtocolAvailable()) {
578 // Ext protocol -> Draw the '+'
579 m_imagelist
.Draw(Client_ExtendedProtocol_Smiley
, *dc
, rect
.x
, rect
.y
+ 1,
580 wxIMAGELIST_DRAW_TRANSPARENT
);
583 if (client
->IsIdentified()) {
585 m_imagelist
.Draw(Client_SecIdent_Smiley
, *dc
, rect
.x
, rect
.y
+ 1,
586 wxIMAGELIST_DRAW_TRANSPARENT
);
587 } else if (client
->IsBadGuy()) {
589 m_imagelist
.Draw(Client_BadGuy_Smiley
, *dc
, rect
.x
, rect
.y
+ 1,
590 wxIMAGELIST_DRAW_TRANSPARENT
);
593 if (client
->HasObfuscatedConnectionBeenEstablished()) {
594 // the "¿" except it's a key
595 m_imagelist
.Draw(Client_Encryption_Smiley
, *dc
, rect
.x
, rect
.y
+ 1,
596 wxIMAGELIST_DRAW_TRANSPARENT
);
600 #ifdef ENABLE_IP2COUNTRY
602 const CountryData
& countrydata
=
603 theApp
->amuledlg
->m_IP2Country
->GetCountryData(client
->GetFullIP());
604 dc
->DrawBitmap(countrydata
.Flag
, rect
.x
+ 20, rect
.y
+ 5,
605 wxIMAGELIST_DRAW_TRANSPARENT
);
607 userName
<< countrydata
.Name
;
608 userName
<< wxT(" - ");
609 #endif // ENABLE_IP2COUNTRY
610 userName
<< client
->GetUserName();
611 dc
->DrawText(userName
, rect
.x
+ 40, rect
.y
+ 3);
617 if ( client
->GetUploadFile() ) {
618 buffer
= client
->GetUploadFile()->GetFileName().GetPrintable();
625 buffer
= client
->GetClientVerString();
629 buffer
= wxString::Format( wxT("%.1f"), client
->GetUploadDatarate() / 1024.0f
);
636 buffer
= CastItoXBytes(client
->GetSessionUp());
640 buffer
= CastSecondsToHM((client
->GetWaitTime())/1000);
644 buffer
= CastSecondsToHM((client
->GetUpStartTimeDelay())/1000);
648 switch ( client
->GetUploadState() ) {
650 buffer
= _("Connecting");
653 case US_WAITCALLBACK
:
654 buffer
= _("Connecting via server");
658 buffer
= wxT("<-- ");
659 buffer
.Append(_("Transferring"));
661 if (client
->GetDownloadState() == DS_DOWNLOADING
) {
662 buffer
.Append(wxT(" -->"));
666 case US_ONUPLOADQUEUE
:
667 buffer
= _("On Queue");
671 buffer
= _("Unknown");
676 if ( client
->GetUpPartCount() ) {
677 CUploadingView::DrawStatusBar( client
, dc
, rect
);
682 buffer
= CastItoXBytes( client
->GetUploadedTotal() ) +
683 wxT(" / ") + CastItoXBytes(client
->GetDownloadedTotal());
687 if ( client
->GetDownloadState() == DS_ONQUEUE
) {
688 if ( client
->IsRemoteQueueFull() ) {
689 buffer
= _("Queue Full");
691 if (client
->GetRemoteQueueRank()) {
692 buffer
= wxString::Format(_("QR: %u"), client
->GetRemoteQueueRank());
694 buffer
= _("Unknown");
697 } else if ( client
->GetDownloadState() == DS_DOWNLOADING
) {
698 buffer
+= wxString::Format( wxT("%.1f"), client
->GetKBpsDown() );
702 buffer
= _("Unknown");
707 dc
->DrawText( buffer
, rect
.x
, rect
.y
+ 3 );
711 int CUploadingView::SortProc(wxUIntPtr item1
, wxUIntPtr item2
, long sortData
)
713 CUpDownClient
* client1
= (CUpDownClient
*)item1
;
714 CUpDownClient
* client2
= (CUpDownClient
*)item2
;
716 // Sorting ascending or decending
717 int mode
= (sortData
& CMuleListCtrl::SORT_DES
) ? -1 : 1;
719 switch (sortData
& CMuleListCtrl::COLUMN_MASK
) {
721 case 0: return mode
* client1
->GetUserName().CmpNoCase( client2
->GetUserName() );
724 // Sort by requested file
726 const CKnownFile
* file1
= client1
->GetUploadFile();
727 const CKnownFile
* file2
= client2
->GetUploadFile();
729 if ( file1
&& file2
) {
730 return mode
* CmpAny(file1
->GetFileName(), file2
->GetFileName());
733 return mode
* CmpAny( file1
, file2
);
736 // Sort by client software
737 case 2: return mode
* CompareVersions(client1
, client2
);
740 case 3: return mode
* CmpAny( client1
->GetUploadDatarate(), client2
->GetUploadDatarate() );
742 // Sort by transferred
743 case 4: return mode
* CmpAny( client1
->GetSessionUp(), client2
->GetSessionUp() );
746 case 5: return mode
* CmpAny( client1
->GetWaitTime(), client2
->GetWaitTime() );
748 // Sort by upload time
749 case 6: return mode
* CmpAny( client1
->GetUpStartTimeDelay(), client2
->GetUpStartTimeDelay() );
752 case 7: return mode
* CmpAny( client1
->GetUploadState(), client2
->GetUploadState() );
755 case 8: return mode
* CmpAny( client1
->GetUpPartCount(), client2
->GetUpPartCount() );
758 case 9: return mode
* CmpAny( client2
->GetDownloadedTotal(), client1
->GetDownloadedTotal() );
760 // Sort by remote rank
761 case 10: return mode
* CmpAny( client2
->GetRemoteQueueRank(), client1
->GetRemoteQueueRank() );
769 void CUploadingView::DrawStatusBar( CUpDownClient
* client
, wxDC
* dc
, const wxRect
& rect1
)
775 wxPen old_pen
= dc
->GetPen();
776 wxBrush old_brush
= dc
->GetBrush();
778 dc
->SetPen(*wxTRANSPARENT_PEN
);
779 dc
->SetBrush( wxBrush( wxColour(220,220,220), wxSOLID
) );
781 dc
->DrawRectangle( rect
);
782 dc
->SetBrush(*wxBLACK_BRUSH
);
784 uint32 partCount
= client
->GetUpPartCount();
786 float blockpixel
= (float)(rect
.width
)/((float)(PARTSIZE
*partCount
)/1024);
787 for ( uint32 i
= 0; i
< partCount
; i
++ ) {
788 if ( client
->IsUpPartAvailable( i
) ) {
789 int right
= rect
.x
+ (uint32
)(((float)PARTSIZE
*i
/1024)*blockpixel
);
790 int left
= rect
.x
+ (uint32
)((float)((float)PARTSIZE
*(i
+1)/1024)*blockpixel
);
791 dc
->DrawRectangle( (int)left
, rect
.y
, right
- left
, rect
.height
);
795 dc
->SetPen( old_pen
);
796 dc
->SetBrush( old_brush
);
800 /////////////////////////////////////////////////////////////////////////////////////////////
801 void CQueuedView::Initialize( CClientListCtrl
* list
)
803 list
->InsertColumn( 0, _("Username"), wxLIST_FORMAT_LEFT
, 150 );
804 list
->InsertColumn( 1, _("File"), wxLIST_FORMAT_LEFT
, 275 );
805 list
->InsertColumn( 2, _("Client Software"), wxLIST_FORMAT_LEFT
, 100 );
806 list
->InsertColumn( 3, _("File Priority"), wxLIST_FORMAT_LEFT
, 110 );
807 list
->InsertColumn( 4, _("Rating"), wxLIST_FORMAT_LEFT
, 60 );
808 list
->InsertColumn( 5, _("Score"), wxLIST_FORMAT_LEFT
, 60 );
809 list
->InsertColumn( 6, _("Asked"), wxLIST_FORMAT_LEFT
, 60 );
810 list
->InsertColumn( 7, _("Last Seen"), wxLIST_FORMAT_LEFT
, 110 );
811 list
->InsertColumn( 8, _("Entered Queue"), wxLIST_FORMAT_LEFT
, 110 );
812 list
->InsertColumn( 9, _("Banned"), wxLIST_FORMAT_LEFT
, 60 );
813 list
->InsertColumn( 10, _("Obtained Parts"), wxLIST_FORMAT_LEFT
, 100 );
815 // Insert any existing items on the list
816 // Insert any existing items on the list
817 const CClientPtrList
& uploading
= theApp
->uploadqueue
->GetWaitingList();
818 CClientPtrList::const_iterator it
= uploading
.begin();
819 for (; it
!= uploading
.end(); ++it
) {
820 list
->InsertClient( *it
, list
->GetListView() );
825 void CQueuedView::DrawCell( CUpDownClient
* client
, int column
, wxDC
* dc
, const wxRect
& rect
)
830 // These 3 are the same for both lists
834 CUploadingView::DrawCell( client
, column
, dc
, rect
);
838 if ( client
->GetUploadFile() ) {
839 buffer
= PriorityToStr( client
->GetUploadFile()->GetUpPriority(), false );
841 buffer
= _("Unknown");
847 buffer
= wxString::Format( wxT("%.1f"), (float)client
->GetScore(false,false,true) );
851 if ( client
->HasLowID() ) {
852 buffer
= wxString::Format( wxT("%i %s"), client
->GetScore(false), _("LowID") );
854 buffer
= wxString::Format(wxT("%i"),client
->GetScore(false));
859 buffer
= wxString::Format( wxT("%i"), client
->GetAskedCount() );
864 buffer
= CastSecondsToHM((::GetTickCount() - client
->GetLastUpRequest())/1000);
868 buffer
= CastSecondsToHM((::GetTickCount() - client
->GetWaitStartTime())/1000);
872 buffer
= CastSecondsToHM(client
->GetLastUpRequest()/1000);
876 buffer
= CastSecondsToHM(client
->GetWaitStartTime()/1000);
880 if ( client
->IsBanned() ) {
889 if ( client
->GetUpPartCount() ) {
890 CUploadingView::DrawStatusBar( client
, dc
, rect
);
896 dc
->DrawText( buffer
, rect
.x
, rect
.y
+ 3 );
900 int CQueuedView::SortProc(wxUIntPtr item1
, wxUIntPtr item2
, long sortData
)
902 CUpDownClient
* client1
= (CUpDownClient
*)item1
;
903 CUpDownClient
* client2
= (CUpDownClient
*)item2
;
905 // Ascending or decending?
906 int mode
= (sortData
& CMuleListCtrl::SORT_DES
) ? -1 : 1;
908 switch (sortData
& CMuleListCtrl::COLUMN_MASK
) {
910 case 0: return mode
* client1
->GetUserName().CmpNoCase( client2
->GetUserName() );
914 const CKnownFile
* file1
= client1
->GetUploadFile();
915 const CKnownFile
* file2
= client2
->GetUploadFile();
917 if ( file1
&& file2
) {
918 return mode
* CmpAny(file1
->GetFileName(), file2
->GetFileName());
921 // Place files with filenames on top
922 return -mode
* CmpAny( file1
, file2
);
925 // Sort by client software
926 case 2: return mode
* CompareVersions(client1
, client2
);
928 // Sort by file upload-priority
930 const CKnownFile
* file1
= client1
->GetUploadFile();
931 const CKnownFile
* file2
= client2
->GetUploadFile();
933 if ( file1
&& file2
) {
934 int8 prioA
= file1
->GetUpPriority();
935 int8 prioB
= file2
->GetUpPriority();
937 // Work-around for PR_VERYLOW which has value 4. See KnownFile.h for that stupidity ...
938 return mode
* CmpAny( ( prioA
!= PR_VERYLOW
? prioA
: -1 ), ( prioB
!= PR_VERYLOW
? prioB
: -1 ) );
941 // Place files with priorities on top
942 return -mode
* CmpAny( file1
, file2
);
946 case 4: return mode
* CmpAny( client1
->GetScore(false,false,true), client2
->GetScore(false,false,true) );
949 case 5: return mode
* CmpAny( client1
->GetScore(false), client2
->GetScore(false) );
951 // Sort by Asked count
952 case 6: return mode
* CmpAny( client1
->GetAskedCount(), client2
->GetAskedCount() );
955 case 7: return mode
* CmpAny( client1
->GetLastUpRequest(), client2
->GetLastUpRequest() );
957 // Sort by entered time
958 case 8: return mode
* CmpAny( client1
->GetWaitStartTime(), client2
->GetWaitStartTime() );
961 case 9: return mode
* CmpAny( client1
->IsBanned(), client2
->IsBanned() );
968 /////////////////////////////////////////////////////////////////////////////////////////////
969 void CClientsView::Initialize( CClientListCtrl
* list
)
971 list
->InsertColumn( 0, _("Username"), wxLIST_FORMAT_LEFT
, 150 );
972 list
->InsertColumn( 1, _("Upload Status"), wxLIST_FORMAT_LEFT
, 150 );
973 list
->InsertColumn( 2, _("Transferred Up"), wxLIST_FORMAT_LEFT
, 150 );
974 list
->InsertColumn( 3, _("Download Status"), wxLIST_FORMAT_LEFT
, 150 );
975 list
->InsertColumn( 4, _("Transferred Down"), wxLIST_FORMAT_LEFT
, 150 );
976 list
->InsertColumn( 5, _("Client Software"), wxLIST_FORMAT_LEFT
, 150 );
977 list
->InsertColumn( 6, _("Connected"), wxLIST_FORMAT_LEFT
, 150 );
978 list
->InsertColumn( 7, _("Userhash"), wxLIST_FORMAT_LEFT
, 150 );
979 list
->InsertColumn( 8, _("Encrypted"), wxLIST_FORMAT_LEFT
, 100 );
980 list
->InsertColumn( 9, _("Hide shared files"), wxLIST_FORMAT_LEFT
, 100 );
982 const CClientList::IDMap
& clist
= theApp
->clientlist
->GetClientList();
983 CClientList::IDMap::const_iterator it
= clist
.begin();
985 for ( ; it
!= clist
.end(); ++it
) {
986 list
->InsertClient( it
->second
, list
->GetListView() );
991 void CClientsView::DrawCell( CUpDownClient
* client
, int column
, wxDC
* dc
, const wxRect
& rect
)
997 CUploadingView::DrawCell( client
, column
, dc
, rect
);
1001 CUploadingView::DrawCell( client
, 7, dc
, rect
);
1005 buffer
= CastItoXBytes( client
->GetUploadedTotal() );
1010 buffer
= DownloadStateToStr( client
->GetDownloadState(),
1011 client
->IsRemoteQueueFull() );
1015 buffer
= CastItoXBytes( client
->GetDownloadedTotal() );
1019 buffer
= client
->GetClientVerString();
1023 if ( client
->IsConnected() ) {
1032 buffer
= client
->GetUserHash().Encode();
1036 buffer
= client
->HasObfuscatedConnectionBeenEstablished() ?
1041 buffer
= client
->GetUserName().IsEmpty() ?
1043 (client
->HasDisabledSharedFiles() ? _("Yes") : _("No"));
1047 dc
->DrawText( buffer
, rect
.x
, rect
.y
+ 3 );
1051 int CClientsView::SortProc(wxUIntPtr item1
, wxUIntPtr item2
, long sortData
)
1053 CUpDownClient
* client1
= (CUpDownClient
*)item1
;
1054 CUpDownClient
* client2
= (CUpDownClient
*)item2
;
1056 // Ascending or decending?
1057 int mode
= (sortData
& CMuleListCtrl::SORT_DES
) ? -1 : 1;
1059 switch (sortData
& CMuleListCtrl::COLUMN_MASK
) {
1061 case 0: return mode
* client1
->GetUserName().CmpNoCase( client2
->GetUserName() );
1063 // Sort by Uploading-state
1064 case 1: return mode
* CmpAny( client1
->GetUploadState(), client2
->GetUploadState() );
1066 // Sort by data-uploaded
1068 return mode
* CmpAny( client1
->GetUploadedTotal(), client2
->GetUploadedTotal() );
1070 // Sort by Downloading-state
1072 if( client1
->GetDownloadState() == client2
->GetDownloadState() ){
1073 if( client1
->IsRemoteQueueFull() && client2
->IsRemoteQueueFull() ) {
1075 } else if( client1
->IsRemoteQueueFull() ) {
1077 } else if( client2
->IsRemoteQueueFull() ) {
1083 return mode
* CmpAny( client1
->GetDownloadState(), client2
->GetDownloadState() );
1085 // Sort by data downloaded
1087 return mode
* CmpAny( client1
->GetDownloadedTotal(), client2
->GetDownloadedTotal() );
1089 // Sort by client-software
1090 case 5: return mode
* CompareVersions(client1
, client2
);
1092 // Sort by connection
1093 case 6: return mode
* CmpAny( client1
->IsConnected(), client2
->IsConnected() );
1095 // Sort by user-hash
1096 case 7: return mode
* CmpAny( client1
->GetUserHash(), client2
->GetUserHash() );
1098 // Sort by Obfuscation state
1099 case 8: return mode
* CmpAny( client2
->HasObfuscatedConnectionBeenEstablished(), client1
->HasObfuscatedConnectionBeenEstablished() );
1101 // Sort by Shared Files DISabled
1102 case 9: return mode
* CmpAny( client2
->HasDisabledSharedFiles(), client1
->HasDisabledSharedFiles() );
1109 // File_checked_for_headers