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 "TransferWnd.h"	// Interface declarations
27 
28 #include <common/MenuIDs.h>
29 
30 #include <wx/config.h>
31 
32 
33 // This include must be before amuleDlg.h
34 #ifdef __WINDOWS__
35     #include <wx/msw/winundef.h>	// Needed for windows compilation
36 #endif
37 
38 
39 #include "amuleDlg.h"			// Needed for CamuleDlg
40 #include "PartFile.h"			// Needed for PR_LOW
41 #include "DownloadQueue.h"		// Needed for CDownloadQueue
42 #include "CatDialog.h"			// Needed for CCatDialog
43 #include "DownloadListCtrl.h"		// Needed for CDownloadListCtrl
44 #include "SourceListCtrl.h"		// Needed for CSourceListCtrl
45 #include "amule.h"			// Needed for theApp
46 #include "muuli_wdr.h"			// Needed for ID_CATEGORIES
47 #include "SearchDlg.h"			// Needed for CSearchDlg->UpdateCatChoice()
48 #include "MuleNotebook.h"
49 #include "Preferences.h"
50 #include "Statistics.h"			// Needed for theStats
51 #include "SharedFileList.h"		// Needed for CSharedFileList
52 #include "GuiEvents.h"			// Needed for CoreNotify_*
53 
54 
BEGIN_EVENT_TABLE(CTransferWnd,wxPanel)55 BEGIN_EVENT_TABLE(CTransferWnd, wxPanel)
56 	EVT_RIGHT_DOWN(CTransferWnd::OnNMRclickDLtab)
57 	EVT_NOTEBOOK_PAGE_CHANGED(ID_CATEGORIES,	CTransferWnd::OnCategoryChanged)
58 
59 	EVT_SPLITTER_SASH_POS_CHANGING(ID_DOWNLOADSSPLATTER, CTransferWnd::OnSashPositionChanging)
60 
61 	EVT_BUTTON(ID_BTNCLRCOMPL,		CTransferWnd::OnBtnClearDownloads)
62 	EVT_BUTTON(ID_CLIENTTOGGLE,		CTransferWnd::OnToggleClientList)
63 
64 	EVT_MENU_RANGE(MP_CAT_SET0, MP_CAT_SET0 + 15, CTransferWnd::OnSetDefaultCat)
65 	EVT_MENU(MP_CAT_ADD,			CTransferWnd::OnAddCategory)
66 	EVT_MENU(MP_CAT_EDIT,			CTransferWnd::OnEditCategory)
67 	EVT_MENU(MP_CAT_REMOVE,			CTransferWnd::OnDelCategory)
68 	EVT_MENU(MP_PRIOLOW,			CTransferWnd::OnSetCatPriority)
69 	EVT_MENU(MP_PRIONORMAL,			CTransferWnd::OnSetCatPriority)
70 	EVT_MENU(MP_PRIOHIGH,			CTransferWnd::OnSetCatPriority)
71 	EVT_MENU(MP_PRIOAUTO,			CTransferWnd::OnSetCatPriority)
72 	EVT_MENU(MP_PAUSE,			CTransferWnd::OnSetCatStatus)
73 	EVT_MENU(MP_STOP,			CTransferWnd::OnSetCatStatus)
74 	EVT_MENU(MP_CANCEL,			CTransferWnd::OnSetCatStatus)
75 	EVT_MENU(MP_RESUME,			CTransferWnd::OnSetCatStatus)
76 END_EVENT_TABLE()
77 
78 
79 
80 CTransferWnd::CTransferWnd( wxWindow* pParent )
81 	: wxPanel( pParent, -1 )
82 {
83 	wxSizer* content = transferDlg(this, true);
84 	content->Show(this, true);
85 
86 	downloadlistctrl = CastChild( wxT("downloadList"), CDownloadListCtrl );
87 	clientlistctrl   = CastChild( ID_CLIENTLIST, CSourceListCtrl );
88 	m_dlTab          = CastChild( ID_CATEGORIES, CMuleNotebook );
89 
90 	// Set disabled image for clear complete button
91 	CastChild(ID_BTNCLRCOMPL, wxBitmapButton)->SetBitmapDisabled(amuleDlgImages(34));
92 
93 	// We want to use our own popup
94 	m_dlTab->SetPopupHandler( this );
95 
96 	// Set default category
97 	theApp->glob_prefs->GetCategory(0)->title = GetCatTitle(thePrefs::GetAllcatFilter());
98 	theApp->glob_prefs->GetCategory(0)->path = thePrefs::GetIncomingDir();
99 
100 	// Show default + userdefined categories
101 	for ( uint32 i = 0; i < theApp->glob_prefs->GetCatCount(); i++ ) {
102 		m_dlTab->AddPage( new wxPanel(m_dlTab), theApp->glob_prefs->GetCategory(i)->title );
103 	}
104 
105 	m_menu = NULL;
106 	m_splitter = 0;
107 
108 	wxConfigBase *config = wxConfigBase::Get();
109 
110 	// Check if the clientlist is hidden
111 	bool show = true;
112 	config->Read( wxT("/GUI/TransferWnd/ShowClientList"), &show, true );
113 	clientlistctrl->SetShowing(show);
114 	// Load the last used splitter position
115 	m_splitter = config->Read( wxT("/GUI/TransferWnd/Splitter"), 463l );
116 }
117 
118 
~CTransferWnd()119 CTransferWnd::~CTransferWnd()
120 {
121 	wxConfigBase *config = wxConfigBase::Get();
122 
123 	if ( !clientlistctrl->GetShowing() ) {
124 		// Save the splitter position
125 		config->Write( wxT("/GUI/TransferWnd/Splitter"), m_splitter );
126 
127 		// Save the visible status of the list
128 		config->Write( wxT("/GUI/TransferWnd/ShowClientList"), false );
129 	} else {
130 		wxSplitterWindow* splitter = CastChild( wxT("splitterWnd"), wxSplitterWindow );
131 
132 		// Save the splitter position
133 		config->Write( wxT("/GUI/TransferWnd/Splitter"), splitter->GetSashPosition() );
134 
135 		// Save the visible status of the list
136 		config->Write( wxT("/GUI/TransferWnd/ShowClientList"), true );
137 	}
138 }
139 
140 
AddCategory(Category_Struct * category)141 void CTransferWnd::AddCategory( Category_Struct* category )
142 {
143 	// Add the initial page
144 	m_dlTab->AddPage( new wxPanel(m_dlTab), category->title );
145 
146 	// Update the title
147 	UpdateCategory( m_dlTab->GetPageCount() - 1 );
148 
149 	theApp->amuledlg->m_searchwnd->UpdateCatChoice();
150 }
151 
UpdateCategory(int index)152 void CTransferWnd::UpdateCategory(int index)
153 {
154 	uint32 nrCats = theApp->glob_prefs->GetCatCount();
155 	std::vector<uint16> files, downloads;
156 	bool showCatTabInfos = thePrefs::ShowCatTabInfos();
157 	if (showCatTabInfos) {
158 		files.insert(files.begin(), nrCats, 0);
159 		downloads.insert(downloads.begin(), nrCats, 0);
160 
161 #ifdef CLIENT_GUI
162 		for (CDownQueueRem::const_iterator it = theApp->downloadqueue->begin(); it != theApp->downloadqueue->end(); ++it) {
163 			CPartFile *cur_file = it->second;
164 #else
165 		std::vector<CPartFile*> fileList;
166 		theApp->downloadqueue->CopyFileList(fileList, true);
167 		int size = fileList.size();
168 		for (int i = 0; i < size; ++i ) {
169 			CPartFile *cur_file = fileList[i];
170 #endif
171 			bool downloading = cur_file->GetTransferingSrcCount() > 0;
172 			int fileCat = cur_file->GetCategory();
173 			if ((index == -1 || fileCat == index) && cur_file->CheckShowItemInGivenCat(fileCat)) {
174 				files[fileCat]++;
175 				if (downloading) {
176 					downloads[fileCat]++;
177 				}
178 			}
179 			if (index == -1 && fileCat > 0 && cur_file->CheckShowItemInGivenCat(0)) {
180 				files[0]++;
181 				if (downloading) {
182 					downloads[0]++;
183 				}
184 			}
185 		}
186 
187 	}
188 	int start, end;
189 	if (index == -1) {
190 		start = 0;
191 		end = nrCats - 1;
192 	} else {
193 		start = index;
194 		end = index;
195 	}
196 	for (int i = start; i <= end; i++) {
197 		wxString label = theApp->glob_prefs->GetCategory(i)->title;
198 		if (showCatTabInfos) {
199 			label += CFormat(wxT(" (%u/%u)")) % downloads[i] % files[i];
200 		}
201 		m_dlTab->SetPageText(i, label);
202 	}
203 }
204 
205 
206 void CTransferWnd::OnSetCatStatus( wxCommandEvent& event )
207 {
208 	if ( event.GetId() == MP_CANCEL ) {
209 		if ( wxMessageBox(_("Are you sure you wish to cancel and delete all files in this category?"),_("Confirmation Required"), wxYES_NO|wxCENTRE|wxICON_EXCLAMATION, this) == wxNO) {
210 			return;
211 		}
212 	}
213 
214 	CoreNotify_Download_Set_Cat_Status( m_dlTab->GetSelection(), event.GetId() );
215 }
216 
217 
218 void CTransferWnd::OnSetCatPriority( wxCommandEvent& event )
219 {
220 	int priority = 0;
221 
222 	switch ( event.GetId() ) {
223 		case MP_PRIOLOW:	priority = PR_LOW;	break;
224 		case MP_PRIONORMAL:	priority = PR_NORMAL;	break;
225 		case MP_PRIOHIGH:	priority = PR_HIGH;	break;
226 		case MP_PRIOAUTO:	priority = PR_AUTO;	break;
227 		default:
228 			return;
229 	}
230 
231 	CoreNotify_Download_Set_Cat_Prio( m_dlTab->GetSelection(), priority );
232 }
233 
234 
235 void CTransferWnd::OnAddCategory(wxCommandEvent& WXUNUSED(event))
236 {
237 	if (theApp->glob_prefs->GetCatCount() >= 99) {
238 		wxMessageBox(_("Only 99 categories are supported."), _("Too many categories!"), wxOK | wxICON_EXCLAMATION);
239 		return;
240 	}
241 	CCatDialog dialog( this,
242 	// Allow browse?
243 #ifdef CLIENT_GUI
244 	false
245 #else
246 	true
247 #endif
248 	);
249 	dialog.ShowModal();
250 }
251 
252 
253 void CTransferWnd::OnDelCategory(wxCommandEvent& WXUNUSED(event))
254 {
255 	RemoveCategory(m_dlTab->GetSelection());
256 }
257 
258 
259 void CTransferWnd::RemoveCategory(int index)
260 {
261 	if ( index > 0 ) {
262 		theApp->downloadqueue->ResetCatParts(index);
263 		theApp->glob_prefs->RemoveCat(index);
264 		RemoveCategoryPage(index);
265 		if ( theApp->glob_prefs->GetCatCount() == 1 ) {
266 			thePrefs::SetAllcatFilter( acfAll );
267 		}
268 		theApp->glob_prefs->SaveCats();
269 		theApp->amuledlg->m_searchwnd->UpdateCatChoice();
270 	}
271 }
272 
273 
274 void CTransferWnd::RemoveCategoryPage(int index)
275 {
276 	m_dlTab->RemovePage(index);
277 	m_dlTab->SetSelection(0);
278 	downloadlistctrl->ChangeCategory(0);
279 }
280 
281 
282 void CTransferWnd::OnEditCategory( wxCommandEvent& WXUNUSED(event) )
283 {
284 	CCatDialog dialog( this,
285 	// Allow browse?
286 #ifdef CLIENT_GUI
287 	false
288 #else
289 	true
290 #endif
291 		, m_dlTab->GetSelection());
292 
293 	dialog.ShowModal();
294 }
295 
296 
297 void CTransferWnd::OnSetDefaultCat( wxCommandEvent& event )
298 {
299 	thePrefs::SetAllcatFilter( static_cast<AllCategoryFilter>(event.GetId() - MP_CAT_SET0) );
300 	theApp->glob_prefs->GetCategory(0)->title = GetCatTitle( thePrefs::GetAllcatFilter() );
301 
302 	UpdateCategory( 0 );
303 
304 	downloadlistctrl->ChangeCategory( 0 );
305 
306 	theApp->glob_prefs->SaveCats();
307 
308 	downloadlistctrl->SortList();
309 }
310 
311 
312 void CTransferWnd::OnCategoryChanged(wxNotebookEvent& evt)
313 {
314 	// First remove currently showing sources (switching cat will deselect all)
315 	CKnownFileVector filesVector;
316 	clientlistctrl->ShowSources(filesVector);
317 	// Then change cat
318 	downloadlistctrl->ChangeCategory(evt.GetSelection());
319 	downloadlistctrl->SortList();
320 }
321 
322 
323 void CTransferWnd::OnNMRclickDLtab(wxMouseEvent& evt)
324 {
325 	// Only handle events from the category-notebook
326 	if ( evt.GetEventObject() != (wxObject*)m_dlTab )
327 		return;
328 
329 	if ( m_dlTab->GetSelection() == -1 ) {
330 		return;
331 	}
332 
333 	// Avoid opening another menu when it's already open
334 	if ( m_menu == NULL ) {
335 		m_menu = new wxMenu( _("Category") );
336 
337 		if ( m_dlTab->GetSelection() == 0 ) {
338 			wxMenu* catmenu = new wxMenu();
339 
340 			catmenu->Append( MP_CAT_SET0,      _("All") );
341 			catmenu->Append( MP_CAT_SET0 + 1,  _("All others") );
342 
343 			catmenu->AppendSeparator();
344 
345 			catmenu->Append( MP_CAT_SET0 + 2,  _("Incomplete") );
346 			catmenu->Append( MP_CAT_SET0 + 3,  _("Completed") );
347 			catmenu->Append( MP_CAT_SET0 + 4,  _("Waiting") );
348 			catmenu->Append( MP_CAT_SET0 + 5,  _("Downloading") );
349 			catmenu->Append( MP_CAT_SET0 + 6,  _("Erroneous") );
350 			catmenu->Append( MP_CAT_SET0 + 7,  _("Paused") );
351 			catmenu->Append( MP_CAT_SET0 + 8,  _("Stopped") );
352 			catmenu->Append( MP_CAT_SET0 + 15, _("Active") );
353 
354 			catmenu->AppendSeparator();
355 
356 			catmenu->Append( MP_CAT_SET0 + 9,  _("Video") );
357 			catmenu->Append( MP_CAT_SET0 + 10, _("Audio") );
358 			catmenu->Append( MP_CAT_SET0 + 11, _("Archive") );
359 			catmenu->Append( MP_CAT_SET0 + 12, _("CD-Images") );
360 			catmenu->Append( MP_CAT_SET0 + 13, _("Pictures") );
361 			catmenu->Append( MP_CAT_SET0 + 14, _("Text") );
362 
363 			m_menu->Append(0, _("Select view filter"), catmenu);
364 		}
365 
366 		m_menu->Append( MP_CAT_ADD, _("Add category") );
367 
368 		if ( m_dlTab->GetSelection() ) {
369 			m_menu->Append(MP_CAT_EDIT,_("Edit category"));
370 			m_menu->Append(MP_CAT_REMOVE, _("Remove category"));
371 		}
372 
373 		m_menu->AppendSeparator();
374 
375 		m_menu->Append( MP_CANCEL, _("Cancel"));
376 		m_menu->Append( MP_STOP,   _("&Stop"));
377 		m_menu->Append( MP_PAUSE,  _("&Pause"));
378 		m_menu->Append( MP_RESUME, _("&Resume"));
379 
380 		PopupMenu(m_menu, evt.GetPosition());
381 
382 		delete m_menu;
383 		m_menu = NULL;
384 	}
385 }
386 
387 
388 void CTransferWnd::OnBtnClearDownloads( wxCommandEvent& WXUNUSED(evt) )
389 {
390     downloadlistctrl->Freeze();
391     downloadlistctrl->ClearCompleted();
392     downloadlistctrl->Thaw();
393 }
394 
395 
396 void CTransferWnd::Prepare()
397 {
398 	wxSplitterWindow* splitter = CastChild( wxT("splitterWnd"), wxSplitterWindow );
399 	int height = splitter->GetSize().GetHeight();
400 	int header_height = s_clientlistHeader->GetSize().GetHeight();
401 
402 	if ( m_splitter ) {
403 		// Some sanity checking
404 		if ( m_splitter < s_splitterMin ) {
405 			m_splitter = s_splitterMin;
406 		} else if ( m_splitter > height - header_height * 2 ) {
407 			m_splitter = height - header_height * 2;
408 		}
409 		splitter->SetSashPosition( m_splitter );
410 		m_splitter = 0;
411 	}
412 
413 	if ( !clientlistctrl->GetShowing() ) {
414 		// use a toggle event to close it (calculate size, change button)
415 		clientlistctrl->SetShowing( true );	// so it will be toggled to false
416 		wxCommandEvent evt1;
417 		OnToggleClientList( evt1 );
418 	}
419 }
420 
421 void CTransferWnd::OnToggleClientList(wxCommandEvent& WXUNUSED(evt))
422 {
423 	wxSplitterWindow* splitter = CastChild( wxT("splitterWnd"), wxSplitterWindow );
424 	wxBitmapButton*   button = CastChild( ID_CLIENTTOGGLE, wxBitmapButton );
425 
426 	if ( !clientlistctrl->GetShowing() ) {
427 		splitter->SetSashPosition( m_splitter );
428 		m_splitter = 0;
429 
430 		clientlistctrl->SetShowing( true );
431 
432 		button->SetBitmapLabel( amuleDlgImages( 10 ) );
433 		button->SetBitmapFocus( amuleDlgImages( 10 ) );
434 		button->SetBitmapSelected( amuleDlgImages( 10 ) );
435 		button->SetBitmapHover( amuleDlgImages( 10 ) );
436 	} else {
437 		clientlistctrl->SetShowing( false );
438 
439 		m_splitter = splitter->GetSashPosition();
440 
441 		// Add the height of the listctrl to the top-window
442 		int height = clientlistctrl->GetSize().GetHeight()
443 					 + splitter->GetWindow1()->GetSize().GetHeight();
444 
445 		splitter->SetSashPosition( height );
446 
447 		button->SetBitmapLabel( amuleDlgImages( 11 ) );
448 		button->SetBitmapFocus( amuleDlgImages( 11 ) );
449 		button->SetBitmapSelected( amuleDlgImages( 11 ) );
450 		button->SetBitmapHover( amuleDlgImages( 11 ) );
451 	}
452 }
453 
454 
455 void CTransferWnd::OnSashPositionChanging(wxSplitterEvent& evt)
456 {
457 	if ( evt.GetSashPosition() < s_splitterMin ) {
458 		evt.SetSashPosition( s_splitterMin );
459 	} else {
460 		wxSplitterWindow* splitter = wxStaticCast( evt.GetEventObject(), wxSplitterWindow);
461 		wxCHECK_RET(splitter, wxT("ERROR: NULL splitter in CTransferWnd::OnSashPositionChanging"));
462 
463 		int height = splitter->GetSize().GetHeight();
464 		int header_height = s_clientlistHeader->GetSize().GetHeight();
465 		int mousey = wxGetMousePosition().y - splitter->GetScreenRect().GetTop();
466 
467 		if ( !clientlistctrl->GetShowing() ) {
468 			// lower window hidden
469 			if ( height - mousey < header_height * 2 ) {
470 				// no moving down if already hidden
471 				evt.Veto();
472 			} else {
473 				// show it
474 				m_splitter = mousey;	// prevent jumping if it was minimized and is then shown by dragging the sash
475 				wxCommandEvent event;
476 				OnToggleClientList( event );
477 			}
478 		} else {
479 			// lower window showing
480 			if ( height - mousey < header_height * 2 ) {
481 				// hide it
482 				wxCommandEvent event;
483 				OnToggleClientList( event );
484 			} else {
485 				// normal resize
486 				// If several events queue up, setting the sash to the current mouse position
487 				// will speed up things and make sash moving more smoothly.
488 				evt.SetSashPosition( mousey );
489 			}
490 		}
491 	}
492 }
493 // File_checked_for_headers
494