1 //
2 // This file is part of the aMule Project.
3 //
4 // Copyright (c) 2003-2011 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.
10 //
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.
15 //
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
24 //
25 
26 #include "SharedFilesCtrl.h"	// Interface declarations
27 
28 #include <common/MenuIDs.h>
29 
30 #include "muuli_wdr.h"			// Needed for ID_SHFILELIST
31 #include "SharedFilesWnd.h"		// Needed for CSharedFilesWnd
32 #include "amuleDlg.h"			// Needed for CamuleDlg
33 #include "CommentDialog.h"		// Needed for CCommentDialog
34 #include "PartFile.h"			// Needed for CPartFile
35 #include "SharedFileList.h"		// Needed for CKnownFileMap
36 #include "amule.h"				// Needed for theApp
37 #include "ServerConnect.h"		// Needed for CServerConnect
38 #include "Preferences.h"		// Needed for thePrefs
39 #include "BarShader.h"			// Needed for CBarShader
40 #include "DataToText.h"			// Needed for PriorityToStr
41 #include "GuiEvents.h"			// Needed for CoreNotify_*
42 #include "MuleCollection.h"		// Needed for CMuleCollection
43 #include "DownloadQueue.h"		// Needed for CDownloadQueue
44 #include "TransferWnd.h"		// Needed for CTransferWnd
45 
46 
47 BEGIN_EVENT_TABLE(CSharedFilesCtrl,CMuleListCtrl)
48 	EVT_LIST_ITEM_RIGHT_CLICK(-1, CSharedFilesCtrl::OnRightClick)
49 
50 	EVT_MENU( MP_PRIOVERYLOW,	CSharedFilesCtrl::OnSetPriority )
51 	EVT_MENU( MP_PRIOLOW,		CSharedFilesCtrl::OnSetPriority )
52 	EVT_MENU( MP_PRIONORMAL,	CSharedFilesCtrl::OnSetPriority )
53 	EVT_MENU( MP_PRIOHIGH,		CSharedFilesCtrl::OnSetPriority )
54 	EVT_MENU( MP_PRIOVERYHIGH,	CSharedFilesCtrl::OnSetPriority )
55 	EVT_MENU( MP_POWERSHARE,	CSharedFilesCtrl::OnSetPriority )
56 	EVT_MENU( MP_PRIOAUTO,		CSharedFilesCtrl::OnSetPriorityAuto )
57 
58 	EVT_MENU( MP_CMT,			CSharedFilesCtrl::OnEditComment )
59 	EVT_MENU( MP_ADDCOLLECTION,		CSharedFilesCtrl::OnAddCollection )
60 	EVT_MENU( MP_GETMAGNETLINK,		CSharedFilesCtrl::OnCreateURI )
61 	EVT_MENU( MP_GETED2KLINK,				CSharedFilesCtrl::OnCreateURI )
62 	EVT_MENU( MP_GETSOURCEED2KLINK,			CSharedFilesCtrl::OnCreateURI )
63 	EVT_MENU( MP_GETCRYPTSOURCEDED2KLINK,			CSharedFilesCtrl::OnCreateURI )
64 	EVT_MENU( MP_GETHOSTNAMESOURCEED2KLINK,	CSharedFilesCtrl::OnCreateURI )
65 	EVT_MENU( MP_GETHOSTNAMECRYPTSOURCEED2KLINK,			CSharedFilesCtrl::OnCreateURI )
66 	EVT_MENU( MP_GETAICHED2KLINK,	CSharedFilesCtrl::OnCreateURI )
67 	EVT_MENU( MP_GETAICHED2KLINKSRC,	CSharedFilesCtrl::OnCreateURI )
68 	EVT_MENU( MP_RENAME,		CSharedFilesCtrl::OnRename )
69 	EVT_MENU( MP_WS,		CSharedFilesCtrl::OnGetFeedback )
70 
71 
72 	EVT_CHAR( CSharedFilesCtrl::OnKeyPressed )
73 END_EVENT_TABLE()
74 
75 enum SharedFilesListColumns {
76 	ID_SHARED_COL_NAME = 0,
77 	ID_SHARED_COL_SIZE,
78 	ID_SHARED_COL_TYPE,
79 	ID_SHARED_COL_PRIO,
80 	ID_SHARED_COL_ID,
81 	ID_SHARED_COL_REQ,
82 	ID_SHARED_COL_AREQ,
83 	ID_SHARED_COL_TRA,
84 	ID_SHARED_COL_RTIO,
85 	ID_SHARED_COL_PART,
86 	ID_SHARED_COL_CMPL,
87 	ID_SHARED_COL_PATH
88 };
89 
90 
CSharedFilesCtrl(wxWindow * parent,int id,const wxPoint & pos,wxSize size,int flags)91 CSharedFilesCtrl::CSharedFilesCtrl(wxWindow* parent, int id, const wxPoint& pos, wxSize size, int flags)
92 	: CMuleListCtrl(parent, id, pos, size, flags | wxLC_OWNERDRAW )
93 {
94 	// Setting the sorter function.
95 	SetSortFunc( SortProc );
96 
97 	// Set the table-name (for loading and saving preferences).
98 	SetTableName( wxT("Shared") );
99 
100 	m_menu=NULL;
101 
102 	InsertColumn(ID_SHARED_COL_NAME, _("File Name"),		wxLIST_FORMAT_LEFT, 250, wxT("N") );
103 	InsertColumn(ID_SHARED_COL_SIZE, _("Size"),			wxLIST_FORMAT_LEFT, 100, wxT("Z") );
104 	InsertColumn(ID_SHARED_COL_TYPE, _("Type"),			wxLIST_FORMAT_LEFT,  50, wxT("Y") );
105 	InsertColumn(ID_SHARED_COL_PRIO, _("Priority"),			wxLIST_FORMAT_LEFT,  70, wxT("p") );
106 	InsertColumn(ID_SHARED_COL_ID,   _("FileID"),			wxLIST_FORMAT_LEFT, 220, wxT("I") );
107 	InsertColumn(ID_SHARED_COL_REQ,  _("Requests"),			wxLIST_FORMAT_LEFT, 100, wxT("Q") );
108 	InsertColumn(ID_SHARED_COL_AREQ, _("Accepted Requests"),	wxLIST_FORMAT_LEFT, 100, wxT("A") );
109 	InsertColumn(ID_SHARED_COL_TRA,  _("Transferred Data"),		wxLIST_FORMAT_LEFT, 120, wxT("T") );
110 	InsertColumn(ID_SHARED_COL_RTIO, _("Share Ratio"),		wxLIST_FORMAT_LEFT, 100, wxT("R") );
111 	InsertColumn(ID_SHARED_COL_PART, _("Obtained Parts"),		wxLIST_FORMAT_LEFT, 120, wxT("P") );
112 	InsertColumn(ID_SHARED_COL_CMPL, _("Complete Sources"),		wxLIST_FORMAT_LEFT, 120, wxT("C") );
113 	InsertColumn(ID_SHARED_COL_PATH, _("Directory Path"),		wxLIST_FORMAT_LEFT, 220, wxT("D") );
114 
115 	LoadSettings();
116 }
117 
118 
GetOldColumnOrder() const119 wxString CSharedFilesCtrl::GetOldColumnOrder() const
120 {
121 	return wxT("N,Z,Y,p,I,Q,A,T,R,P,C,D");
122 }
123 
124 
~CSharedFilesCtrl()125 CSharedFilesCtrl::~CSharedFilesCtrl()
126 {
127 }
128 
129 
OnRightClick(wxListEvent & event)130 void CSharedFilesCtrl::OnRightClick(wxListEvent& event)
131 {
132 	long item_hit = CheckSelection(event);
133 
134 	if ( (m_menu == NULL) && (item_hit != -1)) {
135 		m_menu = new wxMenu(_("Shared Files"));
136 		wxMenu* prioMenu = new wxMenu();
137 		prioMenu->AppendCheckItem(MP_PRIOVERYLOW, _("Very low"));
138 		prioMenu->AppendCheckItem(MP_PRIOLOW, _("Low"));
139 		prioMenu->AppendCheckItem(MP_PRIONORMAL, _("Normal"));
140 		prioMenu->AppendCheckItem(MP_PRIOHIGH, _("High"));
141 		prioMenu->AppendCheckItem(MP_PRIOVERYHIGH, _("Very High"));
142 		prioMenu->AppendCheckItem(MP_POWERSHARE, _("Release"));
143 		prioMenu->AppendCheckItem(MP_PRIOAUTO, _("Auto"));
144 
145 		m_menu->Append(0,_("Priority"),prioMenu);
146 		m_menu->AppendSeparator();
147 
148 		CKnownFile* file = reinterpret_cast<CKnownFile*>(GetItemData(item_hit));
149 		if (file->GetFileComment().IsEmpty() && !file->GetFileRating()) {
150 			m_menu->Append(MP_CMT, _("Add Comment/Rating"));
151 		} else {
152 			m_menu->Append(MP_CMT, _("Edit Comment/Rating"));
153 		}
154 
155 		m_menu->AppendSeparator();
156 		m_menu->Append(MP_RENAME, _("Rename"));
157 		m_menu->AppendSeparator();
158 
159 		if (file->GetFileName().GetExt() == wxT("emulecollection")) {
160 			m_menu->Append( MP_ADDCOLLECTION, _("Add files in collection to transfer list"));
161 			m_menu->AppendSeparator();
162 		}
163 		m_menu->Append(MP_GETMAGNETLINK,_("Copy magnet &URI to clipboard"));
164 		m_menu->Append(MP_GETED2KLINK,_("Copy eD2k &link to clipboard"));
165 		m_menu->Append(MP_GETSOURCEED2KLINK,_("Copy eD2k link to clipboard (&Source)"));
166 		m_menu->Append(MP_GETCRYPTSOURCEDED2KLINK,_("Copy eD2k link to clipboard (Source) (&With Crypt options)"));
167 		m_menu->Append(MP_GETHOSTNAMESOURCEED2KLINK,_("Copy eD2k link to clipboard (&Hostname)"));
168 		m_menu->Append(MP_GETHOSTNAMECRYPTSOURCEED2KLINK,_("Copy eD2k link to clipboard (Hostname) (With &Crypt options)"));
169 		m_menu->Append(MP_GETAICHED2KLINK,_("Copy eD2k link to clipboard (&AICH info)"));
170 		m_menu->Append(MP_GETAICHED2KLINKSRC,_("Copy eD2k link to clipboard (&AICH info + Source)"));
171 		m_menu->Append(MP_WS,_("Copy feedback to clipboard"));
172 
173 		m_menu->Enable(MP_GETAICHED2KLINK, file->HasProperAICHHashSet());
174 		m_menu->Enable(MP_GETAICHED2KLINKSRC, file->HasProperAICHHashSet());
175 		m_menu->Enable(MP_GETHOSTNAMESOURCEED2KLINK, !thePrefs::GetYourHostname().IsEmpty());
176 		m_menu->Enable(MP_GETHOSTNAMECRYPTSOURCEED2KLINK, !thePrefs::GetYourHostname().IsEmpty());
177 
178 		int priority = file->IsAutoUpPriority() ? PR_AUTO : file->GetUpPriority();
179 
180 		prioMenu->Check(MP_PRIOVERYLOW,	priority == PR_VERYLOW);
181 		prioMenu->Check(MP_PRIOLOW,	priority == PR_LOW);
182 		prioMenu->Check(MP_PRIONORMAL,	priority == PR_NORMAL);
183 		prioMenu->Check(MP_PRIOHIGH,	priority == PR_HIGH);
184 		prioMenu->Check(MP_PRIOVERYHIGH,priority == PR_VERYHIGH);
185 		prioMenu->Check(MP_POWERSHARE,	priority == PR_POWERSHARE);
186 		prioMenu->Check(MP_PRIOAUTO,	priority == PR_AUTO);
187 
188 		PopupMenu( m_menu, event.GetPoint() );
189 
190 		delete m_menu;
191 
192 		m_menu = NULL;
193 	}
194 }
195 
196 
OnGetFeedback(wxCommandEvent & WXUNUSED (event))197 void CSharedFilesCtrl::OnGetFeedback(wxCommandEvent& WXUNUSED(event))
198 {
199 	wxString feed;
200 	long index = GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
201 	while (index != -1) {
202 		if (feed.IsEmpty()) {
203 			feed = CFormat(_("Feedback from: %s (%s)\n\n")) % thePrefs::GetUserNick() % theApp->GetFullMuleVersion();
204 		} else {
205 			feed += wxT("\n");
206 		}
207 		feed += reinterpret_cast<CKnownFile*>(GetItemData(index))->GetFeedback();
208 		index = GetNextItem(index, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
209 	}
210 
211 	if (!feed.IsEmpty()) {
212 		theApp->CopyTextToClipboard(feed);
213 	}
214 }
215 
216 
ShowFileList()217 void CSharedFilesCtrl::ShowFileList()
218 {
219 	Freeze();
220 	DeleteAllItems();
221 
222 	std::vector<CKnownFile*> files;
223 	theApp->sharedfiles->CopyFileList(files);
224 	for (unsigned i = 0; i < files.size(); ++i) {
225 		DoShowFile(files[i], true);
226 	}
227 
228 	SortList();
229 	ShowFilesCount();
230 
231 	Thaw();
232 }
233 
234 
RemoveFile(CKnownFile * toRemove)235 void CSharedFilesCtrl::RemoveFile(CKnownFile *toRemove)
236 {
237 	long index = FindItem( -1, reinterpret_cast<wxUIntPtr>(toRemove) );
238 
239 	if ( index != -1 ) {
240 		DeleteItem( index );
241 
242 		ShowFilesCount();
243 	}
244 }
245 
246 
ShowFile(CKnownFile * file)247 void CSharedFilesCtrl::ShowFile(CKnownFile* file)
248 {
249 	DoShowFile(file, false);
250 }
251 
252 
DoShowFile(CKnownFile * file,bool batch)253 void CSharedFilesCtrl::DoShowFile(CKnownFile* file, bool batch)
254 {
255 	wxUIntPtr ptr = reinterpret_cast<wxUIntPtr>(file);
256 	if ((!batch) && (FindItem(-1, ptr) > -1)) {
257 		return;
258 	}
259 
260 	const long insertPos = (batch ? GetItemCount() : GetInsertPos(ptr));
261 
262 	long newitem = InsertItem(insertPos, wxEmptyString);
263 	SetItemPtrData( newitem, ptr );
264 
265 	if (!batch) {
266 		ShowFilesCount();
267 	}
268 }
269 
OnSetPriority(wxCommandEvent & event)270 void CSharedFilesCtrl::OnSetPriority( wxCommandEvent& event )
271 {
272 	int priority = 0;
273 
274 	switch ( event.GetId() ) {
275 		case MP_PRIOVERYLOW:	priority = PR_VERYLOW;	break;
276 		case MP_PRIOLOW:		priority = PR_LOW;		break;
277 		case MP_PRIONORMAL:		priority = PR_NORMAL;	break;
278 		case MP_PRIOHIGH:		priority = PR_HIGH;		break;
279 		case MP_PRIOVERYHIGH:	priority = PR_VERYHIGH;	break;
280 		case MP_POWERSHARE:		priority = PR_POWERSHARE; break;
281 	}
282 
283 	long index = GetNextItem( -1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED );
284 
285 	while( index != -1 ) {
286 		CKnownFile* file = reinterpret_cast<CKnownFile*>(GetItemData(index));
287 		CoreNotify_KnownFile_Up_Prio_Set( file, priority );
288 
289 		RefreshItem( index );
290 
291 		index = GetNextItem( index, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED );
292 	}
293 }
294 
295 
OnSetPriorityAuto(wxCommandEvent & WXUNUSED (event))296 void CSharedFilesCtrl::OnSetPriorityAuto( wxCommandEvent& WXUNUSED(event) )
297 {
298 	long index = GetNextItem( -1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED );
299 
300 	while( index != -1 ) {
301 		CKnownFile* file = reinterpret_cast<CKnownFile*>(GetItemData(index));
302 		CoreNotify_KnownFile_Up_Prio_Auto(file);
303 
304 		RefreshItem( index );
305 
306 		index = GetNextItem( index, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED );
307 	}
308 }
309 
310 
OnCreateURI(wxCommandEvent & event)311 void CSharedFilesCtrl::OnCreateURI( wxCommandEvent& event )
312 {
313 	wxString URIs;
314 
315 	if ( event.GetId() == MP_GETSOURCEED2KLINK || event.GetId() == MP_GETCRYPTSOURCEDED2KLINK) {
316 		if ( !(	(theApp->IsConnectedED2K() && !theApp->serverconnect->IsLowID())
317 				|| (theApp->IsConnectedKad() && !theApp->IsFirewalledKad() ))) {
318 			wxMessageBox(_("You need a HighID to create a valid sourcelink"), _("WARNING"), wxOK | wxICON_ERROR, this);
319 			return;
320 		}
321 	}
322 
323 	long index = GetNextItem( -1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED );
324 
325 	while( index != -1 ) {
326 		CKnownFile* file = reinterpret_cast<CKnownFile*>(GetItemData(index));
327 
328 		switch ( event.GetId() ) {
329 			case MP_GETMAGNETLINK:				URIs += theApp->CreateMagnetLink( file ) + wxT("\n");				break;
330 			case MP_GETED2KLINK:				URIs += theApp->CreateED2kLink( file ) + wxT("\n");					break;
331 			case MP_GETSOURCEED2KLINK:			URIs += theApp->CreateED2kLink( file , true) + wxT("\n");			break;
332 			case MP_GETCRYPTSOURCEDED2KLINK:	URIs += theApp->CreateED2kLink( file , true, false, true) + wxT("\n");			break;
333 			case MP_GETHOSTNAMESOURCEED2KLINK:	URIs += theApp->CreateED2kLink( file , true, true) + wxT("\n");	break;
334 			case MP_GETHOSTNAMECRYPTSOURCEED2KLINK:			URIs += theApp->CreateED2kLink( file, true, true, true ) + wxT("\n");	break;
335 			case MP_GETAICHED2KLINK:			URIs += theApp->CreateED2kLink(file, false, false, false, true) + wxT("\n");		break;
336 			case MP_GETAICHED2KLINKSRC:			URIs += theApp->CreateED2kLink(file, true,  false, false, true) + wxT("\n");		break;
337 		}
338 
339 		index = GetNextItem( index, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED );
340 	}
341 
342 	if ( !URIs.IsEmpty() ) {
343 		theApp->CopyTextToClipboard( URIs.RemoveLast() );
344 	}
345 }
346 
347 
OnEditComment(wxCommandEvent & WXUNUSED (event))348 void CSharedFilesCtrl::OnEditComment( wxCommandEvent& WXUNUSED(event) )
349 {
350 	long index = GetNextItem( -1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED );
351 
352 	if ( index != -1 ) {
353 		CKnownFile* file = reinterpret_cast<CKnownFile*>(GetItemData(index));
354 
355 		CCommentDialog dialog( this, file );
356 
357 		dialog.ShowModal();
358 	}
359 }
360 
361 
SortProc(wxUIntPtr item1,wxUIntPtr item2,long sortData)362 int CSharedFilesCtrl::SortProc(wxUIntPtr item1, wxUIntPtr item2, long sortData)
363 {
364 	CKnownFile* file1 = reinterpret_cast<CKnownFile*>(item1);
365 	CKnownFile* file2 = reinterpret_cast<CKnownFile*>(item2);
366 
367 	int mod = (sortData & CMuleListCtrl::SORT_DES) ? -1 : 1;
368 	bool altSorting = (sortData & CMuleListCtrl::SORT_ALT) > 0;
369 
370 	switch (sortData & CMuleListCtrl::COLUMN_MASK) {
371 		// Sort by filename.
372 		case  ID_SHARED_COL_NAME:
373 			return mod * CmpAny(file1->GetFileName(), file2->GetFileName());
374 
375 		// Sort by filesize.
376 		case  ID_SHARED_COL_SIZE:
377 			return mod * CmpAny( file1->GetFileSize(), file2->GetFileSize() );
378 
379 		// Sort by filetype.
380 		case  ID_SHARED_COL_TYPE:
381 			return mod * GetFiletypeByName(file1->GetFileName()).CmpNoCase(GetFiletypeByName( file2->GetFileName()) );
382 
383 		// Sort by priority.
384 		case  ID_SHARED_COL_PRIO: {
385 			int8 prioA = file1->GetUpPriority();
386 			int8 prioB = file2->GetUpPriority();
387 
388 			// Work-around for PR_VERYLOW which has value 4. See KnownFile.h for that stupidity ...
389 			return mod * CmpAny( ( prioB != PR_VERYLOW ? prioB : -1 ), ( prioA != PR_VERYLOW ? prioA : -1 ) );
390 		}
391 
392 		// Sort by fileID.
393 		case  ID_SHARED_COL_ID:
394 			return mod * file1->GetFileHash().Encode().Cmp( file2->GetFileHash().Encode() );
395 
396 		// Sort by Requests this session.
397 		case  ID_SHARED_COL_REQ:
398 			if (altSorting) {
399 				return mod * CmpAny( file1->statistic.GetAllTimeRequests(), file2->statistic.GetAllTimeRequests() );
400 			} else {
401 				return mod * CmpAny( file1->statistic.GetRequests(), file2->statistic.GetRequests() );
402 			}
403 
404 		// Sort by accepted requests. Ascending.
405 		case  ID_SHARED_COL_AREQ:
406 			if (altSorting) {
407 				return mod * CmpAny( file1->statistic.GetAllTimeAccepts(), file2->statistic.GetAllTimeAccepts() );
408 			} else {
409 				return mod * CmpAny( file1->statistic.GetAccepts(), file2->statistic.GetAccepts() );
410 			}
411 
412 		// Sort by transferred. Ascending.
413 		case  ID_SHARED_COL_TRA:
414 			if (altSorting) {
415 				return mod * CmpAny( file1->statistic.GetAllTimeTransferred(), file2->statistic.GetAllTimeTransferred() );
416 			} else {
417 				return mod * CmpAny( file1->statistic.GetTransferred(), file2->statistic.GetTransferred() );
418 			}
419 
420 		// Sort by Share Ratio. Ascending.
421 		case  ID_SHARED_COL_RTIO:
422 			return mod * CmpAny( (double)file1->statistic.GetAllTimeTransferred() / file1->GetFileSize(),
423 					(double)file2->statistic.GetAllTimeTransferred() / file2->GetFileSize() );
424 
425 		// Complete sources asc
426 		case ID_SHARED_COL_CMPL:
427 			return mod * CmpAny( file1->m_nCompleteSourcesCount, file2->m_nCompleteSourcesCount );
428 
429 		// Folders ascending
430 		case ID_SHARED_COL_PATH: {
431 			if ( file1->IsPartFile() && file2->IsPartFile() )
432 				return mod *  0;
433 			if ( file1->IsPartFile() )
434 				return mod * -1;
435 			if ( file2->IsPartFile() )
436 				return mod *  1;
437 
438 			return mod * CmpAny(file1->GetFilePath(), file2->GetFilePath());
439 		}
440 
441 		default:
442 			return 0;
443 	}
444 }
445 
446 
UpdateItem(CKnownFile * toupdate)447 void CSharedFilesCtrl::UpdateItem(CKnownFile* toupdate)
448 {
449 	long result = FindItem( -1, reinterpret_cast<wxUIntPtr>(toupdate) );
450 
451 	if ( result > -1 ) {
452 		RefreshItem(result);
453 
454 		if ( GetItemState( result, wxLIST_STATE_SELECTED ) ) {
455 			theApp->amuledlg->m_sharedfileswnd->SelectionUpdated();
456 		}
457 	}
458 }
459 
460 
ShowFilesCount()461 void CSharedFilesCtrl::ShowFilesCount()
462 {
463 	wxStaticText* label = CastByName( wxT("sharedFilesLabel"), GetParent(), wxStaticText );
464 
465 	label->SetLabel(CFormat(_("Shared Files (%i)")) % GetItemCount());
466 	label->GetParent()->Layout();
467 	// If file list was updated, the "selection" is involved too, if we chose to show clients for all files.
468 	// So update client list here too.
469 	theApp->amuledlg->m_sharedfileswnd->SelectionUpdated();
470 }
471 
472 
OnDrawItem(int item,wxDC * dc,const wxRect & rect,const wxRect & rectHL,bool highlighted)473 void CSharedFilesCtrl::OnDrawItem( int item, wxDC* dc, const wxRect& rect, const wxRect& rectHL, bool highlighted )
474 {
475 	CKnownFile *file = reinterpret_cast<CKnownFile*>(GetItemData(item));
476 	wxASSERT( file );
477 
478 	if ( highlighted ) {
479 		CMuleColour newcol(GetFocus() ? wxSYS_COLOUR_HIGHLIGHT : wxSYS_COLOUR_BTNSHADOW);
480 		dc->SetBackground(newcol.Blend(125).GetBrush());
481 		dc->SetTextForeground( CMuleColour(wxSYS_COLOUR_HIGHLIGHTTEXT));
482 		// The second blending goes over the first one.
483 		dc->SetPen(newcol.Blend(65).GetPen());
484 	} else {
485 		dc->SetBackground( CMuleColour(wxSYS_COLOUR_LISTBOX).GetBrush() );
486 		dc->SetTextForeground(CMuleColour(wxSYS_COLOUR_WINDOWTEXT));
487 		dc->SetPen(*wxTRANSPARENT_PEN);
488 	}
489 
490 	dc->SetBrush(dc->GetBackground());
491 	dc->DrawRectangle(rectHL);
492 	dc->SetPen(*wxTRANSPARENT_PEN);
493 
494 	// Offset based on the height of the fonts
495 	const int textVOffset = ( rect.GetHeight() - dc->GetCharHeight() ) / 2;
496 	// Empty space to each side of a column
497 	const int SPARE_PIXELS_HORZ	= 4;
498 
499 	// The leftmost position of the current column
500 	int columnLeft = 0;
501 
502 	for ( int i = 0; i < GetColumnCount(); ++i ) {
503 		const int columnWidth = GetColumnWidth(i);
504 
505 		if (columnWidth > 2*SPARE_PIXELS_HORZ) {
506 			wxRect columnRect(
507 				columnLeft + SPARE_PIXELS_HORZ, rect.y,
508 				columnWidth - 2 * SPARE_PIXELS_HORZ, rect.height);
509 
510 			wxDCClipper clipper(*dc, columnRect);
511 
512 			wxString textBuffer;
513 			switch ( i ) {
514 				case ID_SHARED_COL_NAME:
515 					textBuffer = file->GetFileName().GetPrintable();
516 
517 					if (file->GetFileRating() || file->GetFileComment().Length()) {
518 						int image = Client_CommentOnly_Smiley;
519 						if (file->GetFileRating()) {
520 							image = Client_InvalidRating_Smiley + file->GetFileRating() - 1;
521 						}
522 
523 						wxASSERT(image >= Client_InvalidRating_Smiley);
524 						wxASSERT(image <= Client_CommentOnly_Smiley);
525 
526 						int imgWidth = 16;
527 
528 						theApp->amuledlg->m_imagelist.Draw(image, *dc, columnRect.x,
529 								columnRect.y + 1, wxIMAGELIST_DRAW_TRANSPARENT);
530 
531 						// Move the text to the right
532 						columnRect.x += (imgWidth + 4);
533 					}
534 
535 					break;
536 
537 				case ID_SHARED_COL_SIZE:
538 					textBuffer = CastItoXBytes(file->GetFileSize());
539 					break;
540 
541 				case ID_SHARED_COL_TYPE:
542 					textBuffer = GetFiletypeByName(file->GetFileName());
543 					break;
544 
545 				case ID_SHARED_COL_PRIO:
546 					textBuffer = PriorityToStr(file->GetUpPriority(), file->IsAutoUpPriority());
547 					break;
548 
549 				case ID_SHARED_COL_ID:
550 					textBuffer = file->GetFileHash().Encode();
551 					break;
552 
553 				case ID_SHARED_COL_REQ:
554 					textBuffer = CFormat(wxT("%u (%u)"))
555 							% file->statistic.GetRequests()
556 							% file->statistic.GetAllTimeRequests();
557 					break;
558 
559 				case ID_SHARED_COL_AREQ:
560 					textBuffer = CFormat(wxT("%u (%u)"))
561 							% file->statistic.GetAccepts()
562 							% file->statistic.GetAllTimeAccepts();
563 					break;
564 
565 				case ID_SHARED_COL_TRA:
566 					textBuffer = CastItoXBytes(file->statistic.GetTransferred())
567 						+ wxT(" (") + CastItoXBytes(file->statistic.GetAllTimeTransferred()) + wxT(")");
568 					break;
569 
570 				case ID_SHARED_COL_RTIO:
571 					textBuffer = CFormat(wxT("%.2f")) %	((double)file->statistic.GetAllTimeTransferred() / file->GetFileSize());
572 					break;
573 
574 				case ID_SHARED_COL_PART:
575 					if ( file->GetPartCount() ) {
576 						wxRect barRect(columnRect.x, columnRect. y + 1,
577 							columnRect.width, columnRect.height - 2);
578 
579 						DrawAvailabilityBar(file, dc, barRect);
580 					}
581 					break;
582 
583 				case ID_SHARED_COL_CMPL:
584 					if ( file->m_nCompleteSourcesCountLo == 0 ) {
585 						if ( file->m_nCompleteSourcesCountHi ) {
586 							textBuffer = CFormat(wxT("< %u")) % file->m_nCompleteSourcesCountHi;
587 						} else {
588 							textBuffer = wxT("0");
589 						}
590 					} else if (file->m_nCompleteSourcesCountLo == file->m_nCompleteSourcesCountHi) {
591 						textBuffer = CFormat(wxT("%u")) % file->m_nCompleteSourcesCountLo;
592 					} else {
593 						textBuffer = CFormat(wxT("%u - %u")) % file->m_nCompleteSourcesCountLo % file->m_nCompleteSourcesCountHi;
594 					}
595 
596 					break;
597 
598 				case ID_SHARED_COL_PATH:
599 					if ( file->IsPartFile() ) {
600 						textBuffer = _("[PartFile]");
601 					} else {
602 						textBuffer = file->GetFilePath().GetPrintable();
603 					}
604 			}
605 
606 			if (!textBuffer.IsEmpty()) {
607 				dc->DrawText(textBuffer, columnRect.x, columnRect.y + textVOffset);
608 			}
609 		}
610 
611 		// Move to the next column
612 		columnLeft += columnWidth;
613 	}
614 }
615 
616 
GetTTSText(unsigned item) const617 wxString CSharedFilesCtrl::GetTTSText(unsigned item) const
618 {
619 	return reinterpret_cast<CKnownFile*>(GetItemData(item))->GetFileName().GetPrintable();
620 }
621 
622 
AltSortAllowed(unsigned column) const623 bool CSharedFilesCtrl::AltSortAllowed(unsigned column) const
624 {
625 	switch ( column ) {
626 		case ID_SHARED_COL_REQ:
627 		case ID_SHARED_COL_AREQ:
628 		case ID_SHARED_COL_TRA:
629 			return true;
630 
631 		default:
632 			return false;
633 	}
634 }
635 
636 
DrawAvailabilityBar(CKnownFile * file,wxDC * dc,const wxRect & rect) const637 void CSharedFilesCtrl::DrawAvailabilityBar(CKnownFile* file, wxDC* dc, const wxRect& rect ) const
638 {
639 	// Reference to the availability list
640 	const ArrayOfUInts16& list = file->IsPartFile() ?
641 		static_cast<CPartFile*>(file)->m_SrcpartFrequency :
642 		file->m_AvailPartFrequency;
643 	wxPen   old_pen   = dc->GetPen();
644 	wxBrush old_brush = dc->GetBrush();
645 	bool bFlat = thePrefs::UseFlatBar();
646 
647 	wxRect barRect = rect;
648 	if (!bFlat) { // round bar has a black border, the bar itself is 1 pixel less on each border
649 		barRect.x ++;
650 		barRect.y ++;
651 		barRect.height -= 2;
652 		barRect.width -= 2;
653 	}
654 	static CBarShader s_ChunkBar;
655 	s_ChunkBar.SetFileSize( file->GetFileSize() );
656 	s_ChunkBar.SetHeight( barRect.GetHeight() );
657 	s_ChunkBar.SetWidth( barRect.GetWidth() );
658 	s_ChunkBar.Set3dDepth( CPreferences::Get3DDepth() );
659 	uint64 end = 0;
660 	for ( unsigned int i = 0; i < list.size(); ++i ) {
661 		uint64 start = PARTSIZE * static_cast<uint64>(i);
662 		end   = PARTSIZE * static_cast<uint64>(i + 1);
663 		s_ChunkBar.FillRange(start, end, CMuleColour(list[i] ? 0 : 255, list[i] ? ((210-(22*( list[i] - 1 ) ) < 0) ? 0 : (210-(22*( list[i] - 1 ) ))) : 0, list[i] ? 255 : 0));
664 	}
665 	s_ChunkBar.FillRange(end + 1, file->GetFileSize() - 1, CMuleColour(255, 0, 0));
666 	s_ChunkBar.Draw(dc, barRect.x, barRect.y, bFlat);
667 
668 	if (!bFlat) {
669 		// Draw black border
670 		dc->SetPen( *wxBLACK_PEN );
671 		dc->SetBrush( *wxTRANSPARENT_BRUSH );
672 		dc->DrawRectangle(rect);
673 	}
674 
675 	dc->SetPen( old_pen );
676 	dc->SetBrush( old_brush );
677 }
678 
OnRename(wxCommandEvent & WXUNUSED (event))679 void CSharedFilesCtrl::OnRename( wxCommandEvent& WXUNUSED(event) )
680 {
681 	int item = GetNextItem( -1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED );
682 	if ( item != -1 ) {
683 		CKnownFile* file = reinterpret_cast<CKnownFile*>(GetItemData(item));
684 
685 		wxString strNewName = ::wxGetTextFromUser(
686 			_("Enter new name for this file:"),
687 			_("File rename"), file->GetFileName().GetPrintable());
688 
689 		CPath newName = CPath(strNewName);
690 		if (newName.IsOk() && (newName != file->GetFileName())) {
691 			theApp->sharedfiles->RenameFile(file, newName);
692 		}
693 	}
694 }
695 
696 
OnKeyPressed(wxKeyEvent & event)697 void CSharedFilesCtrl::OnKeyPressed( wxKeyEvent& event )
698 {
699 	if (event.GetKeyCode() == WXK_F2) {
700 		wxCommandEvent evt;
701 		OnRename(evt);
702 
703 		return;
704 	}
705 	event.Skip();
706 }
707 
708 
OnAddCollection(wxCommandEvent & WXUNUSED (evt))709 void CSharedFilesCtrl::OnAddCollection( wxCommandEvent& WXUNUSED(evt) )
710 {
711 	int item = GetNextItem( -1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED );
712 	if (item != -1) {
713 		CKnownFile *file = reinterpret_cast<CKnownFile*>(GetItemData(item));
714 		wxString CollectionFile = file->GetFilePath().JoinPaths(file->GetFileName()).GetRaw();
715 		CMuleCollection my_collection;
716 		if (my_collection.Open( (std::string)CollectionFile.mb_str() )) {
717 //#warning This is probably not working on Unicode
718 			for (size_t e = 0; e < my_collection.size(); ++e) {
719 				theApp->downloadqueue->AddLink(wxString(my_collection[e].c_str(), wxConvUTF8));
720 			}
721 
722 		}
723 	}
724 }
725 
726 // File_checked_for_headers
727