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-2011 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 <wx/config.h>
27 #include <wx/gauge.h>		// Do_not_auto_remove (win32)
28 #include <wx/radiobox.h>
29 
30 #include "SharedFilesWnd.h"	// Interface declarations
31 #include "SharedFilesCtrl.h"
32 #include "SharedFilePeersListCtrl.h"
33 #include "muuli_wdr.h"		// Needed for ID_SHFILELIST
34 #include "KnownFileList.h"	// Needed for CKnownFileList
35 #include "KnownFile.h"		// Needed for CKnownFile
36 #include "amule.h"			// Needed for theApp
37 #include "UploadQueue.h"	// Needed for theApp->uploadqueue
38 
39 
BEGIN_EVENT_TABLE(CSharedFilesWnd,wxPanel)40 BEGIN_EVENT_TABLE(CSharedFilesWnd, wxPanel)
41 	EVT_LIST_ITEM_SELECTED( ID_SHFILELIST,	CSharedFilesWnd::OnItemSelectionChanged )
42 	EVT_LIST_ITEM_DESELECTED( ID_SHFILELIST,	CSharedFilesWnd::OnItemSelectionChanged )
43 	EVT_BUTTON( ID_BTNRELSHARED,			CSharedFilesWnd::OnBtnReloadShared )
44 	EVT_BUTTON(ID_SHAREDCLIENTTOGGLE,		CSharedFilesWnd::OnToggleClientList)
45 	EVT_RADIOBOX(ID_SHOW_CLIENTS_MODE,		CSharedFilesWnd::OnSelectClientsMode)
46 
47 	EVT_SPLITTER_SASH_POS_CHANGING(ID_SHARESSPLATTER, CSharedFilesWnd::OnSashPositionChanging)
48 END_EVENT_TABLE()
49 
50 CSharedFilesWnd::CSharedFilesWnd( wxWindow* pParent )
51 	: wxPanel(pParent, -1)
52 {
53 	wxSizer* content = sharedfilesDlg(this, true);
54 	content->Show(this, true);
55 
56 	m_bar_requests	= CastChild( wxT("popbar"), wxGauge );
57 	m_bar_accepted	= CastChild( wxT("popbarAccept"), wxGauge );
58 	m_bar_transfer	= CastChild( wxT("popbarTrans"), wxGauge );
59 	m_radioClientMode = CastChild( ID_SHOW_CLIENTS_MODE, wxRadioBox );
60 	sharedfilesctrl = CastChild( wxT("sharedFilesCt"), CSharedFilesCtrl );
61 	peerslistctrl   = CastChild( ID_SHAREDCLIENTLIST, CSharedFilePeersListCtrl );
62 	wxASSERT(sharedfilesctrl);
63 	wxASSERT(peerslistctrl);
64 	m_prepared		= false;
65 
66 	m_splitter = 0;
67 
68 	wxConfigBase *config = wxConfigBase::Get();
69 
70 	// Check if the clientlist is hidden
71 	bool show = true;
72 	config->Read( wxT("/GUI/SharedWnd/ShowClientList"), &show, true );
73 	peerslistctrl->SetShowing(show);
74 	// Load the last used splitter position
75 	m_splitter = config->Read( wxT("/GUI/SharedWnd/Splitter"), 463l );
76 	m_clientShow = (EClientShow) config->Read(wxT("/GUI/SharedWnd/ClientShowMode"), ClientShowSelected);
77 	m_radioClientMode->SetSelection(m_clientShow);
78 }
79 
80 
~CSharedFilesWnd()81 CSharedFilesWnd::~CSharedFilesWnd()
82 {
83 	if (m_prepared) {
84 		wxConfigBase *config = wxConfigBase::Get();
85 
86 		if ( !peerslistctrl->GetShowing() ) {
87 			// Save the splitter position
88 			config->Write( wxT("/GUI/SharedWnd/Splitter"), m_splitter );
89 
90 			// Save the visible status of the list
91 			config->Write( wxT("/GUI/SharedWnd/ShowClientList"), false );
92 		} else {
93 			wxSplitterWindow* splitter = CastChild( wxT("sharedsplitterWnd"), wxSplitterWindow );
94 
95 			// Save the splitter position
96 			config->Write(wxT("/GUI/SharedWnd/Splitter"), splitter->GetSashPosition());
97 
98 			// Save the visible status of the list
99 			config->Write( wxT("/GUI/SharedWnd/ShowClientList"), true );
100 		}
101 		config->Write(wxT("/GUI/SharedWnd/ClientShowMode"), (int)m_clientShow);
102 	}
103 }
104 
105 
SelectionUpdated()106 void CSharedFilesWnd::SelectionUpdated()
107 {
108 	if (!sharedfilesctrl->IsSorting()) {
109 		uint64 lTransferred = theApp->knownfiles->transferred;
110 		uint32 lAccepted = theApp->knownfiles->accepted;
111 		uint32 lRequested = theApp->knownfiles->requested;
112 		m_bar_requests->SetRange( lRequested );
113 		m_bar_accepted->SetRange( lAccepted );
114 		m_bar_transfer->SetRange( lTransferred / 1024 );
115 
116 		CKnownFileVector fileVector;
117 
118 		// Create a total statistic for the selected item(s)
119 		uint32 session_requests = 0;
120 		uint32 session_accepted = 0;
121 		uint64 session_transferred = 0;
122 		uint32 all_requests = 0;
123 		uint32 all_accepted = 0;
124 		uint64 all_transferred = 0;
125 
126 		long index = -1;
127 		int filter = (m_clientShow == ClientShowSelected) ? wxLIST_STATE_SELECTED : wxLIST_STATE_DONTCARE;
128 		while ( (index = sharedfilesctrl->GetNextItem( index, wxLIST_NEXT_ALL, filter)) != -1) {
129 			CKnownFile* file = reinterpret_cast<CKnownFile*>(sharedfilesctrl->GetItemData(index));
130 			wxASSERT(file);
131 
132 			// Bars are always for selected files
133 			if (sharedfilesctrl->GetItemState(index, wxLIST_STATE_SELECTED)) {
134 				session_requests   += file->statistic.GetRequests();
135 				session_accepted   += file->statistic.GetAccepts();
136 				session_transferred += file->statistic.GetTransferred();
137 
138 				all_requests   += file->statistic.GetAllTimeRequests();
139 				all_accepted   += file->statistic.GetAllTimeAccepts();
140 				all_transferred += file->statistic.GetAllTimeTransferred();
141 			}
142 
143 			if (m_clientShow != ClientShowUploading) {
144 				fileVector.push_back(file);
145 			}
146 		}
147 
148 		if (fileVector.empty()) {
149 			// Requests
150 			m_bar_requests->SetValue( 0 );
151 			CastChild(IDC_SREQUESTED, wxStaticText)->SetLabel( wxT("- / -") );
152 
153 			// Accepted requets
154 			m_bar_accepted->SetValue( 0 );
155 			CastChild(IDC_SACCEPTED, wxStaticText)->SetLabel( wxT("- / -") );
156 
157 			// Transferred
158 			m_bar_transfer->SetValue( 0 );
159 			CastChild(IDC_STRANSFERRED, wxStaticText)->SetLabel( wxT("- / -") );
160 
161 		} else {
162 			std::sort(fileVector.begin(), fileVector.end());
163 
164 			// Store text lengths, and layout() when the texts have grown
165 			static uint32 lReq = 0, lAcc = 0, lTrans = 0;
166 			// Requests
167 			session_requests = session_requests > lRequested ? lRequested : session_requests;
168 			m_bar_requests->SetValue( session_requests );
169 			wxString labelReq = CFormat(wxT("%d / %d")) % session_requests % all_requests;
170 			CastChild(IDC_SREQUESTED, wxStaticText)->SetLabel(labelReq);
171 
172 			// Accepted requets
173 			session_accepted = session_accepted > lAccepted ? lAccepted : session_accepted;
174 			m_bar_accepted->SetValue( session_accepted );
175 			wxString labelAcc = CFormat(wxT("%d / %d")) % session_accepted % all_accepted;
176 			CastChild(IDC_SACCEPTED, wxStaticText)->SetLabel(labelAcc);
177 
178 			// Transferred
179 			session_transferred = session_transferred > lTransferred ? lTransferred : session_transferred;
180 			m_bar_transfer->SetValue( session_transferred / 1024 );
181 			wxString labelTrans = CastItoXBytes( session_transferred ) + wxT(" / ") + CastItoXBytes( all_transferred );
182 			CastChild(IDC_STRANSFERRED, wxStaticText)->SetLabel(labelTrans);
183 
184 			if (labelReq.Len() > lReq || labelAcc.Len() > lAcc || labelTrans.Len() > lTrans) {
185 				lReq = labelReq.Len();
186 				lAcc = labelAcc.Len();
187 				lTrans = labelTrans.Len();
188 				s_sharedfilespeerHeader->Layout();
189 			}
190 		}
191 
192 		if (m_clientShow == ClientShowUploading) {
193 			// The GenericClientListCtrl is designed to show clients associated with a KnownFile.
194 			// So the uploadqueue carries a special known file with all ongoing uploads in its upload list.
195 			// This is a hack, but easier than trying to bend the class into a shape it was not intended for
196 			// to show all clients currently uploading.
197 #ifdef CLIENT_GUI
198 			fileVector.push_back(theApp->m_allUploadingKnownFile);
199 #else
200 			fileVector.push_back(theApp->uploadqueue->GetAllUploadingKnownFile());
201 #endif
202 		}
203 		peerslistctrl->ShowSources(fileVector);
204 
205 		Refresh();
206 		Layout();
207 	}
208 }
209 
210 
OnBtnReloadShared(wxCommandEvent & WXUNUSED (evt))211 void CSharedFilesWnd::OnBtnReloadShared( wxCommandEvent& WXUNUSED(evt) )
212 {
213 	theApp->sharedfiles->Reload();
214 #ifndef CLIENT_GUI
215 	// remote gui will update display when data is back
216 	SelectionUpdated();
217 #endif
218 }
219 
220 
OnItemSelectionChanged(wxListEvent & evt)221 void CSharedFilesWnd::OnItemSelectionChanged(wxListEvent& evt)
222 {
223 	EClientShow clientShowMode = (EClientShow) m_radioClientMode->GetSelection();
224 
225 	// Only update the list of clients if that list shows clients related to the selected shared files
226 	if ( clientShowMode == ClientShowSelected ) {
227 		SelectionUpdated();
228 	}
229 
230 	evt.Skip();
231 }
232 
233 
RemoveAllSharedFiles()234 void CSharedFilesWnd::RemoveAllSharedFiles() {
235 	sharedfilesctrl->DeleteAllItems();
236 	sharedfilesctrl->ShowFilesCount();
237 	SelectionUpdated();
238 }
239 
Prepare()240 void CSharedFilesWnd::Prepare()
241 {
242 	if (m_prepared) {
243 		return;
244 	}
245 	m_prepared = true;
246 	wxSplitterWindow* splitter = CastChild( wxT("sharedsplitterWnd"), wxSplitterWindow );
247 	int height = splitter->GetSize().GetHeight();
248 	int header_height = s_sharedfilespeerHeader->GetSize().GetHeight();
249 
250 	if ( m_splitter ) {
251 		// Some sanity checking
252 		if ( m_splitter < s_splitterMin ) {
253 			m_splitter = s_splitterMin;
254 		} else if ( m_splitter > height - header_height * 2 ) {
255 			m_splitter = height - header_height * 2;
256 		}
257 		splitter->SetSashPosition( m_splitter );
258 		m_splitter = 0;
259 	}
260 
261 	if ( !peerslistctrl->GetShowing() ) {
262 		// use a toggle event to close it (calculate size, change button)
263 		peerslistctrl->SetShowing( true );	// so it will be toggled to false
264 		wxCommandEvent evt1;
265 		OnToggleClientList( evt1 );
266 	}
267 }
268 
OnToggleClientList(wxCommandEvent & WXUNUSED (evt))269 void CSharedFilesWnd::OnToggleClientList(wxCommandEvent& WXUNUSED(evt))
270 {
271 	wxSplitterWindow* splitter = CastChild( wxT("sharedsplitterWnd"), wxSplitterWindow );
272 	wxBitmapButton*   button = CastChild( ID_SHAREDCLIENTTOGGLE, wxBitmapButton );
273 
274 	if ( !peerslistctrl->GetShowing() ) {
275 		splitter->SetSashPosition( m_splitter );
276 		m_splitter = 0;
277 
278 		peerslistctrl->SetShowing( true );
279 
280 		button->SetBitmapLabel( amuleDlgImages( 10 ) );
281 		button->SetBitmapFocus( amuleDlgImages( 10 ) );
282 		button->SetBitmapSelected( amuleDlgImages( 10 ) );
283 		button->SetBitmapHover( amuleDlgImages( 10 ) );
284 	} else {
285 		peerslistctrl->SetShowing( false );
286 
287 		m_splitter = splitter->GetSashPosition();
288 
289 		// Add the height of the listctrl to the top-window
290 		int height = peerslistctrl->GetSize().GetHeight()
291 					 + splitter->GetWindow1()->GetSize().GetHeight();
292 
293 		splitter->SetSashPosition( height );
294 
295 		button->SetBitmapLabel( amuleDlgImages( 11 ) );
296 		button->SetBitmapFocus( amuleDlgImages( 11 ) );
297 		button->SetBitmapSelected( amuleDlgImages( 11 ) );
298 		button->SetBitmapHover( amuleDlgImages( 11 ) );
299 	}
300 }
301 
OnSashPositionChanging(wxSplitterEvent & evt)302 void CSharedFilesWnd::OnSashPositionChanging(wxSplitterEvent& evt)
303 {
304 	if ( evt.GetSashPosition() < s_splitterMin ) {
305 		evt.SetSashPosition( s_splitterMin );
306 	} else {
307 		wxSplitterWindow* splitter = wxStaticCast( evt.GetEventObject(), wxSplitterWindow);
308 		wxCHECK_RET(splitter, wxT("ERROR: NULL splitter in CSharedFilesWnd::OnSashPositionChanging"));
309 
310 		int height = splitter->GetSize().GetHeight();
311 		int header_height = s_sharedfilespeerHeader->GetSize().GetHeight();
312 		int mousey = wxGetMousePosition().y - splitter->GetScreenRect().GetTop();
313 
314 		if ( !peerslistctrl->GetShowing() ) {
315 			// lower window hidden
316 			if ( height - mousey < header_height * 2 ) {
317 				// no moving down if already hidden
318 				evt.Veto();
319 			} else {
320 				// show it
321 				m_splitter = mousey;	// prevent jumping if it was minimized and is then shown by dragging the sash
322 				wxCommandEvent evt1;
323 				OnToggleClientList( evt1 );
324 			}
325 		} else {
326 			// lower window showing
327 			if ( height - mousey < header_height * 2 ) {
328 				// hide it
329 				wxCommandEvent evt1;
330 				OnToggleClientList( evt1 );
331 			} else {
332 				// normal resize
333 				// If several events queue up, setting the sash to the current mouse position
334 				// will speed up things and make sash moving more smoothly.
335 				evt.SetSashPosition( mousey );
336 			}
337 		}
338 	}
339 }
340 
341 
OnSelectClientsMode(wxCommandEvent & WXUNUSED (evt))342 void CSharedFilesWnd::OnSelectClientsMode(wxCommandEvent& WXUNUSED(evt))
343 {
344 	EClientShow clientShowLast = m_clientShow;
345 	m_clientShow = (EClientShow) m_radioClientMode->GetSelection();
346 
347 	if (m_clientShow != clientShowLast) {
348 		SelectionUpdated();
349 	}
350 }
351 
352 // File_checked_for_headers
353