2 // This file is part of the aMule Project.
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 )
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 "TransferWnd.h" // Interface declarations
28 #include <common/MenuIDs.h>
30 #include <wx/config.h>
33 // This include must be before amuleDlg.h
35 #include <wx/msw/winundef.h> // Needed for windows compilation
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_*
55 BEGIN_EVENT_TABLE(CTransferWnd
, wxPanel
)
56 EVT_RIGHT_DOWN(CTransferWnd::OnNMRclickDLtab
)
57 EVT_NOTEBOOK_PAGE_CHANGED(ID_CATEGORIES
, CTransferWnd::OnCategoryChanged
)
59 EVT_SPLITTER_SASH_POS_CHANGING(ID_DOWNLOADSSPLATTER
, CTransferWnd::OnSashPositionChanging
)
61 EVT_BUTTON(ID_BTNCLRCOMPL
, CTransferWnd::OnBtnClearDownloads
)
62 EVT_BUTTON(ID_CLIENTTOGGLE
, CTransferWnd::OnToggleClientList
)
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
)
80 CTransferWnd::CTransferWnd( wxWindow
* pParent
)
81 : wxPanel( pParent
, -1 )
83 wxSizer
* content
= transferDlg(this, true);
84 content
->Show(this, true);
86 downloadlistctrl
= CastChild( wxT("downloadList"), CDownloadListCtrl
);
87 clientlistctrl
= CastChild( ID_CLIENTLIST
, CSourceListCtrl
);
88 m_dlTab
= CastChild( ID_CATEGORIES
, CMuleNotebook
);
90 // Set disabled image for clear complete button
91 CastChild(ID_BTNCLRCOMPL
, wxBitmapButton
)->SetBitmapDisabled(amuleDlgImages(34));
93 // We want to use our own popup
94 m_dlTab
->SetPopupHandler( this );
96 // Set default category
97 theApp
->glob_prefs
->GetCategory(0)->title
= GetCatTitle(thePrefs::GetAllcatFilter());
98 theApp
->glob_prefs
->GetCategory(0)->path
= thePrefs::GetIncomingDir();
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
);
108 wxConfigBase
*config
= wxConfigBase::Get();
110 // Check if the clientlist is hidden
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 );
119 CTransferWnd::~CTransferWnd()
121 wxConfigBase
*config
= wxConfigBase::Get();
123 if ( !clientlistctrl
->GetShowing() ) {
124 // Save the splitter position
125 config
->Write( wxT("/GUI/TransferWnd/Splitter"), m_splitter
);
127 // Save the visible status of the list
128 config
->Write( wxT("/GUI/TransferWnd/ShowClientList"), false );
130 wxSplitterWindow
* splitter
= CastChild( wxT("splitterWnd"), wxSplitterWindow
);
132 // Save the splitter position
133 config
->Write( wxT("/GUI/TransferWnd/Splitter"), splitter
->GetSashPosition() );
135 // Save the visible status of the list
136 config
->Write( wxT("/GUI/TransferWnd/ShowClientList"), true );
141 void CTransferWnd::AddCategory( Category_Struct
* category
)
143 // Add the initial page
144 m_dlTab
->AddPage( new wxPanel(m_dlTab
), category
->title
);
147 UpdateCategory( m_dlTab
->GetPageCount() - 1 );
149 theApp
->amuledlg
->m_searchwnd
->UpdateCatChoice();
152 void CTransferWnd::UpdateCategory(int index
)
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);
162 for (CDownQueueRem::const_iterator it
= theApp
->downloadqueue
->begin(); it
!= theApp
->downloadqueue
->end(); ++it
) {
163 CPartFile
*cur_file
= it
->second
;
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
];
171 bool downloading
= cur_file
->GetTransferingSrcCount() > 0;
172 int fileCat
= cur_file
->GetCategory();
173 if ((index
== -1 || fileCat
== index
) && cur_file
->CheckShowItemInGivenCat(fileCat
)) {
176 downloads
[fileCat
]++;
179 if (index
== -1 && fileCat
> 0 && cur_file
->CheckShowItemInGivenCat(0)) {
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
];
201 m_dlTab
->SetPageText(i
, label
);
206 void CTransferWnd::OnSetCatStatus( wxCommandEvent
& event
)
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
) {
214 CoreNotify_Download_Set_Cat_Status( m_dlTab
->GetSelection(), event
.GetId() );
218 void CTransferWnd::OnSetCatPriority( wxCommandEvent
& event
)
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;
231 CoreNotify_Download_Set_Cat_Prio( m_dlTab
->GetSelection(), priority
);
235 void CTransferWnd::OnAddCategory(wxCommandEvent
& WXUNUSED(event
))
237 if (theApp
->glob_prefs
->GetCatCount() >= 99) {
238 wxMessageBox(_("Only 99 categories are supported."), _("Too many categories!"), wxOK
| wxICON_EXCLAMATION
);
241 CCatDialog
dialog( this,
249 if (dialog
.ShowModal() == wxOK
) {
250 // Add the files on this folder.
251 Category_Struct
* newcat
=
252 theApp
->glob_prefs
->GetCategory(
253 theApp
->glob_prefs
->GetCatCount()-1);
254 theApp
->sharedfiles
->AddFilesFromDirectory(newcat
->path
);
255 theApp
->sharedfiles
->Reload();
260 void CTransferWnd::OnDelCategory(wxCommandEvent
& WXUNUSED(event
))
262 RemoveCategory(m_dlTab
->GetSelection());
266 void CTransferWnd::RemoveCategory(int index
)
269 theApp
->downloadqueue
->ResetCatParts(index
);
270 theApp
->glob_prefs
->RemoveCat(index
);
271 RemoveCategoryPage(index
);
272 if ( theApp
->glob_prefs
->GetCatCount() == 1 ) {
273 thePrefs::SetAllcatFilter( acfAll
);
275 theApp
->glob_prefs
->SaveCats();
276 theApp
->amuledlg
->m_searchwnd
->UpdateCatChoice();
281 void CTransferWnd::RemoveCategoryPage(int index
)
283 m_dlTab
->RemovePage(index
);
284 m_dlTab
->SetSelection(0);
285 downloadlistctrl
->ChangeCategory(0);
289 void CTransferWnd::OnEditCategory( wxCommandEvent
& WXUNUSED(event
) )
291 Category_Struct
* cat
= theApp
->glob_prefs
->GetCategory(m_dlTab
->GetSelection());
292 CPath oldpath
= cat
->path
;
293 CCatDialog
dialog( this,
300 , m_dlTab
->GetSelection());
302 if (dialog
.ShowModal() == wxOK
) {
303 if (!oldpath
.IsSameDir(cat
->path
)) {
304 theApp
->sharedfiles
->AddFilesFromDirectory(cat
->path
);
305 theApp
->sharedfiles
->Reload();
311 void CTransferWnd::OnSetDefaultCat( wxCommandEvent
& event
)
313 thePrefs::SetAllcatFilter( static_cast<AllCategoryFilter
>(event
.GetId() - MP_CAT_SET0
) );
314 theApp
->glob_prefs
->GetCategory(0)->title
= GetCatTitle( thePrefs::GetAllcatFilter() );
318 downloadlistctrl
->ChangeCategory( 0 );
320 theApp
->glob_prefs
->SaveCats();
322 downloadlistctrl
->SortList();
326 void CTransferWnd::OnCategoryChanged(wxNotebookEvent
& evt
)
328 // First remove currently showing sources (switching cat will deselect all)
329 CKnownFileVector filesVector
;
330 clientlistctrl
->ShowSources(filesVector
);
332 downloadlistctrl
->ChangeCategory(evt
.GetSelection());
333 downloadlistctrl
->SortList();
337 void CTransferWnd::OnNMRclickDLtab(wxMouseEvent
& evt
)
339 // Only handle events from the category-notebook
340 if ( evt
.GetEventObject() != (wxObject
*)m_dlTab
)
343 if ( m_dlTab
->GetSelection() == -1 ) {
347 // Avoid opening another menu when it's already open
348 if ( m_menu
== NULL
) {
349 m_menu
= new wxMenu( _("Category") );
351 if ( m_dlTab
->GetSelection() == 0 ) {
352 wxMenu
* catmenu
= new wxMenu();
354 catmenu
->Append( MP_CAT_SET0
, _("All") );
355 catmenu
->Append( MP_CAT_SET0
+ 1, _("All others") );
357 catmenu
->AppendSeparator();
359 catmenu
->Append( MP_CAT_SET0
+ 2, _("Incomplete") );
360 catmenu
->Append( MP_CAT_SET0
+ 3, _("Completed") );
361 catmenu
->Append( MP_CAT_SET0
+ 4, _("Waiting") );
362 catmenu
->Append( MP_CAT_SET0
+ 5, _("Downloading") );
363 catmenu
->Append( MP_CAT_SET0
+ 6, _("Erroneous") );
364 catmenu
->Append( MP_CAT_SET0
+ 7, _("Paused") );
365 catmenu
->Append( MP_CAT_SET0
+ 8, _("Stopped") );
366 catmenu
->Append( MP_CAT_SET0
+ 15, _("Active") );
368 catmenu
->AppendSeparator();
370 catmenu
->Append( MP_CAT_SET0
+ 9, _("Video") );
371 catmenu
->Append( MP_CAT_SET0
+ 10, _("Audio") );
372 catmenu
->Append( MP_CAT_SET0
+ 11, _("Archive") );
373 catmenu
->Append( MP_CAT_SET0
+ 12, _("CD-Images") );
374 catmenu
->Append( MP_CAT_SET0
+ 13, _("Pictures") );
375 catmenu
->Append( MP_CAT_SET0
+ 14, _("Text") );
377 m_menu
->Append(0, _("Select view filter"), catmenu
);
380 m_menu
->Append( MP_CAT_ADD
, _("Add category") );
382 if ( m_dlTab
->GetSelection() ) {
383 m_menu
->Append(MP_CAT_EDIT
,_("Edit category"));
384 m_menu
->Append(MP_CAT_REMOVE
, _("Remove category"));
387 m_menu
->AppendSeparator();
389 m_menu
->Append( MP_CANCEL
, _("Cancel"));
390 m_menu
->Append( MP_STOP
, _("&Stop"));
391 m_menu
->Append( MP_PAUSE
, _("&Pause"));
392 m_menu
->Append( MP_RESUME
, _("&Resume"));
394 PopupMenu(m_menu
, evt
.GetPosition());
402 void CTransferWnd::OnBtnClearDownloads( wxCommandEvent
& WXUNUSED(evt
) )
404 downloadlistctrl
->Freeze();
405 downloadlistctrl
->ClearCompleted();
406 downloadlistctrl
->Thaw();
410 void CTransferWnd::Prepare()
412 wxSplitterWindow
* splitter
= CastChild( wxT("splitterWnd"), wxSplitterWindow
);
413 int height
= splitter
->GetSize().GetHeight();
414 int header_height
= s_clientlistHeader
->GetSize().GetHeight();
417 // Some sanity checking
418 if ( m_splitter
< s_splitterMin
) {
419 m_splitter
= s_splitterMin
;
420 } else if ( m_splitter
> height
- header_height
* 2 ) {
421 m_splitter
= height
- header_height
* 2;
423 splitter
->SetSashPosition( m_splitter
);
427 if ( !clientlistctrl
->GetShowing() ) {
428 // use a toggle event to close it (calculate size, change button)
429 clientlistctrl
->SetShowing( true ); // so it will be toggled to false
431 OnToggleClientList( evt1
);
435 void CTransferWnd::OnToggleClientList(wxCommandEvent
& WXUNUSED(evt
))
437 wxSplitterWindow
* splitter
= CastChild( wxT("splitterWnd"), wxSplitterWindow
);
438 wxBitmapButton
* button
= CastChild( ID_CLIENTTOGGLE
, wxBitmapButton
);
440 if ( !clientlistctrl
->GetShowing() ) {
441 splitter
->SetSashPosition( m_splitter
);
444 clientlistctrl
->SetShowing( true );
446 button
->SetBitmapLabel( amuleDlgImages( 10 ) );
447 button
->SetBitmapFocus( amuleDlgImages( 10 ) );
448 button
->SetBitmapSelected( amuleDlgImages( 10 ) );
449 button
->SetBitmapHover( amuleDlgImages( 10 ) );
451 clientlistctrl
->SetShowing( false );
453 m_splitter
= splitter
->GetSashPosition();
455 // Add the height of the listctrl to the top-window
456 int height
= clientlistctrl
->GetSize().GetHeight()
457 + splitter
->GetWindow1()->GetSize().GetHeight();
459 splitter
->SetSashPosition( height
);
461 button
->SetBitmapLabel( amuleDlgImages( 11 ) );
462 button
->SetBitmapFocus( amuleDlgImages( 11 ) );
463 button
->SetBitmapSelected( amuleDlgImages( 11 ) );
464 button
->SetBitmapHover( amuleDlgImages( 11 ) );
469 void CTransferWnd::OnSashPositionChanging(wxSplitterEvent
& evt
)
471 if ( evt
.GetSashPosition() < s_splitterMin
) {
472 evt
.SetSashPosition( s_splitterMin
);
474 wxSplitterWindow
* splitter
= wxStaticCast( evt
.GetEventObject(), wxSplitterWindow
);
475 wxCHECK_RET(splitter
, wxT("ERROR: NULL splitter in CTransferWnd::OnSashPositionChanging"));
477 int height
= splitter
->GetSize().GetHeight();
478 int header_height
= s_clientlistHeader
->GetSize().GetHeight();
479 int mousey
= wxGetMousePosition().y
- splitter
->GetScreenRect().GetTop();
481 if ( !clientlistctrl
->GetShowing() ) {
482 // lower window hidden
483 if ( height
- mousey
< header_height
* 2 ) {
484 // no moving down if already hidden
488 m_splitter
= mousey
; // prevent jumping if it was minimized and is then shown by dragging the sash
489 wxCommandEvent event
;
490 OnToggleClientList( event
);
493 // lower window showing
494 if ( height
- mousey
< header_height
* 2 ) {
496 wxCommandEvent event
;
497 OnToggleClientList( event
);
500 // If several events queue up, setting the sash to the current mouse position
501 // will speed up things and make sash moving more smoothly.
502 evt
.SetSashPosition( mousey
);
507 // File_checked_for_headers