Upstream tarball 20080414
[amule.git] / src / ClientListCtrl.cpp
blob69460df7a6c87f3e5da615324d9a457a5019ec3d
1 //
2 // This file is part of the aMule Project.
3 //
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 )
6 //
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
9 // respective authors.
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.
20 //
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>
31 #include "amule.h"
32 #include "amuleDlg.h"
33 #include "ChatWnd.h"
34 #include "ClientDetailDialog.h"
35 #include "ClientList.h"
36 #include "Color.h"
37 #include "DataToText.h"
38 #ifdef ENABLE_IP2COUNTRY
39 #include "IP2Country.h" // Needed for IP2Country
40 #endif
41 #include "KnownFile.h"
42 #include "updownclient.h"
43 #include "UploadQueue.h"
45 #include <wx/menu.h>
46 #include <wx/textdlg.h>
47 #include <wx/dc.h>
48 #include <wx/settings.h>
50 ////////////////////////////////////////////////////////////
51 // Sorter functions.
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 ////////////////////////////////////////////////////////////
68 // CClientListCtrl
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 )
81 END_EVENT_TABLE()
84 #define m_imagelist theApp->amuledlg->m_imagelist
87 /**
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
92 * for easier access.
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.
97 struct ClientListView
99 //! The name of the view, this is used to load and save column-preferences.
100 wxString m_title;
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.
118 wxEmptyString,
119 NULL,
120 NULL,
121 NULL,
124 //! Uploading: The clients currently being uploaded to.
126 wxT("Uploads"),
127 CUploadingView::Initialize,
128 CUploadingView::DrawCell,
129 CUploadingView::SortProc,
132 //! Queued: The clients currently queued for uploading.
134 wxT("Queue"),
135 CQueuedView::Initialize,
136 CQueuedView::DrawCell,
137 CQueuedView::SortProc,
140 //! Clients The complete list of all known clients.
142 wxT("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 )
155 m_viewType = vtNone;
157 m_menu = NULL;
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()
180 return m_viewType;
184 void CClientListCtrl::SetListView( ViewType newView )
186 if ( m_viewType != newView ) {
187 if (m_viewType != vtNone) {
188 SaveSettings();
189 ClearAll();
192 m_viewType = newView;
194 const ClientListView& view = g_listViews[ (int)newView ];
196 // Initialize the selected view
197 if ( view.m_init ) {
198 view.m_init( this );
201 SetTableName( view.m_title );
202 SetSortFunc( view.m_sort );
204 if (newView != vtNone) {
205 LoadSettings();
211 void CClientListCtrl::ToggleView()
213 // Disallow toggling if the list is disabled
214 if ( m_viewType == vtNone ) {
215 return;
218 unsigned int view = (int)m_viewType + 1;
220 if ( view < itemsof(g_listViews) ) {
221 SetListView( (ViewType)(view) );
222 } else {
223 SetListView( (ViewType)(1) );
228 /////////////////////////////////////////////////////////////////////////////////////////////
229 void CClientListCtrl::OnRightClick(wxMouseEvent& event)
231 long index = CheckSelection(event);
233 if ( m_menu == NULL ) {
235 bool banned = false;
236 bool validIP = false;
237 bool isfriend = false;
238 bool hasdisabledsharedfiles = false;
240 // Check if the client is banned
241 if ( index > -1 ) {
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() );
278 delete m_menu;
280 m_menu = NULL;
285 void CClientListCtrl::OnMiddleClick(wxListEvent& event)
287 long index = CheckSelection(event);
289 if (index > -1) {
290 CUpDownClient *client = reinterpret_cast<CUpDownClient *>(GetItemData( index ));
292 CClientDetailDialog dialog(this, client);
294 dialog.ShowModal();
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());
315 } else {
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 );
327 if ( index > -1 ) {
328 CUpDownClient *client = reinterpret_cast<CUpDownClient *>(GetItemData( index ));
329 CClientDetailDialog dialog(this, client);
330 dialog.ShowModal();
335 void CClientListCtrl::OnViewFiles( wxCommandEvent& WXUNUSED(event) )
337 long index = GetNextItem( -1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED );
339 if ( index > -1 ) {
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 );
350 if ( index > -1 ) {
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 );
371 if ( index > -1 ) {
372 CUpDownClient *client = reinterpret_cast<CUpDownClient *>(GetItemData( index ));
373 if ( client->IsBanned() ) {
374 client->UnBan();
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 ) ) {
385 return;
388 long index = InsertItem( GetItemCount(), wxEmptyString );
389 SetItemPtrData( index, reinterpret_cast<wxUIntPtr>(client) );
391 wxListItem myitem;
392 myitem.SetId( index );
393 myitem.SetBackgroundColour( SYSCOLOR(wxSYS_COLOUR_LISTBOX) );
395 SetItem(myitem);
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 ) ) {
406 return;
409 long index = FindItem( -1, reinterpret_cast<wxUIntPtr>(client) );
411 if ( index > -1 ) {
412 DeleteItem( index );
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 ) ) {
422 return;
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) );
429 if ( result > -1 ) {
430 #ifndef __WXMSW__
431 GetVisibleLines( &first, &last );
432 #endif
433 if ( result >= first && result <= last) {
434 RefreshItem(result);
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 ) ) {
445 return;
448 if ( highlighted ) {
449 if ( GetFocus() ) {
450 dc->SetBackground(*m_hilightBrush);
451 dc->SetTextForeground( SYSCOLOR(wxSYS_COLOUR_HIGHLIGHTTEXT) );
452 } else {
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) );
459 } else {
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;
471 cur_rect.x += 4;
473 const ClientListView& view = g_listViews[ (int)m_viewType ];
475 if ( view.m_draw ) {
476 for ( int i = 0; i < GetColumnCount(); i++ ) {
477 int width = GetColumnWidth( i );
478 if ( width ) {
479 cur_rect.width = width - 8;
481 wxDCClipper clipper( *dc, cur_rect );
483 view.m_draw( client, i, dc, cur_rect );
485 cur_rect.x += width;
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 )
525 wxString buffer;
527 switch ( column ) {
528 case 0: {
529 uint8 clientImage;
531 if ( client->IsFriend() ) {
532 clientImage = Client_Friend_Smiley;
533 } else {
534 switch (client->GetClientSoft()) {
535 case SO_AMULE:
536 clientImage = Client_aMule_Smiley;
537 break;
538 case SO_MLDONKEY:
539 case SO_NEW_MLDONKEY:
540 case SO_NEW2_MLDONKEY:
541 clientImage = Client_mlDonkey_Smiley;
542 break;
543 case SO_EDONKEY:
544 case SO_EDONKEYHYBRID:
545 // Maybe we would like to make different icons?
546 clientImage = Client_eDonkeyHybrid_Smiley;
547 break;
548 case SO_EMULE:
549 clientImage = Client_eMule_Smiley;
550 break;
551 case SO_LPHANT:
552 clientImage = Client_lphant_Smiley;
553 break;
554 case SO_SHAREAZA:
555 case SO_NEW_SHAREAZA:
556 case SO_NEW2_SHAREAZA:
557 clientImage = Client_Shareaza_Smiley;
558 break;
559 case SO_LXMULE:
560 clientImage = Client_xMule_Smiley;
561 break;
562 default:
563 // cDonkey, Compat Unk
564 // No icon for those yet. Using the eMule one + '?'
565 clientImage = Client_Unknown;
566 break;
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()) {
584 // the 'v'
585 m_imagelist.Draw(Client_SecIdent_Smiley, *dc, rect.x, rect.y + 1,
586 wxIMAGELIST_DRAW_TRANSPARENT);
587 } else if (client->IsBadGuy()) {
588 // the 'X'
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);
599 wxString userName;
600 #ifdef ENABLE_IP2COUNTRY
601 // Draw the flag
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);
613 return;
616 case 1:
617 if ( client->GetUploadFile() ) {
618 buffer = client->GetUploadFile()->GetFileName().GetPrintable();
619 } else {
620 buffer = _("N/A");
622 break;
624 case 2:
625 buffer = client->GetClientVerString();
626 break;
628 case 3:
629 buffer = wxString::Format( wxT("%.1f"), client->GetUploadDatarate() / 1024.0f );
631 buffer += wxT(" ");
632 buffer += _("kB/s");
633 break;
635 case 4:
636 buffer = CastItoXBytes(client->GetSessionUp());
637 break;
639 case 5:
640 buffer = CastSecondsToHM((client->GetWaitTime())/1000);
641 break;
643 case 6:
644 buffer = CastSecondsToHM((client->GetUpStartTimeDelay())/1000);
645 break;
647 case 7:
648 switch ( client->GetUploadState() ) {
649 case US_CONNECTING:
650 buffer = _("Connecting");
651 break;
653 case US_WAITCALLBACK:
654 buffer = _("Connecting via server");
655 break;
657 case US_UPLOADING:
658 buffer = wxT("<-- ");
659 buffer.Append(_("Transferring"));
661 if (client->GetDownloadState() == DS_DOWNLOADING) {
662 buffer.Append(wxT(" -->"));
664 break;
666 case US_ONUPLOADQUEUE:
667 buffer = _("On Queue");
668 break;
670 default:
671 buffer = _("Unknown");
673 break;
675 case 8:
676 if ( client->GetUpPartCount() ) {
677 CUploadingView::DrawStatusBar( client, dc, rect );
679 return;
681 case 9:
682 buffer = CastItoXBytes( client->GetUploadedTotal() ) +
683 wxT(" / ") + CastItoXBytes(client->GetDownloadedTotal());
684 break;
686 case 10:
687 if ( client->GetDownloadState() == DS_ONQUEUE ) {
688 if ( client->IsRemoteQueueFull() ) {
689 buffer = _("Queue Full");
690 } else {
691 if (client->GetRemoteQueueRank()) {
692 buffer = wxString::Format(_("QR: %u"), client->GetRemoteQueueRank());
693 } else {
694 buffer = _("Unknown");
697 } else if ( client->GetDownloadState() == DS_DOWNLOADING ) {
698 buffer += wxString::Format( wxT("%.1f"), client->GetKBpsDown() );
699 buffer += wxT(" ");
700 buffer += _("kB/s");
701 } else {
702 buffer = _("Unknown");
704 break;
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) {
720 // Sort by username
721 case 0: return mode * client1->GetUserName().CmpNoCase( client2->GetUserName() );
724 // Sort by requested file
725 case 1: {
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);
739 // Sort by speed
740 case 3: return mode * CmpAny( client1->GetUploadDatarate(), client2->GetUploadDatarate() );
742 // Sort by transferred
743 case 4: return mode * CmpAny( client1->GetSessionUp(), client2->GetSessionUp() );
745 // Sort by wait-time
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() );
751 // Sort by state
752 case 7: return mode * CmpAny( client1->GetUploadState(), client2->GetUploadState() );
754 // Sort by partcount
755 case 8: return mode * CmpAny( client1->GetUpPartCount(), client2->GetUpPartCount() );
757 // Sort by U/D ratio
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() );
763 default:
764 return 0;
769 void CUploadingView::DrawStatusBar( CUpDownClient* client, wxDC* dc, const wxRect& rect1 )
771 wxRect rect = rect1;
772 rect.y += 2;
773 rect.height -= 2;
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 )
827 wxString buffer;
829 switch ( column ) {
830 // These 3 are the same for both lists
831 case 0:
832 case 1:
833 case 2:
834 CUploadingView::DrawCell( client, column, dc, rect );
835 return;
837 case 3:
838 if ( client->GetUploadFile() ) {
839 buffer = PriorityToStr( client->GetUploadFile()->GetUpPriority(), false );
840 } else {
841 buffer = _("Unknown");
844 break;
846 case 4:
847 buffer = wxString::Format( wxT("%.1f"), (float)client->GetScore(false,false,true) );
848 break;
850 case 5:
851 if ( client->HasLowID() ) {
852 buffer = wxString::Format( wxT("%i %s"), client->GetScore(false), _("LowID") );
853 } else {
854 buffer = wxString::Format(wxT("%i"),client->GetScore(false));
856 break;
858 case 6:
859 buffer = wxString::Format( wxT("%i"), client->GetAskedCount() );
860 break;
862 #ifndef CLIENT_GUI
863 case 7:
864 buffer = CastSecondsToHM((::GetTickCount() - client->GetLastUpRequest())/1000);
865 break;
867 case 8:
868 buffer = CastSecondsToHM((::GetTickCount() - client->GetWaitStartTime())/1000);
869 break;
870 #else
871 case 7:
872 buffer = CastSecondsToHM(client->GetLastUpRequest()/1000);
873 break;
875 case 8:
876 buffer = CastSecondsToHM(client->GetWaitStartTime()/1000);
877 break;
878 #endif
879 case 9:
880 if ( client->IsBanned() ) {
881 buffer = _("Yes");
882 } else {
883 buffer = _("No");
886 break;
888 case 10:
889 if ( client->GetUpPartCount() ) {
890 CUploadingView::DrawStatusBar( client, dc, rect );
893 return;
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) {
909 // Sort by username
910 case 0: return mode * client1->GetUserName().CmpNoCase( client2->GetUserName() );
912 // Sort by filename
913 case 1: {
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
929 case 3: {
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 );
945 // Sort by rating
946 case 4: return mode * CmpAny( client1->GetScore(false,false,true), client2->GetScore(false,false,true) );
948 // Sort by score
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() );
954 // Sort by Last seen
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() );
960 // Sort by banned
961 case 9: return mode * CmpAny( client1->IsBanned(), client2->IsBanned() );
963 default: return 0;
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 )
993 wxString buffer;
995 switch ( column ) {
996 case 0:
997 CUploadingView::DrawCell( client, column, dc, rect );
998 return;
1000 case 1:
1001 CUploadingView::DrawCell( client, 7, dc, rect );
1002 return;
1004 case 2:
1005 buffer = CastItoXBytes( client->GetUploadedTotal() );
1007 break;
1009 case 3:
1010 buffer = DownloadStateToStr( client->GetDownloadState(),
1011 client->IsRemoteQueueFull() );
1012 break;
1014 case 4:
1015 buffer = CastItoXBytes( client->GetDownloadedTotal() );
1016 break;
1018 case 5:
1019 buffer = client->GetClientVerString();
1020 break;
1022 case 6:
1023 if ( client->IsConnected() ) {
1024 buffer = _("Yes");
1025 } else {
1026 buffer = _("No");
1029 break;
1031 case 7:
1032 buffer = client->GetUserHash().Encode();
1033 break;
1035 case 8:
1036 buffer = client->HasObfuscatedConnectionBeenEstablished() ?
1037 _("Yes") : _("No");
1038 break;
1040 case 9:
1041 buffer = client->GetUserName().IsEmpty() ?
1042 wxT("?") :
1043 (client->HasDisabledSharedFiles() ? _("Yes") : _("No"));
1044 break;
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) {
1060 // Sort by Username
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
1067 case 2:
1068 return mode * CmpAny( client1->GetUploadedTotal(), client2->GetUploadedTotal() );
1070 // Sort by Downloading-state
1071 case 3:
1072 if( client1->GetDownloadState() == client2->GetDownloadState() ){
1073 if( client1->IsRemoteQueueFull() && client2->IsRemoteQueueFull() ) {
1074 return mode * 0;
1075 } else if( client1->IsRemoteQueueFull() ) {
1076 return mode * 1;
1077 } else if( client2->IsRemoteQueueFull() ) {
1078 return mode * -1;
1079 } else {
1080 return mode * 0;
1083 return mode * CmpAny( client1->GetDownloadState(), client2->GetDownloadState() );
1085 // Sort by data downloaded
1086 case 4:
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() );
1104 default:
1105 return 0;
1109 // File_checked_for_headers