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
;
112 //! Pointer to the function which returns the old column order.
113 wxString (*m_getOldColumnOrder
)();
117 //! This is the list of currently usable views, in the same order as the ViewType enum.
118 ClientListView g_listViews
[] =
120 //! None: This view does nothing at all.
129 //! Uploading: The clients currently being uploaded to.
132 CUploadingView::Initialize
,
133 CUploadingView::DrawCell
,
134 CUploadingView::SortProc
,
135 CUploadingView::GetOldColumnOrder
,
138 //! Queued: The clients currently queued for uploading.
141 CQueuedView::Initialize
,
142 CQueuedView::DrawCell
,
143 CQueuedView::SortProc
,
144 CQueuedView::GetOldColumnOrder
,
147 //! Clients The complete list of all known clients.
150 CClientsView::Initialize
,
151 CClientsView::DrawCell
,
152 CClientsView::SortProc
,
153 CClientsView::GetOldColumnOrder
,
159 CClientListCtrl::CClientListCtrl( wxWindow
*parent
, wxWindowID winid
, const wxPoint
&pos
, const wxSize
&size
, long style
, const wxValidator
& validator
, const wxString
& name
)
161 CMuleListCtrl( parent
, winid
, pos
, size
, style
| wxLC_OWNERDRAW
, validator
, name
)
167 m_hilightBrush
= CMuleColour(wxSYS_COLOUR_HIGHLIGHT
).Blend(125).GetBrush();
169 m_hilightUnfocusBrush
= CMuleColour(wxSYS_COLOUR_BTNSHADOW
).Blend(125).GetBrush();
171 // We show the uploading-list initially
172 SetListView( vtUploading
);
176 CClientListCtrl::~CClientListCtrl()
182 ViewType
CClientListCtrl::GetListView()
188 void CClientListCtrl::SetListView( ViewType newView
)
190 if ( m_viewType
!= newView
) {
191 if (m_viewType
!= vtNone
) {
196 m_viewType
= newView
;
198 const ClientListView
& view
= g_listViews
[ (int)newView
];
200 // Initialize the selected view
205 SetTableName( view
.m_title
);
206 SetSortFunc( view
.m_sort
);
208 if (newView
!= vtNone
) {
215 void CClientListCtrl::ToggleView()
217 // Disallow toggling if the list is disabled
218 if ( m_viewType
== vtNone
) {
222 unsigned int view
= (int)m_viewType
+ 1;
224 if ( view
< itemsof(g_listViews
) ) {
225 SetListView( (ViewType
)(view
) );
227 SetListView( (ViewType
)(1) );
232 /////////////////////////////////////////////////////////////////////////////////////////////
233 void CClientListCtrl::OnRightClick(wxMouseEvent
& event
)
235 long index
= CheckSelection(event
);
237 if ( m_menu
== NULL
) {
240 bool validIP
= false;
241 bool isfriend
= false;
242 bool hasdisabledsharedfiles
= false;
244 // Check if the client is banned
246 CUpDownClient
*client
= reinterpret_cast<CUpDownClient
*>(GetItemData( index
));
248 banned
= client
->IsBanned();
249 validIP
= (client
->GetIP() != 0);
250 isfriend
= client
->IsFriend();
251 hasdisabledsharedfiles
= client
->HasDisabledSharedFiles();
254 m_menu
= new wxMenu(_("Clients"));
255 m_menu
->Append( MP_DETAIL
, _("Show &Details") );
256 m_menu
->Append( MP_ADDFRIEND
, isfriend
? _("Remove from friends") : _("Add to Friends") );
257 m_menu
->Append( MP_SHOWLIST
, _("View Files") );
258 m_menu
->Append( MP_SENDMESSAGE
, _("Send message") );
259 m_menu
->Append( MP_UNBAN
, _("Unban") );
261 m_menu
->AppendSeparator();
263 wxMenu
* view
= new wxMenu();
264 view
->Append( MP_SWITCHCTRL_0
+ 1, _("Show Uploads") );
265 view
->Append( MP_SWITCHCTRL_0
+ 2, _("Show Queue") );
266 view
->Append( MP_SWITCHCTRL_0
+ 3, _("Show Clients") );
268 view
->Enable( MP_SWITCHCTRL_0
+ (int)m_viewType
, false );
270 m_menu
->Append( 0, _("Select View"), view
);
272 m_menu
->Enable( MP_DETAIL
, index
> -1 );
273 m_menu
->Enable( MP_SHOWLIST
, index
> -1 );
275 m_menu
->Enable( MP_UNBAN
, banned
);
276 m_menu
->Enable( MP_SHOWLIST
, !hasdisabledsharedfiles
);
277 m_menu
->Enable( MP_ADDFRIEND
, validIP
);
278 m_menu
->Enable( MP_SENDMESSAGE
, validIP
);
280 PopupMenu( m_menu
, event
.GetPosition() );
289 void CClientListCtrl::OnMiddleClick(wxListEvent
& event
)
291 long index
= CheckSelection(event
);
294 CUpDownClient
*client
= reinterpret_cast<CUpDownClient
*>(GetItemData( index
));
296 CClientDetailDialog
dialog(this, client
);
303 void CClientListCtrl::OnChangeView( wxCommandEvent
& event
)
305 int view
= event
.GetId() - MP_SWITCHCTRL_0
;
307 SetListView( (ViewType
)view
);
311 void CClientListCtrl::OnAddFriend( wxCommandEvent
& WXUNUSED(event
) )
313 long index
= GetNextItem( -1, wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED
);
315 while ( index
!= -1 ) {
316 CUpDownClient
*client
= reinterpret_cast<CUpDownClient
*>(GetItemData( index
));
317 if (client
->IsFriend()) {
318 theApp
->amuledlg
->m_chatwnd
->RemoveFriend(client
->GetUserHash(), client
->GetIP(), client
->GetUserPort());
320 theApp
->amuledlg
->m_chatwnd
->AddFriend( client
);
322 index
= GetNextItem( index
, wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED
);
327 void CClientListCtrl::OnShowDetails( wxCommandEvent
& WXUNUSED(event
) )
329 long index
= GetNextItem( -1, wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED
);
332 CUpDownClient
*client
= reinterpret_cast<CUpDownClient
*>(GetItemData( index
));
333 CClientDetailDialog
dialog(this, client
);
339 void CClientListCtrl::OnViewFiles( wxCommandEvent
& WXUNUSED(event
) )
341 long index
= GetNextItem( -1, wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED
);
344 CUpDownClient
*client
= reinterpret_cast<CUpDownClient
*>(GetItemData( index
));
345 client
->RequestSharedFileList();
350 void CClientListCtrl::OnSendMessage( wxCommandEvent
& WXUNUSED(event
) )
352 long index
= GetNextItem( -1, wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED
);
355 CUpDownClient
*client
= reinterpret_cast<CUpDownClient
*>(GetItemData( index
));
357 // These values are cached, since calling wxGetTextFromUser will
358 // start an event-loop, in which the client may be deleted.
359 wxString userName
= client
->GetUserName();
360 uint64 userID
= GUI_ID(client
->GetIP(),client
->GetUserPort());
362 wxString message
= ::wxGetTextFromUser( _("Send message to user"), _("Message to send:") );
364 if (!message
.IsEmpty()) {
365 theApp
->amuledlg
->m_chatwnd
->SendMessage(message
, userName
, userID
);
371 void CClientListCtrl::OnUnbanClient( wxCommandEvent
& WXUNUSED(event
) )
373 long index
= GetNextItem( -1, wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED
);
376 CUpDownClient
*client
= reinterpret_cast<CUpDownClient
*>(GetItemData( index
));
377 if ( client
->IsBanned() ) {
384 void CClientListCtrl::InsertClient( CUpDownClient
* client
, ViewType view
)
386 wxCHECK_RET(client
, wxT("Attempted to add NULL client pointer."));
388 if ( ( m_viewType
!= view
) || ( view
== vtNone
) ) {
392 long index
= InsertItem( GetItemCount(), wxEmptyString
);
393 SetItemPtrData( index
, reinterpret_cast<wxUIntPtr
>(client
) );
396 myitem
.SetId( index
);
397 myitem
.SetBackgroundColour( CMuleColour(wxSYS_COLOUR_LISTBOX
) );
401 RefreshItem( index
);
405 void CClientListCtrl::RemoveClient( CUpDownClient
* client
, ViewType view
)
407 wxCHECK_RET(client
, wxT("Attempted to remove NULL client pointer."));
409 if ( ( m_viewType
!= view
) || ( view
== vtNone
) ) {
413 long index
= FindItem( -1, reinterpret_cast<wxUIntPtr
>(client
) );
421 void CClientListCtrl::UpdateClient( CUpDownClient
* client
, ViewType view
)
423 wxCHECK_RET(client
, wxT("Attempted to update NULL client pointer."));
425 if ( ( m_viewType
!= view
) || ( view
== vtNone
) ) {
429 if ( theApp
->amuledlg
->IsDialogVisible( CamuleDlg::DT_TRANSFER_WND
) ) {
430 // Visible lines, default to all because not all platforms support the GetVisibleLines function
431 long first
= 0, last
= GetItemCount();
432 long result
= FindItem( -1, reinterpret_cast<wxUIntPtr
>(client
) );
435 GetVisibleLines( &first
, &last
);
437 if ( result
>= first
&& result
<= last
) {
445 void CClientListCtrl::OnDrawItem( int item
, wxDC
* dc
, const wxRect
& rect
, const wxRect
& rectHL
, bool highlighted
)
447 // Don't do any drawing if we not being watched.
448 if ( !theApp
->amuledlg
|| !theApp
->amuledlg
->IsDialogVisible( CamuleDlg::DT_TRANSFER_WND
) ) {
454 dc
->SetBackground(m_hilightBrush
);
455 dc
->SetTextForeground( CMuleColour(wxSYS_COLOUR_HIGHLIGHTTEXT
) );
457 dc
->SetBackground(m_hilightUnfocusBrush
);
458 dc
->SetTextForeground( CMuleColour(wxSYS_COLOUR_HIGHLIGHTTEXT
));
461 CMuleColour colour
= GetFocus() ? m_hilightBrush
.GetColour() : m_hilightUnfocusBrush
.GetColour();
462 dc
->SetPen( *(wxThePenList
->FindOrCreatePen( colour
.Blend(65), 1, wxSOLID
) ));
464 dc
->SetBackground( CMuleColour(wxSYS_COLOUR_LISTBOX
).GetBrush());
465 dc
->SetTextForeground( CMuleColour(wxSYS_COLOUR_WINDOWTEXT
) );
466 dc
->SetPen(*wxTRANSPARENT_PEN
);
469 dc
->SetBrush(dc
->GetBackground());
470 dc
->DrawRectangle(rectHL
);
471 dc
->SetPen(*wxTRANSPARENT_PEN
);
473 CUpDownClient
* client
= reinterpret_cast<CUpDownClient
*>(GetItemData(item
));
474 wxRect cur_rect
= rect
;
477 const ClientListView
& view
= g_listViews
[ (int)m_viewType
];
480 for ( int i
= 0; i
< GetColumnCount(); i
++ ) {
481 int width
= GetColumnWidth( i
);
483 cur_rect
.width
= width
- 8;
485 wxDCClipper
clipper( *dc
, cur_rect
);
487 view
.m_draw( client
, i
, dc
, cur_rect
);
495 wxString
CClientListCtrl::GetTTSText(unsigned item
) const
497 CUpDownClient
*client
= reinterpret_cast<CUpDownClient
*>(GetItemData( item
));
499 return client
->GetUserName();
503 wxString
CClientListCtrl::GetOldColumnOrder() const
505 const ClientListView
& view
= g_listViews
[ (int)m_viewType
];
506 if (view
.m_getOldColumnOrder
) {
507 return view
.m_getOldColumnOrder();
509 return wxEmptyString
;
513 /////////////////////////////////////////////////////////////////////////////////////////////
514 void CUploadingView::Initialize( CClientListCtrl
* list
)
516 list
->InsertColumn( 0, _("Username"), wxLIST_FORMAT_LEFT
, 150, wxT("U") );
517 list
->InsertColumn( 1, _("File"), wxLIST_FORMAT_LEFT
, 275, wxT("F") );
518 list
->InsertColumn( 2, _("Client Software"), wxLIST_FORMAT_LEFT
, 100, wxT("C") );
519 list
->InsertColumn( 3, _("Speed"), wxLIST_FORMAT_LEFT
, 60, wxT("S") );
520 list
->InsertColumn( 4, _("Transferred"), wxLIST_FORMAT_LEFT
, 65, wxT("T") );
521 list
->InsertColumn( 5, _("Waited"), wxLIST_FORMAT_LEFT
, 60, wxT("W") );
522 list
->InsertColumn( 6, _("Upload Time"), wxLIST_FORMAT_LEFT
, 60, wxT("u") );
523 list
->InsertColumn( 7, _("Status"), wxLIST_FORMAT_LEFT
, 110, wxT("s") );
524 list
->InsertColumn( 8, _("Obtained Parts"), wxLIST_FORMAT_LEFT
, 100, wxT("P") );
525 list
->InsertColumn( 9, _("Upload/Download"), wxLIST_FORMAT_LEFT
, 100, wxT("R") );
526 list
->InsertColumn( 10, _("Remote Status"), wxLIST_FORMAT_LEFT
, 100, wxT("r") );
528 // Insert any existing items on the list
529 const CClientPtrList
& uploading
= theApp
->uploadqueue
->GetUploadingList();
530 CClientPtrList::const_iterator it
= uploading
.begin();
531 for (; it
!= uploading
.end(); ++it
) {
532 list
->InsertClient( *it
, list
->GetListView() );
537 wxString
CUploadingView::GetOldColumnOrder()
539 return wxT("U,F,C,S,T,W,u,s,P,R,r");
543 void CUploadingView::DrawCell( CUpDownClient
* client
, int column
, wxDC
* dc
, const wxRect
& rect
)
551 if ( client
->IsFriend() ) {
552 clientImage
= Client_Friend_Smiley
;
554 switch (client
->GetClientSoft()) {
556 clientImage
= Client_aMule_Smiley
;
559 case SO_NEW_MLDONKEY
:
560 case SO_NEW2_MLDONKEY
:
561 clientImage
= Client_mlDonkey_Smiley
;
564 case SO_EDONKEYHYBRID
:
565 // Maybe we would like to make different icons?
566 clientImage
= Client_eDonkeyHybrid_Smiley
;
569 clientImage
= Client_eMule_Smiley
;
572 clientImage
= Client_lphant_Smiley
;
575 case SO_NEW_SHAREAZA
:
576 case SO_NEW2_SHAREAZA
:
577 clientImage
= Client_Shareaza_Smiley
;
580 clientImage
= Client_xMule_Smiley
;
583 // cDonkey, Compat Unk
584 // No icon for those yet. Using the eMule one + '?'
585 clientImage
= Client_Unknown
;
590 m_imagelist
.Draw(clientImage
, *dc
, rect
.x
, rect
.y
+ 1,
591 wxIMAGELIST_DRAW_TRANSPARENT
);
593 if (client
->GetScoreRatio() > 1) {
594 // Has credits, draw the gold star
595 m_imagelist
.Draw(Client_CreditsYellow_Smiley
, *dc
, rect
.x
, rect
.y
+ 1,
596 wxIMAGELIST_DRAW_TRANSPARENT
);
597 } else if (client
->ExtProtocolAvailable()) {
598 // Ext protocol -> Draw the '+'
599 m_imagelist
.Draw(Client_ExtendedProtocol_Smiley
, *dc
, rect
.x
, rect
.y
+ 1,
600 wxIMAGELIST_DRAW_TRANSPARENT
);
603 if (client
->IsIdentified()) {
605 m_imagelist
.Draw(Client_SecIdent_Smiley
, *dc
, rect
.x
, rect
.y
+ 1,
606 wxIMAGELIST_DRAW_TRANSPARENT
);
607 } else if (client
->IsBadGuy()) {
609 m_imagelist
.Draw(Client_BadGuy_Smiley
, *dc
, rect
.x
, rect
.y
+ 1,
610 wxIMAGELIST_DRAW_TRANSPARENT
);
613 if (client
->HasObfuscatedConnectionBeenEstablished()) {
614 // the "¿" except it's a key
615 m_imagelist
.Draw(Client_Encryption_Smiley
, *dc
, rect
.x
, rect
.y
+ 1,
616 wxIMAGELIST_DRAW_TRANSPARENT
);
620 #ifdef ENABLE_IP2COUNTRY
622 const CountryData
& countrydata
=
623 theApp
->amuledlg
->m_IP2Country
->GetCountryData(client
->GetFullIP());
624 dc
->DrawBitmap(countrydata
.Flag
, rect
.x
+ 20, rect
.y
+ 5,
625 wxIMAGELIST_DRAW_TRANSPARENT
);
627 userName
<< countrydata
.Name
;
628 userName
<< wxT(" - ");
629 #endif // ENABLE_IP2COUNTRY
630 userName
<< client
->GetUserName();
631 dc
->DrawText(userName
, rect
.x
+ 40, rect
.y
+ 3);
637 if ( client
->GetUploadFile() ) {
638 buffer
= client
->GetUploadFile()->GetFileName().GetPrintable();
645 buffer
= client
->GetClientVerString();
649 buffer
= wxString::Format( wxT("%.1f"), client
->GetUploadDatarate() / 1024.0f
);
656 buffer
= CastItoXBytes(client
->GetSessionUp());
660 buffer
= CastSecondsToHM((client
->GetWaitTime())/1000);
664 buffer
= CastSecondsToHM((client
->GetUpStartTimeDelay())/1000);
668 switch ( client
->GetUploadState() ) {
670 buffer
= _("Connecting");
673 case US_WAITCALLBACK
:
674 buffer
= _("Connecting via server");
678 buffer
= wxT("<-- ");
679 buffer
.Append(_("Transferring"));
681 if (client
->GetDownloadState() == DS_DOWNLOADING
) {
682 buffer
.Append(wxT(" -->"));
686 case US_ONUPLOADQUEUE
:
687 buffer
= _("On Queue");
691 buffer
= _("Unknown");
696 if ( client
->GetUpPartCount() ) {
697 CUploadingView::DrawStatusBar( client
, dc
, rect
);
702 buffer
= CastItoXBytes( client
->GetUploadedTotal() ) +
703 wxT(" / ") + CastItoXBytes(client
->GetDownloadedTotal());
707 if ( client
->GetDownloadState() == DS_ONQUEUE
) {
708 if ( client
->IsRemoteQueueFull() ) {
709 buffer
= _("Queue Full");
711 if (client
->GetRemoteQueueRank()) {
712 buffer
= wxString::Format(_("QR: %u"), client
->GetRemoteQueueRank());
714 buffer
= _("Unknown");
717 } else if ( client
->GetDownloadState() == DS_DOWNLOADING
) {
718 buffer
+= wxString::Format( wxT("%.1f"), client
->GetKBpsDown() );
722 buffer
= _("Unknown");
727 dc
->DrawText( buffer
, rect
.x
, rect
.y
+ 3 );
731 int CUploadingView::SortProc(wxUIntPtr item1
, wxUIntPtr item2
, long sortData
)
733 CUpDownClient
* client1
= (CUpDownClient
*)item1
;
734 CUpDownClient
* client2
= (CUpDownClient
*)item2
;
736 // Sorting ascending or decending
737 int mode
= (sortData
& CMuleListCtrl::SORT_DES
) ? -1 : 1;
739 switch (sortData
& CMuleListCtrl::COLUMN_MASK
) {
741 case 0: return mode
* client1
->GetUserName().CmpNoCase( client2
->GetUserName() );
744 // Sort by requested file
746 const CKnownFile
* file1
= client1
->GetUploadFile();
747 const CKnownFile
* file2
= client2
->GetUploadFile();
749 if ( file1
&& file2
) {
750 return mode
* CmpAny(file1
->GetFileName(), file2
->GetFileName());
753 return mode
* CmpAny( file1
, file2
);
756 // Sort by client software
757 case 2: return mode
* CompareVersions(client1
, client2
);
760 case 3: return mode
* CmpAny( client1
->GetUploadDatarate(), client2
->GetUploadDatarate() );
762 // Sort by transferred
763 case 4: return mode
* CmpAny( client1
->GetSessionUp(), client2
->GetSessionUp() );
766 case 5: return mode
* CmpAny( client1
->GetWaitTime(), client2
->GetWaitTime() );
768 // Sort by upload time
769 case 6: return mode
* CmpAny( client1
->GetUpStartTimeDelay(), client2
->GetUpStartTimeDelay() );
772 case 7: return mode
* CmpAny( client1
->GetUploadState(), client2
->GetUploadState() );
775 case 8: return mode
* CmpAny( client1
->GetUpPartCount(), client2
->GetUpPartCount() );
778 case 9: return mode
* CmpAny( client2
->GetDownloadedTotal(), client1
->GetDownloadedTotal() );
780 // Sort by remote rank
781 case 10: return mode
* CmpAny( client2
->GetRemoteQueueRank(), client1
->GetRemoteQueueRank() );
788 static const CMuleColour
crUnavailable(240, 240, 240);
789 static const CMuleColour
crFlatUnavailable(224, 224, 224);
791 static const CMuleColour
crAvailable(104, 104, 104);
792 static const CMuleColour
crFlatAvailable(0, 0, 0);
794 void CUploadingView::DrawStatusBar( CUpDownClient
* client
, wxDC
* dc
, const wxRect
& rect1
)
800 wxPen old_pen
= dc
->GetPen();
801 wxBrush old_brush
= dc
->GetBrush();
802 bool bFlat
= thePrefs::UseFlatBar();
804 wxRect barRect
= rect
;
805 if (!bFlat
) { // round bar has a black border, the bar itself is 1 pixel less on each border
811 static CBarShader
s_StatusBar(16);
813 uint32 partCount
= client
->GetUpPartCount();
815 // Seems the partfile in the client object is not necessarily valid when bar is drawn for the first time.
816 // Keep it simple and make all parts same size.
817 s_StatusBar
.SetFileSize(partCount
* PARTSIZE
);
818 s_StatusBar
.SetHeight(barRect
.height
);
819 s_StatusBar
.SetWidth(barRect
.width
);
820 s_StatusBar
.Set3dDepth( thePrefs::Get3DDepth() );
823 for ( uint64 i
= 0; i
< partCount
; i
++ ) {
824 uint64 uStart
= PARTSIZE
* i
;
825 uEnd
= uStart
+ PARTSIZE
- 1;
827 s_StatusBar
.FillRange(uStart
, uEnd
, client
->IsUpPartAvailable(i
) ? (bFlat
? crFlatAvailable
: crAvailable
) : (bFlat
? crFlatUnavailable
: crUnavailable
));
829 // fill the rest (if partStatus is empty)
830 s_StatusBar
.FillRange(uEnd
+ 1, partCount
* PARTSIZE
- 1, bFlat
? crFlatUnavailable
: crUnavailable
);
831 s_StatusBar
.Draw(dc
, barRect
.x
, barRect
.y
, bFlat
);
835 dc
->SetPen( *wxBLACK_PEN
);
836 dc
->SetBrush( *wxTRANSPARENT_BRUSH
);
837 dc
->DrawRectangle(rect
);
840 dc
->SetPen( old_pen
);
841 dc
->SetBrush( old_brush
);
845 /////////////////////////////////////////////////////////////////////////////////////////////
846 void CQueuedView::Initialize( CClientListCtrl
* list
)
848 list
->InsertColumn( 0, _("Username"), wxLIST_FORMAT_LEFT
, 150, wxT("U") );
849 list
->InsertColumn( 1, _("File"), wxLIST_FORMAT_LEFT
, 275, wxT("F") );
850 list
->InsertColumn( 2, _("Client Software"), wxLIST_FORMAT_LEFT
, 100, wxT("C") );
851 list
->InsertColumn( 3, _("File Priority"), wxLIST_FORMAT_LEFT
, 110, wxT("p") );
852 list
->InsertColumn( 4, _("Rating"), wxLIST_FORMAT_LEFT
, 60, wxT("R") );
853 list
->InsertColumn( 5, _("Score"), wxLIST_FORMAT_LEFT
, 60, wxT("c") );
854 list
->InsertColumn( 6, _("Asked"), wxLIST_FORMAT_LEFT
, 60, wxT("A") );
855 list
->InsertColumn( 7, _("Last Seen"), wxLIST_FORMAT_LEFT
, 110, wxT("L") );
856 list
->InsertColumn( 8, _("Entered Queue"), wxLIST_FORMAT_LEFT
, 110, wxT("Q") );
857 list
->InsertColumn( 9, _("Banned"), wxLIST_FORMAT_LEFT
, 60, wxT("B") );
858 list
->InsertColumn( 10, _("Obtained Parts"), wxLIST_FORMAT_LEFT
, 100, wxT("P") );
860 // Insert any existing items on the list
861 const CClientPtrList
& uploading
= theApp
->uploadqueue
->GetWaitingList();
862 CClientPtrList::const_iterator it
= uploading
.begin();
863 for (; it
!= uploading
.end(); ++it
) {
864 list
->InsertClient( *it
, list
->GetListView() );
869 wxString
CQueuedView::GetOldColumnOrder()
871 return wxT("U,F,C,p,R,c,A,L,Q,B,P");
875 void CQueuedView::DrawCell( CUpDownClient
* client
, int column
, wxDC
* dc
, const wxRect
& rect
)
880 // These 3 are the same for both lists
884 CUploadingView::DrawCell( client
, column
, dc
, rect
);
888 if ( client
->GetUploadFile() ) {
889 buffer
= PriorityToStr( client
->GetUploadFile()->GetUpPriority(), false );
891 buffer
= _("Unknown");
897 buffer
= wxString::Format( wxT("%.1f"), (float)client
->GetScore(false,false,true) );
901 if ( client
->HasLowID() ) {
902 buffer
= wxString::Format( wxT("%i %s"), client
->GetScore(false), _("LowID") );
904 buffer
= wxString::Format(wxT("%i"),client
->GetScore(false));
909 buffer
= wxString::Format( wxT("%i"), client
->GetAskedCount() );
914 buffer
= CastSecondsToHM((::GetTickCount() - client
->GetLastUpRequest())/1000);
918 buffer
= CastSecondsToHM((::GetTickCount() - client
->GetWaitStartTime())/1000);
922 buffer
= CastSecondsToHM(client
->GetLastUpRequest()/1000);
926 buffer
= CastSecondsToHM(client
->GetWaitStartTime()/1000);
930 if ( client
->IsBanned() ) {
939 if ( client
->GetUpPartCount() ) {
940 CUploadingView::DrawStatusBar( client
, dc
, rect
);
946 dc
->DrawText( buffer
, rect
.x
, rect
.y
+ 3 );
950 int CQueuedView::SortProc(wxUIntPtr item1
, wxUIntPtr item2
, long sortData
)
952 CUpDownClient
* client1
= (CUpDownClient
*)item1
;
953 CUpDownClient
* client2
= (CUpDownClient
*)item2
;
955 // Ascending or decending?
956 int mode
= (sortData
& CMuleListCtrl::SORT_DES
) ? -1 : 1;
958 switch (sortData
& CMuleListCtrl::COLUMN_MASK
) {
960 case 0: return mode
* client1
->GetUserName().CmpNoCase( client2
->GetUserName() );
964 const CKnownFile
* file1
= client1
->GetUploadFile();
965 const CKnownFile
* file2
= client2
->GetUploadFile();
967 if ( file1
&& file2
) {
968 return mode
* CmpAny(file1
->GetFileName(), file2
->GetFileName());
971 // Place files with filenames on top
972 return -mode
* CmpAny( file1
, file2
);
975 // Sort by client software
976 case 2: return mode
* CompareVersions(client1
, client2
);
978 // Sort by file upload-priority
980 const CKnownFile
* file1
= client1
->GetUploadFile();
981 const CKnownFile
* file2
= client2
->GetUploadFile();
983 if ( file1
&& file2
) {
984 int8 prioA
= file1
->GetUpPriority();
985 int8 prioB
= file2
->GetUpPriority();
987 // Work-around for PR_VERYLOW which has value 4. See KnownFile.h for that stupidity ...
988 return mode
* CmpAny( ( prioA
!= PR_VERYLOW
? prioA
: -1 ), ( prioB
!= PR_VERYLOW
? prioB
: -1 ) );
991 // Place files with priorities on top
992 return -mode
* CmpAny( file1
, file2
);
996 case 4: return mode
* CmpAny( client1
->GetScore(false,false,true), client2
->GetScore(false,false,true) );
999 case 5: return mode
* CmpAny( client1
->GetScore(false), client2
->GetScore(false) );
1001 // Sort by Asked count
1002 case 6: return mode
* CmpAny( client1
->GetAskedCount(), client2
->GetAskedCount() );
1004 // Sort by Last seen
1005 case 7: return mode
* CmpAny( client1
->GetLastUpRequest(), client2
->GetLastUpRequest() );
1007 // Sort by entered time
1008 case 8: return mode
* CmpAny( client1
->GetWaitStartTime(), client2
->GetWaitStartTime() );
1011 case 9: return mode
* CmpAny( client1
->IsBanned(), client2
->IsBanned() );
1018 /////////////////////////////////////////////////////////////////////////////////////////////
1019 void CClientsView::Initialize( CClientListCtrl
* list
)
1021 list
->InsertColumn( 0, _("Username"), wxLIST_FORMAT_LEFT
, 150, wxT("U") );
1022 list
->InsertColumn( 1, _("Upload Status"), wxLIST_FORMAT_LEFT
, 150, wxT("S") );
1023 list
->InsertColumn( 2, _("Transferred Up"), wxLIST_FORMAT_LEFT
, 150, wxT("T") );
1024 list
->InsertColumn( 3, _("Download Status"), wxLIST_FORMAT_LEFT
, 150, wxT("s") );
1025 list
->InsertColumn( 4, _("Transferred Down"), wxLIST_FORMAT_LEFT
, 150, wxT("t") );
1026 list
->InsertColumn( 5, _("Client Software"), wxLIST_FORMAT_LEFT
, 150, wxT("C") );
1027 list
->InsertColumn( 6, _("Connected"), wxLIST_FORMAT_LEFT
, 150, wxT("c") );
1028 list
->InsertColumn( 7, _("Userhash"), wxLIST_FORMAT_LEFT
, 150, wxT("H") );
1029 list
->InsertColumn( 8, _("Encrypted"), wxLIST_FORMAT_LEFT
, 100, wxT("E") );
1030 list
->InsertColumn( 9, _("Hide shared files"), wxLIST_FORMAT_LEFT
, 100, wxT("h") );
1032 const CClientList::IDMap
& clist
= theApp
->clientlist
->GetClientList();
1033 CClientList::IDMap::const_iterator it
= clist
.begin();
1035 for ( ; it
!= clist
.end(); ++it
) {
1036 list
->InsertClient( it
->second
, list
->GetListView() );
1041 wxString
CClientsView::GetOldColumnOrder()
1043 return wxT("U,S,T,s,t,C,c,H,E,h");
1047 void CClientsView::DrawCell( CUpDownClient
* client
, int column
, wxDC
* dc
, const wxRect
& rect
)
1053 CUploadingView::DrawCell( client
, column
, dc
, rect
);
1057 CUploadingView::DrawCell( client
, 7, dc
, rect
);
1061 buffer
= CastItoXBytes( client
->GetUploadedTotal() );
1066 buffer
= DownloadStateToStr( client
->GetDownloadState(),
1067 client
->IsRemoteQueueFull() );
1071 buffer
= CastItoXBytes( client
->GetDownloadedTotal() );
1075 buffer
= client
->GetClientVerString();
1079 if ( client
->IsConnected() ) {
1088 buffer
= client
->GetUserHash().Encode();
1092 buffer
= client
->HasObfuscatedConnectionBeenEstablished() ?
1097 buffer
= client
->GetUserName().IsEmpty() ?
1099 (client
->HasDisabledSharedFiles() ? _("Yes") : _("No"));
1103 dc
->DrawText( buffer
, rect
.x
, rect
.y
+ 3 );
1107 int CClientsView::SortProc(wxUIntPtr item1
, wxUIntPtr item2
, long sortData
)
1109 CUpDownClient
* client1
= (CUpDownClient
*)item1
;
1110 CUpDownClient
* client2
= (CUpDownClient
*)item2
;
1112 // Ascending or decending?
1113 int mode
= (sortData
& CMuleListCtrl::SORT_DES
) ? -1 : 1;
1115 switch (sortData
& CMuleListCtrl::COLUMN_MASK
) {
1117 case 0: return mode
* client1
->GetUserName().CmpNoCase( client2
->GetUserName() );
1119 // Sort by Uploading-state
1120 case 1: return mode
* CmpAny( client1
->GetUploadState(), client2
->GetUploadState() );
1122 // Sort by data-uploaded
1124 return mode
* CmpAny( client1
->GetUploadedTotal(), client2
->GetUploadedTotal() );
1126 // Sort by Downloading-state
1128 if( client1
->GetDownloadState() == client2
->GetDownloadState() ){
1129 if( client1
->IsRemoteQueueFull() && client2
->IsRemoteQueueFull() ) {
1131 } else if( client1
->IsRemoteQueueFull() ) {
1133 } else if( client2
->IsRemoteQueueFull() ) {
1139 return mode
* CmpAny( client1
->GetDownloadState(), client2
->GetDownloadState() );
1141 // Sort by data downloaded
1143 return mode
* CmpAny( client1
->GetDownloadedTotal(), client2
->GetDownloadedTotal() );
1145 // Sort by client-software
1146 case 5: return mode
* CompareVersions(client1
, client2
);
1148 // Sort by connection
1149 case 6: return mode
* CmpAny( client1
->IsConnected(), client2
->IsConnected() );
1151 // Sort by user-hash
1152 case 7: return mode
* CmpAny( client1
->GetUserHash(), client2
->GetUserHash() );
1154 // Sort by Obfuscation state
1155 case 8: return mode
* CmpAny( client2
->HasObfuscatedConnectionBeenEstablished(), client1
->HasObfuscatedConnectionBeenEstablished() );
1157 // Sort by Shared Files DISabled
1158 case 9: return mode
* CmpAny( client2
->HasDisabledSharedFiles(), client1
->HasDisabledSharedFiles() );
1165 // File_checked_for_headers