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/app.h>
27 
28 #include <wx/archive.h>
29 #include <wx/config.h>		// Do_not_auto_remove (MacOS 10.3, wx 2.7)
30 #include <wx/confbase.h>	// Do_not_auto_remove (MacOS 10.3, wx 2.7)
31 #include <wx/html/htmlwin.h>
32 #include <wx/mimetype.h>	// Do_not_auto_remove (win32)
33 #include <wx/stattext.h>
34 #include <wx/stdpaths.h>
35 #include <wx/textfile.h>	// Do_not_auto_remove (win32)
36 #include <wx/tokenzr.h>
37 #include <wx/wfstream.h>
38 #include <wx/zipstrm.h>
39 #include <wx/sysopt.h>
40 #include <wx/wupdlock.h>	// Needed for wxWindowUpdateLocker
41 
42 #include <common/EventIDs.h>
43 
44 #ifdef HAVE_CONFIG_H
45 #include "config.h"		// Needed for SVNDATE, PACKAGE, VERSION
46 #else
47 #include <common/ClientVersion.h>
48 #endif // HAVE_CONFIG_H
49 
50 #include "amuleDlg.h"		// Interface declarations.
51 
52 #include <common/Format.h>	// Needed for CFormat
53 #include "amule.h"		// Needed for theApp
54 #include "ChatWnd.h"		// Needed for CChatWnd
55 #include "SourceListCtrl.h"	// Needed for CSourceListCtrl
56 #include "DownloadListCtrl.h"	// Needed for CDownloadListCtrl
57 #include "DownloadQueue.h"	// Needed for CDownloadQueue
58 #include "KadDlg.h"		// Needed for CKadDlg
59 #include "Logger.h"
60 #include "MuleTrayIcon.h"
61 #include "muuli_wdr.h"		// Needed for ID_BUTTON*
62 #include "Preferences.h"	// Needed for CPreferences
63 #include "PrefsUnifiedDlg.h"
64 #include "SearchDlg.h"		// Needed for CSearchDlg
65 #include "Server.h"		// Needed for CServer
66 #include "ServerConnect.h"	// Needed for CServerConnect
67 #include "ServerWnd.h"		// Needed for CServerWnd
68 #include "SharedFilesWnd.h"	// Needed for CSharedFilesWnd
69 #include "SharedFilePeersListCtrl.h" // Needed for CSharedFilePeersListCtrl
70 #include "Statistics.h"		// Needed for theStats
71 #include "StatisticsDlg.h"	// Needed for CStatisticsDlg
72 #include "TerminationProcess.h"	// Needed for CTerminationProcess
73 #include "TransferWnd.h"	// Needed for CTransferWnd
74 #ifndef CLIENT_GUI
75 #include "PartFileConvertDlg.h"
76 #endif
77 #include "IPFilter.h"
78 
79 #ifndef __WINDOWS__
80 #include "aMule.xpm"
81 #endif
82 
83 #include "kademlia/kademlia/Kademlia.h"
84 #include "MuleVersion.h"	// Needed for GetMuleVersion()
85 
86 #ifdef ENABLE_IP2COUNTRY
87 #include "IP2Country.h"		// Needed for IP2Country
88 #endif
89 
90 #ifdef ENABLE_IP2COUNTRY	// That's no bug. MSVC has ENABLE_IP2COUNTRY always on,
91 							// but dummy GeoIP.h turns ENABLE_IP2COUNTRY off again.
IP2CountryDownloadFinished(uint32 result)92 void CamuleDlg::IP2CountryDownloadFinished(uint32 result)
93 {
94 	m_IP2Country->DownloadFinished(result);
95 }
96 
EnableIP2Country()97 void CamuleDlg::EnableIP2Country()
98 {
99 	if (thePrefs::IsGeoIPEnabled()) {
100 		m_IP2Country->Enable();
101 	}
102 }
103 
104 #else
105 
IP2CountryDownloadFinished(uint32)106 void CamuleDlg::IP2CountryDownloadFinished(uint32){}
EnableIP2Country()107 void CamuleDlg::EnableIP2Country(){}
108 
109 #endif
110 
BEGIN_EVENT_TABLE(CamuleDlg,wxFrame)111 BEGIN_EVENT_TABLE(CamuleDlg, wxFrame)
112 
113 	EVT_TOOL(ID_BUTTONNETWORKS, CamuleDlg::OnToolBarButton)
114 	EVT_TOOL(ID_BUTTONSEARCH, CamuleDlg::OnToolBarButton)
115 	EVT_TOOL(ID_BUTTONDOWNLOADS, CamuleDlg::OnToolBarButton)
116 	EVT_TOOL(ID_BUTTONSHARED, CamuleDlg::OnToolBarButton)
117 	EVT_TOOL(ID_BUTTONMESSAGES, CamuleDlg::OnToolBarButton)
118 	EVT_TOOL(ID_BUTTONSTATISTICS, CamuleDlg::OnToolBarButton)
119 	EVT_TOOL(ID_ABOUT, CamuleDlg::OnAboutButton)
120 
121 	EVT_TOOL(ID_BUTTONNEWPREFERENCES, CamuleDlg::OnPrefButton)
122 	EVT_TOOL(ID_BUTTONIMPORT, CamuleDlg::OnImportButton)
123 
124 	EVT_TOOL(ID_BUTTONCONNECT, CamuleDlg::OnBnConnect)
125 
126 	EVT_CLOSE(CamuleDlg::OnClose)
127 	EVT_ICONIZE(CamuleDlg::OnMinimize)
128 
129 	EVT_BUTTON(ID_BUTTON_FAST, CamuleDlg::OnBnClickedFast)
130 
131 	EVT_TIMER(ID_GUI_TIMER_EVENT, CamuleDlg::OnGUITimer)
132 
133 	EVT_SIZE(CamuleDlg::OnMainGUISizeChange)
134 
135 	EVT_KEY_UP(CamuleDlg::OnKeyPressed)
136 
137 	EVT_MENU(wxID_EXIT, CamuleDlg::OnExit)
138 
139 END_EVENT_TABLE()
140 
141 #ifndef wxCLOSE_BOX
142 	#define wxCLOSE_BOX 0
143 #endif
144 
145 CamuleDlg::CamuleDlg(
146 	wxWindow* pParent,
147 	const wxString &title,
148 	wxPoint where,
149 	wxSize dlg_size)
150 :
151 wxFrame(
152 	pParent, -1, title, where, dlg_size,
153 	wxCAPTION|wxRESIZE_BORDER|wxSYSTEM_MENU|wxDIALOG_NO_PARENT|
154 	wxRESIZE_BORDER|wxMINIMIZE_BOX|wxMAXIMIZE_BOX|wxCLOSE_BOX,
155 	wxT("aMule")),
156 m_activewnd(NULL),
157 m_transferwnd(NULL),
158 m_serverwnd(NULL),
159 m_sharedfileswnd(NULL),
160 m_searchwnd(NULL),
161 m_chatwnd(NULL),
162 m_statisticswnd(NULL),
163 m_kademliawnd(NULL),
164 m_prefsDialog(NULL),
165 m_srv_split_pos(0),
166 m_imagelist(16,16),
167 m_tblist(32,32),
168 m_prefsVisible(false),
169 m_wndToolbar(NULL),
170 m_wndTaskbarNotifier(NULL),
171 m_nActiveDialog(DT_NETWORKS_WND),
172 m_is_safe_state(false),
173 m_BlinkMessages(false),
174 m_CurrentBlinkBitmap(24),
175 m_last_iconizing(0),
176 m_skinFileName(),
177 m_clientSkinNames(CLIENT_SKIN_SIZE)
178 {
179 	// Initialize skin names
180 	m_clientSkinNames[Client_Green_Smiley]            = wxT("Transfer");
181 	m_clientSkinNames[Client_Red_Smiley]              = wxT("Connecting");
182 	m_clientSkinNames[Client_Yellow_Smiley]           = wxT("OnQueue");
183 	m_clientSkinNames[Client_Grey_Smiley]             = wxT("A4AFNoNeededPartsQueueFull");
184 	m_clientSkinNames[Client_White_Smiley]            = wxT("StatusUnknown");
185 	m_clientSkinNames[Client_ExtendedProtocol_Smiley] = wxT("ExtendedProtocol");
186 	m_clientSkinNames[Client_SecIdent_Smiley]         = wxT("SecIdent");
187 	m_clientSkinNames[Client_BadGuy_Smiley]           = wxT("BadGuy");
188 	m_clientSkinNames[Client_CreditsGrey_Smiley]      = wxT("CreditsGrey");
189 	m_clientSkinNames[Client_CreditsYellow_Smiley]    = wxT("CreditsYellow");
190 	m_clientSkinNames[Client_Upload_Smiley]           = wxT("Upload");
191 	m_clientSkinNames[Client_Friend_Smiley]           = wxT("Friend");
192 	m_clientSkinNames[Client_eMule_Smiley]            = wxT("eMule");
193 	m_clientSkinNames[Client_mlDonkey_Smiley]         = wxT("mlDonkey");
194 	m_clientSkinNames[Client_eDonkeyHybrid_Smiley]    = wxT("eDonkeyHybrid");
195 	m_clientSkinNames[Client_aMule_Smiley]            = wxT("aMule");
196 	m_clientSkinNames[Client_lphant_Smiley]           = wxT("lphant");
197 	m_clientSkinNames[Client_Shareaza_Smiley]         = wxT("Shareaza");
198 	m_clientSkinNames[Client_xMule_Smiley]            = wxT("xMule");
199 	m_clientSkinNames[Client_Unknown]                 = wxT("Unknown");
200 	m_clientSkinNames[Client_InvalidRating_Smiley]    = wxT("InvalidRatingOnFile");
201 	m_clientSkinNames[Client_PoorRating_Smiley]       = wxT("PoorRatingOnFile");
202 	m_clientSkinNames[Client_GoodRating_Smiley]       = wxT("GoodRatingOnFile");
203 	m_clientSkinNames[Client_FairRating_Smiley]       = wxT("FairRatingOnFile");
204 	m_clientSkinNames[Client_ExcellentRating_Smiley]  = wxT("ExcellentRatingOnFile");
205 	m_clientSkinNames[Client_CommentOnly_Smiley]      = wxT("CommentOnly");
206 	m_clientSkinNames[Client_Encryption_Smiley]       = wxT("Encrypted");
207 
208 	// wxWidgets send idle events to ALL WINDOWS by default... *SIGH*
209 	wxIdleEvent::SetMode(wxIDLE_PROCESS_SPECIFIED);
210 	wxUpdateUIEvent::SetMode(wxUPDATE_UI_PROCESS_SPECIFIED);
211 	wxInitAllImageHandlers();
212 	Apply_Clients_Skin();
213 
214 #ifdef __WINDOWS__
215 	wxSystemOptions::SetOption(wxT("msw.remap"), 0);
216 #endif
217 
218 #if !(wxCHECK_VERSION(2, 9, 0) && defined(__WXMAC__))
219 	// this crashes on Mac with wx 2.9
220 	SetIcon(wxICON(aMule));
221 #endif
222 
223 	srand(time(NULL));
224 
225 	// Create new sizer and stuff a wxPanel in there.
226 	wxFlexGridSizer *s_main = new wxFlexGridSizer(1);
227 	s_main->AddGrowableCol(0);
228 	s_main->AddGrowableRow(0);
229 
230 	wxPanel* p_cnt = new wxPanel(this, -1, wxDefaultPosition, wxDefaultSize);
231 	s_main->Add(p_cnt, 0, wxGROW|wxEXPAND, 0);
232 	muleDlg(p_cnt, false, true);
233 	SetSizer(s_main, true);
234 
235 	m_serverwnd = new CServerWnd(p_cnt, m_srv_split_pos);
236 	AddLogLineN(wxEmptyString);
237 	AddLogLineN(wxT(" - ") +
238 		CFormat(_("This is aMule %s based on eMule.")) % GetMuleVersion());
239 	AddLogLineN(wxT("   ") +
240 		CFormat(_("Running on %s")) % wxGetOsDescription());
241 	AddLogLineN(wxT(" - ") +
242 		wxString(_("Visit http://www.amule.org to check if a new version is available.")));
243 	AddLogLineN(wxEmptyString);
244 
245 #ifdef ENABLE_IP2COUNTRY
246 	m_GeoIPavailable = true;
247 	m_IP2Country = new CIP2Country(thePrefs::GetConfigDir());
248 #else
249 	m_GeoIPavailable = false;
250 #endif
251 	m_searchwnd = new CSearchDlg(p_cnt);
252 	m_transferwnd = new CTransferWnd(p_cnt);
253 	m_sharedfileswnd = new CSharedFilesWnd(p_cnt);
254 	m_statisticswnd = new CStatisticsDlg(p_cnt, theApp->m_statistics);
255 	m_chatwnd = new CChatWnd(p_cnt);
256 	m_kademliawnd = CastChild(wxT("kadWnd"), CKadDlg);
257 
258 	m_serverwnd->Show(false);
259 	m_searchwnd->Show(false);
260 	m_transferwnd->Show(false);
261 	m_sharedfileswnd->Show(false);
262 	m_statisticswnd->Show(false);
263 	m_chatwnd->Show(false);
264 
265 	// Create the GUI timer
266 	gui_timer=new wxTimer(this,ID_GUI_TIMER_EVENT);
267 	if (!gui_timer) {
268 		AddLogLineN(_("FATAL ERROR: Failed to create Timer"));
269 		exit(1);
270 	}
271 
272 	// Set transfers as active window
273 	Create_Toolbar(thePrefs::VerticalToolbar());
274 	SetActiveDialog(DT_TRANSFER_WND, m_transferwnd);
275 	m_wndToolbar->ToggleTool(ID_BUTTONDOWNLOADS, true );
276 
277 	bool override_where = (where != wxDefaultPosition);
278 	bool override_size = (
279 		(dlg_size.x != DEFAULT_SIZE_X) ||
280 		(dlg_size.y != DEFAULT_SIZE_Y) );
281 	if (!LoadGUIPrefs(override_where, override_size)) {
282 		// Prefs not loaded for some reason, exit
283 		AddLogLineC(wxT("Error! Unable to load Preferences") );
284 		return;
285 	}
286 
287 	// Prepare the dialog, sets the splitter-position (AFTER window size is set)
288 	m_transferwnd->Prepare();
289 
290 	m_is_safe_state = true;
291 
292 	// Init statistics stuff, better do it asap
293 	m_statisticswnd->Init();
294 	m_kademliawnd->Init();
295 	m_searchwnd->UpdateCatChoice();
296 
297 	if (thePrefs::UseTrayIcon()) {
298 		CreateSystray();
299 	}
300 
301 	Show(true);
302 	// Must we start minimized?
303 	if (thePrefs::GetStartMinimized()) {
304 		DoIconize(true);
305 	}
306 
307 	// Set shortcut keys
308 	wxAcceleratorEntry entries[] = {
309 		wxAcceleratorEntry(wxACCEL_CTRL, wxT('Q'), wxID_EXIT)
310 	};
311 
312 	SetAcceleratorTable(wxAcceleratorTable(itemsof(entries), entries));
313 	ShowED2KLinksHandler( thePrefs::GetFED2KLH() );
314 
315 	wxNotebook* logs_notebook = CastChild( ID_SRVLOG_NOTEBOOK, wxNotebook);
316 	wxNotebook* networks_notebook = CastChild( ID_NETNOTEBOOK, wxNotebook);
317 
318 	wxASSERT(logs_notebook->GetPageCount() == 4);
319 	wxASSERT(networks_notebook->GetPageCount() == 2);
320 
321 	for (uint32 i = 0; i < logs_notebook->GetPageCount(); ++i) {
322 		m_logpages[i].page = logs_notebook->GetPage(i);
323 		m_logpages[i].name = logs_notebook->GetPageText(i);
324 	}
325 
326 	for (uint32 i = 0; i < networks_notebook->GetPageCount(); ++i) {
327 		m_networkpages[i].page = networks_notebook->GetPage(i);
328 		m_networkpages[i].name = networks_notebook->GetPageText(i);
329 	}
330 
331 	DoNetworkRearrange();
332 }
333 
334 
335 // Madcat - Sets Fast ED2K Links Handler on/off.
ShowED2KLinksHandler(bool show)336 void CamuleDlg::ShowED2KLinksHandler( bool show )
337 {
338 	// Errorchecking in case the pointer becomes invalid ...
339 	if (s_fed2klh == NULL) {
340 		wxLogWarning(wxT("Unable to find Fast ED2K Links handler sizer! Hiding FED2KLH aborted."));
341 		return;
342 	}
343 
344 	s_dlgcnt->Show( s_fed2klh, show );
345 	s_dlgcnt->Layout();
346 }
347 
348 // Toogles ed2k link handler.
ToogleED2KLinksHandler()349 void CamuleDlg::ToogleED2KLinksHandler()
350 {
351 	// Errorchecking in case the pointer becomes invalid ...
352 	if (s_fed2klh == NULL) {
353 		wxLogWarning(wxT("Unable to find Fast ED2K Links handler sizer! Toogling FED2KLH aborted."));
354 		return;
355 	}
356 	ShowED2KLinksHandler(!s_dlgcnt->IsShown(s_fed2klh));
357 }
358 
SetActiveDialog(DialogType type,wxWindow * dlg)359 void CamuleDlg::SetActiveDialog(DialogType type, wxWindow* dlg)
360 {
361 	m_nActiveDialog = type;
362 
363 	if ( type == DT_TRANSFER_WND ) {
364 		if (thePrefs::ShowCatTabInfos()) {
365 			m_transferwnd->UpdateCatTabTitles();
366 		}
367 	}
368 
369 	if ( m_activewnd ) {
370 		m_activewnd->Show(false);
371 		contentSizer->Detach(m_activewnd);
372 	}
373 
374 	contentSizer->Add(dlg, 1, wxALIGN_LEFT|wxEXPAND);
375 	dlg->Show(true);
376 	m_activewnd=dlg;
377 	s_dlgcnt->Layout();
378 
379 	// Since we might be suspending redrawing while hiding the dialog
380 	// we have to refresh it once it is visible again
381 	dlg->Refresh( true );
382 	dlg->SetFocus();
383 
384 	if ( type == DT_SHARED_WND ) {
385 		// set up splitter now that window sizes are defined
386 		m_sharedfileswnd->Prepare();
387 	}
388 }
389 
390 
UpdateTrayIcon(int percent)391 void CamuleDlg::UpdateTrayIcon(int percent)
392 {
393 	// set trayicon-icon
394 	if(!theApp->IsConnected()) {
395 		m_wndTaskbarNotifier->SetTrayIcon(TRAY_ICON_DISCONNECTED, percent);
396 	} else {
397 		if(theApp->IsConnectedED2K() && theApp->serverconnect->IsLowID()) {
398 			m_wndTaskbarNotifier->SetTrayIcon(TRAY_ICON_LOWID, percent);
399 		} else {
400 			m_wndTaskbarNotifier->SetTrayIcon(TRAY_ICON_HIGHID, percent);
401 		}
402 	}
403 }
404 
405 
CreateSystray()406 void CamuleDlg::CreateSystray()
407 {
408 	wxCHECK_RET(m_wndTaskbarNotifier == NULL,
409 		wxT("Systray already created"));
410 
411 	m_wndTaskbarNotifier = new CMuleTrayIcon();
412 	// This will effectively show the Tray Icon.
413 	UpdateTrayIcon(0);
414 }
415 
416 
RemoveSystray()417 void CamuleDlg::RemoveSystray()
418 {
419 	delete m_wndTaskbarNotifier;
420 	m_wndTaskbarNotifier = NULL;
421 }
422 
423 
OnToolBarButton(wxCommandEvent & ev)424 void CamuleDlg::OnToolBarButton(wxCommandEvent& ev)
425 {
426 	static int lastbutton = ID_BUTTONDOWNLOADS;
427 
428 	// Kry - just if the GUI is ready for it
429 	if ( m_is_safe_state ) {
430 
431 		// Rehide the handler if needed
432 		if ( lastbutton == ID_BUTTONSEARCH && !thePrefs::GetFED2KLH() ) {
433 			if (ev.GetId() != ID_BUTTONSEARCH) {
434 				ShowED2KLinksHandler( false );
435 			} else {
436 				// Toogle ED2K handler.
437 				ToogleED2KLinksHandler();
438 			}
439 		}
440 
441 		if ( lastbutton != ev.GetId() ) {
442 			switch ( ev.GetId() ) {
443 				case ID_BUTTONNETWORKS:
444 					SetActiveDialog(DT_NETWORKS_WND, m_serverwnd);
445 					// Set serverlist splitter position
446 					CastChild( wxT("SrvSplitterWnd"), wxSplitterWindow )->SetSashPosition(m_srv_split_pos, true);
447 					break;
448 
449 				case ID_BUTTONSEARCH:
450 					// The search dialog should always display the handler
451 					if ( !thePrefs::GetFED2KLH() )
452 						ShowED2KLinksHandler( true );
453 
454 					SetActiveDialog(DT_SEARCH_WND, m_searchwnd);
455 					break;
456 
457 				case ID_BUTTONDOWNLOADS:
458 					SetActiveDialog(DT_TRANSFER_WND, m_transferwnd);
459 					// Prepare the dialog, sets the splitter-position
460 					m_transferwnd->Prepare();
461 					break;
462 
463 				case ID_BUTTONSHARED:
464 					SetActiveDialog(DT_SHARED_WND, m_sharedfileswnd);
465 					break;
466 
467 				case ID_BUTTONMESSAGES:
468 					m_BlinkMessages = false;
469 					SetActiveDialog(DT_CHAT_WND, m_chatwnd);
470 					break;
471 
472 				case ID_BUTTONSTATISTICS:
473 					SetActiveDialog(DT_STATS_WND, m_statisticswnd);
474 					break;
475 
476 				// This shouldn't happen, but just in case
477 				default:
478 					AddLogLineC(wxT("Unknown button triggered CamuleApp::OnToolBarButton().") );
479 					break;
480 			}
481 		}
482 
483 		m_wndToolbar->ToggleTool(lastbutton, lastbutton == ev.GetId() );
484 		lastbutton = ev.GetId();
485 	}
486 }
487 
488 
OnAboutButton(wxCommandEvent & WXUNUSED (ev))489 void CamuleDlg::OnAboutButton(wxCommandEvent& WXUNUSED(ev))
490 {
491 	wxString msg = wxT(" ");
492 #ifdef CLIENT_GUI
493 	msg << _("aMule remote control ") << wxT(VERSION);
494 #else
495 	msg << wxT("aMule ") << wxT(VERSION);
496 #endif
497 	msg << wxT(" ");
498 #ifdef SVNDATE
499 	msg << _("Snapshot:") << wxT("\n ") << wxT(SVNDATE);
500 #endif
501 	msg << wxT("\n\n") << _("'All-Platform' p2p client based on eMule \n\n") <<
502 		_("Website: http://www.amule.org \n") <<
503 		_("Forum: http://forum.amule.org \n") <<
504 		_("FAQ: http://wiki.amule.org \n\n") <<
505 		_("Contact: admin@amule.org (administrative issues) \n") <<
506 		_("Copyright (c) 2003-2019 aMule Team \n\n") <<
507 		_("Part of aMule is based on \n") <<
508 		_("Kademlia: Peer-to-peer routing based on the XOR metric.\n") <<
509                 _(" Copyright (c) 2002-2011 Petar Maymounkov ( petar@post.harvard.edu )\n") <<
510 		_("http://kademlia.scs.cs.nyu.edu\n");
511 
512 	if (m_is_safe_state) {
513 		wxMessageBox(msg, _("Message"), wxOK | wxICON_INFORMATION, this);
514 	}
515 }
516 
517 
OnPrefButton(wxCommandEvent & WXUNUSED (ev))518 void CamuleDlg::OnPrefButton(wxCommandEvent& WXUNUSED(ev))
519 {
520 	if (m_is_safe_state) {
521 		if (m_prefsDialog == NULL) {
522 			m_prefsDialog = new PrefsUnifiedDlg(this);
523 		}
524 
525 		m_prefsDialog->TransferToWindow();
526 		m_prefsDialog->Show(true);
527 		m_prefsDialog->Raise();
528 	}
529 }
530 
531 
OnImportButton(wxCommandEvent & WXUNUSED (ev))532 void CamuleDlg::OnImportButton(wxCommandEvent& WXUNUSED(ev))
533 {
534 #ifndef CLIENT_GUI
535 	if (m_is_safe_state) {
536 		CPartFileConvertDlg::ShowGUI(NULL);
537 	}
538 #endif
539 }
540 
541 
~CamuleDlg()542 CamuleDlg::~CamuleDlg()
543 {
544 	theApp->amuledlg = NULL;
545 
546 #ifdef ENABLE_IP2COUNTRY
547 	delete m_IP2Country;
548 #endif
549 
550 	AddLogLineN(_("aMule dialog destroyed"));
551 }
552 
553 
OnBnConnect(wxCommandEvent & WXUNUSED (evt))554 void CamuleDlg::OnBnConnect(wxCommandEvent& WXUNUSED(evt))
555 {
556 
557 	bool disconnect = (theApp->IsConnectedED2K() || theApp->serverconnect->IsConnecting())
558 						#ifdef CLIENT_GUI
559 						|| theApp->IsConnectedKad()		// there's no Kad running state atm
560 						#else
561 						|| (Kademlia::CKademlia::IsRunning())
562 						#endif
563 						;
564 	if (thePrefs::GetNetworkED2K()) {
565 		if (disconnect) {
566 			//disconnect if currently connected
567 			if (theApp->serverconnect->IsConnecting()) {
568 				theApp->serverconnect->StopConnectionTry();
569 			} else {
570 				theApp->serverconnect->Disconnect();
571 			}
572 		} else {
573 			//connect if not currently connected
574 			AddLogLineC(_("Connecting"));
575 			theApp->serverconnect->ConnectToAnyServer();
576 		}
577 	} else {
578 		wxASSERT(!theApp->IsConnectedED2K());
579 	}
580 
581 	// Connect Kad also
582 	if (thePrefs::GetNetworkKademlia()) {
583 		if( disconnect ) {
584 			theApp->StopKad();
585 		} else {
586 			theApp->StartKad();
587 		}
588 	} else {
589 		#ifndef CLIENT_GUI
590 			wxASSERT(!Kademlia::CKademlia::IsRunning());
591 		#endif
592 	}
593 
594 	ShowConnectionState();
595 }
596 
597 
ResetLog(int id)598 void CamuleDlg::ResetLog(int id)
599 {
600 	wxTextCtrl* ct = CastByID(id, m_serverwnd, wxTextCtrl);
601 	wxCHECK_RET(ct, wxT("Resetting unknown log"));
602 
603 	ct->Clear();
604 
605 	if (id == ID_LOGVIEW) {
606 		// Also clear the log line
607 		wxStaticText* text = CastChild(wxT("infoLabel"), wxStaticText);
608 		text->SetLabel(wxEmptyString);
609 		text->GetParent()->Layout();
610 	}
611 }
612 
613 
AddLogLine(const wxString & line)614 void CamuleDlg::AddLogLine(const wxString& line)
615 {
616 	bool addtostatusbar = line[0] == '!';
617 	wxString bufferline = line.Mid(1);
618 
619 	// Add the message to the log-view
620 	wxTextCtrl* ct = CastByID( ID_LOGVIEW, m_serverwnd, wxTextCtrl );
621 	if ( ct ) {
622 		// Bold critical log-lines
623 		// Works in Windows too thanks to wxTE_RICH2 style in muuli
624 		wxTextAttr style = ct->GetDefaultStyle();
625 		wxFont font = style.GetFont();
626 		font.SetWeight(addtostatusbar ? wxFONTWEIGHT_BOLD : wxFONTWEIGHT_NORMAL);
627 		style.SetFont(font);
628 #if wxCHECK_VERSION(2, 9, 0)
629 		style.SetFontSize(8);
630 #endif
631 		ct->SetDefaultStyle(style);
632 		ct->AppendText(bufferline);
633 		ct->ShowPosition( ct->GetLastPosition() - 1 );
634 	}
635 
636 
637 	// Set the status-bar if the event warrents it
638 	if ( addtostatusbar ) {
639 		// Escape "&"s, which would otherwise not show up
640 		bufferline.Replace( wxT("&"), wxT("&&") );
641 		wxStaticText* text = CastChild( wxT("infoLabel"), wxStaticText );
642 		// Only show the first line if multiple lines
643 		text->SetLabel( bufferline.BeforeFirst( wxT('\n') ) );
644 		text->SetToolTip( bufferline );
645 		text->GetParent()->Layout();
646 	}
647 
648 }
649 
650 
AddServerMessageLine(wxString & message)651 void CamuleDlg::AddServerMessageLine(wxString& message)
652 {
653 	wxTextCtrl* cv= CastByID( ID_SERVERINFO, m_serverwnd, wxTextCtrl );
654 	if(cv) {
655 		if (message.Length() > 500) {
656 			cv->AppendText(message.Left(500) + wxT("\n"));
657 		} else {
658 			cv->AppendText(message + wxT("\n"));
659 		}
660 		cv->ShowPosition(cv->GetLastPosition()-1);
661 	}
662 }
663 
664 
ShowConnectionState(bool skinChanged)665 void CamuleDlg::ShowConnectionState(bool skinChanged)
666 {
667 	static wxImageList status_arrows(16,16,true,0);
668 	if (!status_arrows.GetImageCount()) {
669 		// Generate the image list (This is only done once)
670 		for (int t = 0; t < 7; ++t) {
671 			status_arrows.Add(connImages(t));
672 		}
673 	}
674 
675 	m_serverwnd->UpdateED2KInfo();
676 	m_serverwnd->UpdateKadInfo();
677 
678 
679 	////////////////////////////////////////////////////////////
680 	// Determine the status of the networks
681 	//
682 	enum ED2KState { ED2KOff = 0, ED2KLowID = 1, ED2KConnecting = 2, ED2KHighID = 3, ED2KUndef = -1 };
683 	enum EKadState { EKadOff = 4, EKadFW = 5, EKadConnecting = 5, EKadOK = 6, EKadUndef = -1 };
684 
685 	ED2KState ed2kState = ED2KOff;
686 	EKadState kadState  = EKadOff;
687 
688 	////////////////////////////////////////////////////////////
689 	// Update the label on the status-bar and determine
690 	// the states of the two networks.
691 	//
692 	wxString msgED2K;
693 	if (theApp->IsConnectedED2K()) {
694 		CServer* server = theApp->serverconnect->GetCurrentServer();
695 		if (server) {
696 			msgED2K = CFormat(wxT("eD2k: %s")) % server->GetListName();
697 		}
698 
699 		if (theApp->serverconnect->IsLowID()) {
700 			ed2kState = ED2KLowID;
701 		} else {
702 			ed2kState = ED2KHighID;
703 		}
704 	} else if (theApp->serverconnect->IsConnecting()) {
705 		msgED2K = _("eD2k: Connecting");
706 
707 		ed2kState = ED2KConnecting;
708 	} else if (thePrefs::GetNetworkED2K()) {
709 		msgED2K = _("eD2k: Disconnected");
710 	}
711 
712 	wxString msgKad;
713 	if (theApp->IsConnectedKad()) {
714 		if (theApp->IsFirewalledKad()) {
715 			msgKad = _("Kad: Firewalled");
716 
717 			kadState = EKadFW;
718 		} else {
719 			msgKad = _("Kad: Connected");
720 
721 			kadState = EKadOK;
722 		}
723 	} else if (theApp->IsKadRunning()) {
724 		msgKad = _("Kad: Connecting");
725 
726 		kadState = EKadConnecting;
727 	} else if (thePrefs::GetNetworkKademlia()) {
728 		msgKad = _("Kad: Off");
729 	}
730 
731 	wxStaticText* connLabel = CastChild( wxT("connLabel"), wxStaticText );
732 	{ wxCHECK_RET(connLabel, wxT("'connLabel' widget not found")); }
733 
734 	wxString labelMsg;
735 	if (msgED2K.Length() && msgKad.Length()) {
736 		labelMsg = msgED2K + wxT(" | ") + msgKad;
737 	} else {
738 		labelMsg = msgED2K + msgKad;
739 	}
740 
741 	connLabel->SetLabel(labelMsg);
742 	connLabel->GetParent()->Layout();
743 
744 
745 	////////////////////////////////////////////////////////////
746 	// Update the connect/disconnect/cancel button.
747 	//
748 	enum EConnState {
749 		ECS_Unknown,
750 		ECS_Connected,
751 		ECS_Connecting,
752 		ECS_Disconnected
753 	};
754 
755 	static EConnState s_oldState = ECS_Unknown;
756 	EConnState currentState = ECS_Disconnected;
757 
758 	if (theApp->serverconnect->IsConnecting() ||
759 			(theApp->IsKadRunning() && !theApp->IsConnectedKad())) {
760 		currentState = ECS_Connecting;
761 	} else if (theApp->IsConnected()) {
762 		currentState = ECS_Connected;
763 	} else {
764 		currentState = ECS_Disconnected;
765 	}
766 
767 	if ( (true == skinChanged) || (currentState != s_oldState) ) {
768 		wxWindowUpdateLocker freezer(m_wndToolbar);
769 
770 		wxToolBarToolBase* toolbarTool = m_wndToolbar->RemoveTool(ID_BUTTONCONNECT);
771 
772 		switch (currentState) {
773 			case ECS_Connecting:
774 				toolbarTool->SetLabel(_("Cancel"));
775 				toolbarTool->SetShortHelp(_("Stop the current connection attempts"));
776 				toolbarTool->SetNormalBitmap(m_tblist.GetBitmap(2));
777 				break;
778 
779 			case ECS_Connected:
780 				toolbarTool->SetLabel(_("Disconnect"));
781 				toolbarTool->SetShortHelp(_("Disconnect from the currently connected networks"));
782 				toolbarTool->SetNormalBitmap(m_tblist.GetBitmap(1));
783 				break;
784 
785 			default:
786 				toolbarTool->SetLabel(_("Connect"));
787 				toolbarTool->SetShortHelp(_("Connect to the currently enabled networks"));
788 				toolbarTool->SetNormalBitmap(m_tblist.GetBitmap(0));
789 		}
790 
791 		m_wndToolbar->InsertTool(0, toolbarTool);
792 		m_wndToolbar->Realize();
793 		m_wndToolbar->EnableTool(ID_BUTTONCONNECT, (thePrefs::GetNetworkED2K() || thePrefs::GetNetworkKademlia()) && theApp->ipfilter->IsReady());
794 
795 		s_oldState = currentState;
796 	}
797 
798 
799 	////////////////////////////////////////////////////////////
800 	// Update the globe-icon in the lower-right corner.
801 	// (only if connection state has changed)
802 	//
803 	static ED2KState s_ED2KOldState = ED2KUndef;
804 	static EKadState s_EKadOldState = EKadUndef;
805 	if (ed2kState != s_ED2KOldState || kadState != s_EKadOldState) {
806 		s_ED2KOldState = ed2kState;
807 		s_EKadOldState = kadState;
808 		wxStaticBitmap* connBitmap = CastChild( wxT("connImage"), wxStaticBitmap );
809 		wxCHECK_RET(connBitmap, wxT("'connImage' widget not found"));
810 
811 		wxBitmap statusIcon = connBitmap->GetBitmap();
812 		// Sanity check - otherwise there's a crash here if aMule runs out of resources
813 		if (statusIcon.GetRefData() == NULL) {
814 			return;
815 		}
816 
817 		wxMemoryDC bitmapDC(statusIcon);
818 
819 		status_arrows.Draw(kadState, bitmapDC, 0, 0, wxIMAGELIST_DRAW_TRANSPARENT);
820 		status_arrows.Draw(ed2kState, bitmapDC, 0, 0, wxIMAGELIST_DRAW_TRANSPARENT);
821 
822 		connBitmap->SetBitmap(statusIcon);
823 	}
824 }
825 
826 
ShowUserCount(const wxString & info)827 void CamuleDlg::ShowUserCount(const wxString& info)
828 {
829 	wxStaticText* label = CastChild( wxT("userLabel"), wxStaticText );
830 
831 	// Update Kad tab
832 	m_serverwnd->UpdateKadInfo();
833 
834 	label->SetLabel(info);
835 	label->GetParent()->Layout();
836 }
837 
838 
ShowTransferRate()839 void CamuleDlg::ShowTransferRate()
840 {
841 	float kBpsUp = theStats::GetUploadRate() / 1024.0;
842 	float kBpsDown = theStats::GetDownloadRate() / 1024.0;
843 	wxString buffer;
844 	if( thePrefs::ShowOverhead() )
845 	{
846 		buffer = CFormat(_("Up: %.1f(%.1f) | Down: %.1f(%.1f)")) % kBpsUp % (theStats::GetUpOverheadRate() / 1024.0) % kBpsDown % (theStats::GetDownOverheadRate() / 1024.0);
847 	} else {
848 		buffer = CFormat(_("Up: %.1f | Down: %.1f")) % kBpsUp % kBpsDown;
849 	}
850 	buffer.Truncate(50); // Max size 50
851 
852 	wxStaticText* label = CastChild( wxT("speedLabel"), wxStaticText );
853 	label->SetLabel(buffer);
854 	label->GetParent()->Layout();
855 
856 	// Show upload/download speed in title
857 	if (thePrefs::GetShowRatesOnTitle()) {
858 		wxString UpDownSpeed = CFormat(wxT("Up: %.1f | Down: %.1f")) % kBpsUp % kBpsDown;
859 		if (thePrefs::GetShowRatesOnTitle() == 1) {
860 			SetTitle(theApp->m_FrameTitle + wxT(" -- ") + UpDownSpeed);
861 		} else {
862 			SetTitle(UpDownSpeed + wxT(" -- ") + theApp->m_FrameTitle);
863 		}
864 	}
865 
866 	wxASSERT((m_wndTaskbarNotifier != NULL) == thePrefs::UseTrayIcon());
867 	if (m_wndTaskbarNotifier) {
868 		// set trayicon-icon
869 		int percentDown = (int)ceil((kBpsDown*100) / thePrefs::GetMaxGraphDownloadRate());
870 		UpdateTrayIcon( ( percentDown > 100 ) ? 100 : percentDown);
871 
872 		wxString buffer2;
873 		if ( theApp->IsConnected() ) {
874 			buffer2 = CFormat(_("aMule (%s | Connected)")) % buffer;
875 		} else {
876 			buffer2 = CFormat(_("aMule (%s | Disconnected)")) % buffer;
877 		}
878 		m_wndTaskbarNotifier->SetTrayToolTip(buffer2);
879 	}
880 
881 	wxStaticBitmap* bmp = CastChild( wxT("transferImg"), wxStaticBitmap );
882 	bmp->SetBitmap(dlStatusImages((kBpsUp>0.01 ? 2 : 0) + (kBpsDown>0.01 ? 1 : 0)));
883 }
884 
DlgShutDown()885 void CamuleDlg::DlgShutDown()
886 {
887 	// Are we already shutting down or still on init?
888 	if ( m_is_safe_state == false ) {
889 		return;
890 	}
891 
892 	// we are going DOWN
893 	m_is_safe_state = false;
894 
895 	// Stop the GUI Timer
896 	delete gui_timer;
897 	m_transferwnd->downloadlistctrl->DeleteAllItems();
898 
899 	// We want to delete the systray too!
900 	RemoveSystray();
901 }
902 
OnClose(wxCloseEvent & evt)903 void CamuleDlg::OnClose(wxCloseEvent& evt)
904 {
905 	if (thePrefs::HideOnClose() && evt.CanVeto()) {
906 		Show(false);
907 		evt.Veto();
908 		return;
909 	}
910 
911 	// This will be here till the core close is != app close
912 	if (evt.CanVeto() && thePrefs::IsConfirmExitEnabled() ) {
913 		if (wxNO == wxMessageBox(wxString(CFormat(_("Do you really want to exit %s?")) % theApp->GetMuleAppName()),
914 				wxString(_("Exit confirmation")), wxYES_NO, this)) {
915 			evt.Veto();
916 			return;
917 		}
918 	}
919 
920 	SaveGUIPrefs();
921 
922 	Enable(false);
923 	Show(false);
924 
925 	theApp->ShutDown(evt);
926 }
927 
928 
OnBnClickedFast(wxCommandEvent & WXUNUSED (evt))929 void CamuleDlg::OnBnClickedFast(wxCommandEvent& WXUNUSED(evt))
930 {
931 	wxTextCtrl* ctl = CastChild( wxT("FastEd2kLinks"), wxTextCtrl );
932 
933 	for ( int i = 0; i < ctl->GetNumberOfLines(); i++ ) {
934 		wxString strlink = ctl->GetLineText(i);
935 		strlink.Trim(true);
936 		strlink.Trim(false);
937 		if ( !strlink.IsEmpty() ) {
938 			theApp->downloadqueue->AddLink( strlink, m_transferwnd->downloadlistctrl->GetCategory() );
939 		}
940 	}
941 
942 	ctl->SetValue(wxEmptyString);
943 }
944 
945 
946 // Formerly known as LoadRazorPrefs()
LoadGUIPrefs(bool override_pos,bool override_size)947 bool CamuleDlg::LoadGUIPrefs(bool override_pos, bool override_size)
948 {
949 	// Create a config base for loading razor preferences
950 	wxConfigBase *config = wxConfigBase::Get();
951 	// If config haven't been created exit without loading
952 	if (config == NULL) {
953 		return false;
954 	}
955 
956 	// The section where to save in in file
957 	wxString section = wxT("/Razor_Preferences/");
958 
959 	// Get window size and position
960 	int x1 = config->Read(section + wxT("MAIN_X_POS"), -1);
961 	int y1 = config->Read(section + wxT("MAIN_Y_POS"), -1);
962 	int x2 = config->Read(section + wxT("MAIN_X_SIZE"), -1);
963 	int y2 = config->Read(section + wxT("MAIN_Y_SIZE"), -1);
964 
965 	int maximized = config->Read(section + wxT("Maximized"), 01);
966 
967 	// Kry - Random usable pos for m_srv_split_pos
968 	m_srv_split_pos = config->Read(section + wxT("SRV_SPLITTER_POS"), 463l);
969 	if (!override_size) {
970 		if (x2 > 0 && y2 > 0) {
971 			SetSize(x2, y2);
972 		} else {
973 #ifndef __WXGTK__
974 			// Probably first run.
975 			Maximize();
976 #endif
977 		}
978 	}
979 
980 	if (!override_pos) {
981 		// If x1 and y1 != -1 Redefine location
982 		if(x1 != -1 && y1 != -1) {
983 			wxRect display = wxGetClientDisplayRect();
984 			if (x1 <= display.GetRightTop().x && y1 <= display.GetRightBottom().y) {
985 				Move(x1, y1);
986 			} else {
987 				// It's offscreen... so let's not.
988 			}
989 		}
990 	}
991 
992 	if (!override_size && !override_pos && maximized) {
993 		Maximize();
994 	}
995 
996 	return true;
997 }
998 
999 
SaveGUIPrefs()1000 bool CamuleDlg::SaveGUIPrefs()
1001 {
1002 	/* Razor 1a - Modif by MikaelB
1003 	   Save client size and position */
1004 
1005 	// Create a config base for saving razor preferences
1006 	wxConfigBase *config = wxConfigBase::Get();
1007 	// If config haven't been created exit without saving
1008 	if (config == NULL) {
1009 		return false;
1010 	}
1011 	// The section where to save in in file
1012 	wxString section = wxT("/Razor_Preferences/");
1013 
1014 	if (!IsIconized()) {
1015 		// Main window location and size
1016 		int x1, y1, x2, y2;
1017 		GetPosition(&x1, &y1);
1018 		GetSize(&x2, &y2);
1019 
1020 		// Saving window size and position
1021 		config->Write(section+wxT("MAIN_X_POS"), (long) x1);
1022 		config->Write(section+wxT("MAIN_Y_POS"), (long) y1);
1023 
1024 		config->Write(section+wxT("MAIN_X_SIZE"), (long) x2);
1025 		config->Write(section+wxT("MAIN_Y_SIZE"), (long) y2);
1026 
1027 		config->Write(section+wxT("Maximized"), (long) (IsMaximized() ? 1 : 0));
1028 	}
1029 
1030 	// Saving sash position of splitter in server window
1031 	config->Write(section+wxT("SRV_SPLITTER_POS"), (long) m_srv_split_pos);
1032 
1033 	config->Flush(true);
1034 
1035 	/* End modif */
1036 
1037 	return true;
1038 }
1039 
1040 
DoIconize(bool iconize)1041 void CamuleDlg::DoIconize(bool iconize)
1042 {
1043 	if (m_wndTaskbarNotifier && thePrefs::DoMinToTray()) {
1044 		if (iconize) {
1045 			// Skip() will do it.
1046 			//Iconize(true);
1047 			if (SafeState()) {
1048 				Show(false);
1049 			}
1050 		} else {
1051 			Show(true);
1052 			Raise();
1053 		}
1054 	} else {
1055 		// Will be done by Skip();
1056 		//Iconize(iconize);
1057 	}
1058 }
1059 
OnMinimize(wxIconizeEvent & evt)1060 void CamuleDlg::OnMinimize(wxIconizeEvent& evt)
1061 {
1062 // Evil Hack: check if the mouse is inside the window
1063 #ifndef __WINDOWS__
1064 	if (GetScreenRect().Contains(wxGetMousePosition()))
1065 #endif
1066 	{
1067 		if (m_prefsDialog && m_prefsDialog->IsShown()) {
1068 			// Veto.
1069 		} else {
1070 			if (m_wndTaskbarNotifier) {
1071 #if wxCHECK_VERSION(2, 9, 0)
1072 				DoIconize(evt.IsIconized());
1073 #else
1074 				DoIconize(evt.Iconized());
1075 #endif
1076 			}
1077 			evt.Skip();
1078 		}
1079 	}
1080 }
1081 
OnGUITimer(wxTimerEvent & WXUNUSED (evt))1082 void CamuleDlg::OnGUITimer(wxTimerEvent& WXUNUSED(evt))
1083 {
1084 	// Former TimerProc section
1085 
1086 	static uint32	msPrev1, msPrev5;
1087 
1088 	uint32			msCur = theStats::GetUptimeMillis();
1089 
1090 	// can this actually happen under wxwin ?
1091 	if (!SafeState()) {
1092 		return;
1093 	}
1094 
1095 #ifndef CLIENT_GUI
1096 	static uint32 msPrevGraph, msPrevStats;
1097 	int msGraphUpdate = thePrefs::GetTrafficOMeterInterval() * 1000;
1098 	if ((msGraphUpdate > 0)  && ((msCur / msGraphUpdate) > (msPrevGraph / msGraphUpdate))) {
1099 		// trying to get the graph shifts evenly spaced after a change in the update period
1100 		msPrevGraph = msCur;
1101 
1102 		GraphUpdateInfo update = theApp->m_statistics->GetPointsForUpdate();
1103 
1104 		m_statisticswnd->UpdateStatGraphs(theStats::GetPeakConnections(), update);
1105 		m_kademliawnd->UpdateGraph(update);
1106 	}
1107 
1108 	int sStatsUpdate = thePrefs::GetStatsInterval();
1109 	if ((sStatsUpdate > 0) && ((int)(msCur - msPrevStats) > sStatsUpdate*1000)) {
1110 		if (m_statisticswnd->IsShownOnScreen()) {
1111 			msPrevStats = msCur;
1112 			m_statisticswnd->ShowStatistics();
1113 		}
1114 	}
1115 #endif
1116 
1117 	if (msCur-msPrev5 > 5000) {  // every 5 seconds
1118 		msPrev5 = msCur;
1119 		ShowTransferRate();
1120 		if (thePrefs::ShowCatTabInfos() && theApp->amuledlg->m_activewnd == theApp->amuledlg->m_transferwnd) {
1121 			m_transferwnd->UpdateCatTabTitles();
1122 		}
1123 		if (thePrefs::AutoSortDownload()) {
1124 			m_transferwnd->downloadlistctrl->SortList();
1125 			m_transferwnd->clientlistctrl->SortList();
1126 			m_sharedfileswnd->peerslistctrl->SortList();
1127 		}
1128 		m_kademliawnd->UpdateNodeCount(CStatistics::GetKadNodes());
1129 	}
1130 
1131 	if (msCur-msPrev1 > 1000) {  // every second
1132 		msPrev1 = msCur;
1133 		if (m_CurrentBlinkBitmap == 12) {
1134 			m_CurrentBlinkBitmap = 7;
1135 			SetMessagesTool();
1136 		} else {
1137 			if (m_BlinkMessages) {
1138 				m_CurrentBlinkBitmap = 12;
1139 				SetMessagesTool();
1140 			}
1141 		}
1142 
1143 	}
1144 }
1145 
1146 
SetMessagesTool()1147 void CamuleDlg::SetMessagesTool()
1148 {
1149 	wxWindowUpdateLocker freezer(m_wndToolbar);
1150 #ifdef __WXCOCOA__
1151 	m_wndToolbar->FindById(ID_BUTTONMESSAGES)->SetNormalBitmap(m_tblist.GetBitmap(m_CurrentBlinkBitmap));
1152 #else
1153 	m_wndToolbar->SetToolNormalBitmap(ID_BUTTONMESSAGES, m_tblist.GetBitmap(m_CurrentBlinkBitmap));
1154 #endif
1155 }
1156 
LaunchUrl(const wxString & url)1157 void CamuleDlg::LaunchUrl( const wxString& url )
1158 {
1159 	wxString cmd;
1160 
1161 	cmd = thePrefs::GetBrowser();
1162 	wxString tmp = url;
1163 	// Pipes cause problems, so escape them
1164 	tmp.Replace( wxT("|"), wxT("%7C") );
1165 
1166 	if ( !cmd.IsEmpty() ) {
1167 		if (!cmd.Replace(wxT("%s"), tmp)) {
1168 			// No %s found, just append the url
1169 			cmd += wxT(" ") + tmp;
1170 		}
1171 
1172 		CTerminationProcess *p = new CTerminationProcess(cmd);
1173 		if (wxExecute(cmd, wxEXEC_ASYNC, p)) {
1174 			AddLogLineN(_("Launch Command: ") + cmd);
1175 			return;
1176 		} else {
1177 			delete p;
1178 		}
1179 	} else {
1180 		wxLaunchDefaultBrowser(tmp);
1181 		return;
1182 	}
1183 	// Unable to execute browser. But this error message doesn't make sense,
1184 	// cosidering that you _can't_ set the browser executable path... =/
1185 	wxLogError(wxT("Unable to launch browser. Please set correct browser executable path in Preferences."));
1186 }
1187 
1188 
Check_and_Init_Skin()1189 bool CamuleDlg::Check_and_Init_Skin()
1190 {
1191 	bool ret = true;
1192 	wxString skinFileName(thePrefs::GetSkin());
1193 
1194 	if (skinFileName.IsEmpty() || skinFileName.IsSameAs(_("- default -"))) {
1195 		return false;
1196 	}
1197 
1198 	wxString userDir(JoinPaths(thePrefs::GetConfigDir(), wxT("skins")) + wxFileName::GetPathSeparator());
1199 
1200 	wxStandardPathsBase &spb(wxStandardPaths::Get());
1201 #ifdef __WINDOWS__
1202 	wxString dataDir(spb.GetPluginsDir());
1203 #elif defined(__WXMAC__)
1204 		wxString dataDir(spb.GetDataDir());
1205 #else
1206 	wxString dataDir(spb.GetDataDir().BeforeLast(wxT('/')) + wxT("/amule"));
1207 #endif
1208 	wxString systemDir(JoinPaths(dataDir,wxT("skins")) + wxFileName::GetPathSeparator());
1209 
1210 
1211 	skinFileName.Replace(wxT("User:"), userDir );
1212 	skinFileName.Replace(wxT("System:"), systemDir );
1213 
1214 	m_skinFileName.Assign(skinFileName);
1215 	if (!m_skinFileName.FileExists()) {
1216 		AddLogLineC(CFormat(
1217 			_("Skin directory '%s' does not exist")) %
1218 			skinFileName );
1219 		ret = false;
1220 	} else if (!m_skinFileName.IsFileReadable()) {
1221 		AddLogLineC(CFormat(
1222 			_("WARNING: Unable to open skin file '%s' for read")) %
1223 			skinFileName);
1224 		ret = false;
1225 	}
1226 
1227 	wxFFileInputStream in(m_skinFileName.GetFullPath());
1228 	wxZipInputStream zip(in);
1229 	wxZipEntry *entry;
1230 
1231 	while ((entry = zip.GetNextEntry()) != NULL) {
1232 		wxZipEntry*& current = cat[entry->GetInternalName()];
1233 		delete current;
1234 		current = entry;
1235 	}
1236 
1237 	return ret;
1238 }
1239 
1240 
Add_Skin_Icon(const wxString & iconName,const wxBitmap & stdIcon,bool useSkins)1241 void CamuleDlg::Add_Skin_Icon(
1242 	const wxString &iconName,
1243 	const wxBitmap &stdIcon,
1244 	bool useSkins)
1245 {
1246 	wxImage new_image;
1247 	if (useSkins) {
1248 		wxFFileInputStream in(m_skinFileName.GetFullPath());
1249 		wxZipInputStream zip(in);
1250 
1251 		ZipCatalog::iterator it = cat.find(wxZipEntry::GetInternalName(iconName + wxT(".png")));
1252 		if ( it != cat.end() ) {
1253 			zip.OpenEntry(*it->second);
1254 			if ( !new_image.LoadFile(zip,wxBITMAP_TYPE_PNG) ) {
1255 				AddLogLineN(wxT("Warning: Error loading icon for ") +
1256 						iconName);
1257 				useSkins = false;
1258 			}
1259 		}else {
1260 				AddLogLineN(wxT("Warning: Can't load icon for ") +
1261 						iconName);
1262 				useSkins = false;
1263 		}
1264 
1265 	}
1266 
1267 	wxBitmap bmp(useSkins ? new_image : stdIcon);
1268 	if (iconName.StartsWith(wxT("Client_"))) {
1269 		m_imagelist.Add(bmp);
1270 	} else if (iconName.StartsWith(wxT("Toolbar_"))) {
1271 		m_tblist.Add(bmp);
1272 	}
1273 }
1274 
1275 
Apply_Clients_Skin()1276 void CamuleDlg::Apply_Clients_Skin()
1277 {
1278 	bool useSkins = Check_and_Init_Skin();
1279 
1280 	// Clear the client image list
1281 	m_imagelist.RemoveAll();
1282 
1283 	// Add the images to the image list
1284 	for (int i = 0; i < CLIENT_SKIN_SIZE; ++i) {
1285 		Add_Skin_Icon(wxT("Client_") + m_clientSkinNames[i],
1286 			clientImages(i), useSkins);
1287 	}
1288 }
1289 
1290 
Apply_Toolbar_Skin(wxToolBar * wndToolbar)1291 void CamuleDlg::Apply_Toolbar_Skin(wxToolBar *wndToolbar)
1292 {
1293 	bool useSkins = Check_and_Init_Skin();
1294 
1295 
1296 	// Clear the toolbar image list
1297 	m_tblist.RemoveAll();
1298 
1299 	// Add the images to the image list
1300 	Add_Skin_Icon(wxT("Toolbar_Connect"),    connButImg(0),      useSkins);
1301 	Add_Skin_Icon(wxT("Toolbar_Disconnect"), connButImg(1),      useSkins);
1302 	Add_Skin_Icon(wxT("Toolbar_Connecting"), connButImg(2),      useSkins);
1303 	Add_Skin_Icon(wxT("Toolbar_Network"),    amuleDlgImages(20), useSkins);
1304 	Add_Skin_Icon(wxT("Toolbar_Transfers"),  amuleDlgImages(21), useSkins);
1305 	Add_Skin_Icon(wxT("Toolbar_Search"),     amuleDlgImages(22), useSkins);
1306 	Add_Skin_Icon(wxT("Toolbar_Shared"),     amuleDlgImages(23), useSkins);
1307 	Add_Skin_Icon(wxT("Toolbar_Messages"),   amuleDlgImages(24), useSkins);
1308 	Add_Skin_Icon(wxT("Toolbar_Stats"),      amuleDlgImages(25), useSkins);
1309 	Add_Skin_Icon(wxT("Toolbar_Prefs"),      amuleDlgImages(26), useSkins);
1310 	Add_Skin_Icon(wxT("Toolbar_Import"),     amuleDlgImages(32), useSkins);
1311 	Add_Skin_Icon(wxT("Toolbar_About"),      amuleDlgImages(29), useSkins);
1312 	Add_Skin_Icon(wxT("Toolbar_Blink"),	 amuleDlgImages(33), useSkins);
1313 
1314 	// Build aMule toolbar
1315 	wndToolbar->SetMargins(0, 0);
1316 
1317 	// Placeholder. Gets updated by ShowConnectionState
1318 	wndToolbar->AddTool(ID_BUTTONCONNECT, wxT("..."), m_tblist.GetBitmap(0));
1319 
1320 	wndToolbar->AddSeparator();
1321 	wndToolbar->AddTool(ID_BUTTONNETWORKS, _("Networks"), m_tblist.GetBitmap(3), wxNullBitmap, wxITEM_CHECK, _("Networks Window"));
1322 	wndToolbar->AddTool(ID_BUTTONSEARCH, _("Searches"), m_tblist.GetBitmap(5), wxNullBitmap, wxITEM_CHECK, _("Searches Window"));
1323 	wndToolbar->AddTool(ID_BUTTONDOWNLOADS, _("Downloads"), m_tblist.GetBitmap(4), wxNullBitmap, wxITEM_CHECK, _("Downloads Window"));
1324 	wndToolbar->AddTool(ID_BUTTONSHARED, _("Shared files"), m_tblist.GetBitmap(6), wxNullBitmap, wxITEM_CHECK, _("Shared Files Window"));
1325 	wndToolbar->AddTool(ID_BUTTONMESSAGES, _("Messages"), m_tblist.GetBitmap(7), wxNullBitmap, wxITEM_CHECK, _("Messages Window"));
1326 	wndToolbar->AddTool(ID_BUTTONSTATISTICS, _("Statistics"), m_tblist.GetBitmap(8), wxNullBitmap, wxITEM_CHECK, _("Statistics Graph Window"));
1327 	wndToolbar->AddSeparator();
1328 	wndToolbar->AddTool(ID_BUTTONNEWPREFERENCES, _("Preferences"), m_tblist.GetBitmap(9), wxNullBitmap, wxITEM_NORMAL, _("Preferences Settings Window"));
1329 #ifndef CLIENT_GUI
1330 	wndToolbar->AddTool(ID_BUTTONIMPORT, _("Import"), m_tblist.GetBitmap(10), wxNullBitmap, wxITEM_NORMAL, _("The partfile importer tool"));
1331 #endif
1332 	wndToolbar->AddTool(ID_ABOUT, _("About"), m_tblist.GetBitmap(11), wxNullBitmap, wxITEM_NORMAL, _("About/Help"));
1333 
1334 	wndToolbar->ToggleTool(ID_BUTTONDOWNLOADS, true);
1335 
1336 	// Needed for non-GTK platforms, where the
1337 	// items don't get added immediatly.
1338 	wndToolbar->Realize();
1339 
1340 	// Updates the "Connect" button, and so on.
1341 	ShowConnectionState(true);
1342 }
1343 
1344 
Create_Toolbar(bool orientation)1345 void CamuleDlg::Create_Toolbar(bool orientation)
1346 {
1347 	Freeze();
1348 	// Create ToolBar from the one designed by wxDesigner (BigBob)
1349 	wxToolBar *current = GetToolBar();
1350 
1351 	wxASSERT(current == m_wndToolbar);
1352 
1353 	if (current) {
1354 		bool oldorientation = ((current->GetWindowStyle() & wxTB_VERTICAL) == wxTB_VERTICAL);
1355 		if (oldorientation != orientation) {
1356 			current->Destroy();
1357 			SetToolBar(NULL); // Remove old one if present
1358 			m_wndToolbar = NULL;
1359 		} else {
1360 			current->ClearTools();
1361 		}
1362 	}
1363 
1364 	if (!m_wndToolbar) {
1365         #if wxCHECK_VERSION(3, 1, 2)
1366             m_wndToolbar = CreateToolBar(
1367                 (orientation ? wxTB_VERTICAL : wxTB_HORIZONTAL) |
1368                 wxNO_BORDER | wxTB_TEXT | wxTB_FLAT |
1369                 wxCLIP_CHILDREN | wxTB_NODIVIDER);
1370         #else
1371             m_wndToolbar = CreateToolBar(
1372                 (orientation ? wxTB_VERTICAL : wxTB_HORIZONTAL) |
1373                 wxNO_BORDER | wxTB_TEXT | wxTB_3DBUTTONS |
1374                 wxTB_FLAT | wxCLIP_CHILDREN | wxTB_NODIVIDER);
1375         #endif
1376 
1377 			m_wndToolbar->SetToolBitmapSize(wxSize(32, 32));
1378 	}
1379 
1380 	Apply_Toolbar_Skin(m_wndToolbar);
1381 
1382 	Thaw();
1383 }
1384 
1385 
OnMainGUISizeChange(wxSizeEvent & evt)1386 void CamuleDlg::OnMainGUISizeChange(wxSizeEvent& evt)
1387 {
1388 	wxFrame::OnSize(evt);
1389 	if (m_transferwnd && m_transferwnd->clientlistctrl) {
1390 		// Transfer window's splitter set again if it's hidden.
1391 		if (!m_transferwnd->clientlistctrl->GetShowing()) {
1392 			int height = m_transferwnd->clientlistctrl->GetSize().GetHeight();
1393 			wxSplitterWindow* splitter =
1394 				CastChild(wxT("splitterWnd"), wxSplitterWindow);
1395 			height += splitter->GetWindow1()->GetSize().GetHeight();
1396 			splitter->SetSashPosition( height );
1397 		}
1398 	}
1399 }
1400 
1401 
OnKeyPressed(wxKeyEvent & event)1402 void CamuleDlg::OnKeyPressed(wxKeyEvent& event)
1403 {
1404 	if (event.GetKeyCode() == WXK_F1) {
1405 		// Ctrl/Alt/Shift must not be pressed, to avoid
1406 		// conflicts with other (global) shortcuts.
1407 		if (!event.HasModifiers() && !event.ShiftDown()) {
1408 			LaunchUrl(wxT("http://wiki.amule.org"));
1409 			return;
1410 		}
1411 	}
1412 
1413 	event.Skip();
1414 }
1415 
1416 
OnExit(wxCommandEvent & WXUNUSED (evt))1417 void CamuleDlg::OnExit(wxCommandEvent& WXUNUSED(evt))
1418 {
1419 	Close(true);
1420 }
1421 
DoNetworkRearrange()1422 void CamuleDlg::DoNetworkRearrange()
1423 {
1424 #if !defined(__WXOSX_COCOA__)
1425 	// in Mac OS with wxWidgets >= 3.0 and COCOA the following seems to cause problems
1426 	// (window is not refreshed after changes in network settings)
1427 	wxWindowUpdateLocker freezer(this);
1428 #endif
1429 
1430 	wxToolBarToolBase* toolbarTool = m_wndToolbar->RemoveTool(ID_BUTTONNETWORKS);
1431 
1432 	// set the log windows
1433 	wxNotebook* logs_notebook = CastChild( ID_SRVLOG_NOTEBOOK, wxNotebook);
1434 
1435 	while (logs_notebook->GetPageCount() > 1) {
1436 		logs_notebook->RemovePage(logs_notebook->GetPageCount() - 1);
1437 	}
1438 
1439 	if (thePrefs::GetNetworkED2K()) {
1440 #ifndef CLIENT_GUI
1441 		logs_notebook->AddPage(m_logpages[1].page, m_logpages[1].name);
1442 #endif
1443 		logs_notebook->AddPage(m_logpages[2].page, m_logpages[2].name);
1444 	}
1445 
1446 	if (thePrefs::GetNetworkKademlia()) {
1447 		logs_notebook->AddPage(m_logpages[3].page, m_logpages[3].name);
1448 	}
1449 
1450 	// Set the main window.
1451 	// If we have both networks active, activate a notebook to select between them.
1452 	// If only one is active, show the window directly without a surrounding one tab notebook.
1453 
1454 	// States:
1455 	// 1: ED2K only
1456 	// 2: Kad only
1457 	// 3: both (in Notebook)
1458 
1459 	static uint8 currentState = 3;		// on startup we have both enabled
1460 	uint8 newState;
1461 	if (thePrefs::GetNetworkED2K() && thePrefs::GetNetworkKademlia()) {
1462 		newState = 3;
1463 		toolbarTool->SetLabel(_("Networks"));
1464 	}
1465 	else if (thePrefs::GetNetworkED2K()) {
1466 		newState = 1;
1467 		toolbarTool->SetLabel(_("eD2k network"));
1468 	}
1469 	else {			// Kad only or no network
1470 		newState = 2;	// no network makes no sense anyway, so just show Kad there
1471 		toolbarTool->SetLabel(thePrefs::GetNetworkKademlia() ? _("Kad network") : _("No network"));
1472 	}
1473 
1474 	if (newState != currentState) {
1475 		wxNotebook* networks_notebook = CastChild(ID_NETNOTEBOOK, wxNotebook);
1476 		// First hide all windows
1477 		networks_notebook->Show(false);
1478 		m_networkpages[0].page->Show(false);
1479 		m_networkpages[1].page->Show(false);
1480 		m_networknotebooksizer->Clear();
1481 
1482 		wxWindow* replacement = NULL;
1483 
1484 		// Move both pages into the notebook if they aren't already there.
1485 		if (currentState == 1) {	// ED2K
1486 			m_networkpages[0].page->Reparent(networks_notebook);
1487 			networks_notebook->InsertPage(0, m_networkpages[0].page, m_networkpages[0].name);
1488 		} else if (currentState == 2) {	// Kad
1489 			m_networkpages[1].page->Reparent(networks_notebook);
1490 			networks_notebook->AddPage(m_networkpages[1].page, m_networkpages[1].name);
1491 		}
1492 
1493 		// Now both pages are in the notebook. If we want to show one of them outside, move it back out again.
1494 		// Windows that are part of a notebook can't be reparented.
1495 		if (newState == 3) {
1496 			// Since we messed with the notebook, we now have to show both pages, one after the other.
1497 			// Otherwise GTK gets confused and shows the first tab only.
1498 			// (So much for "platform independent".)
1499 			networks_notebook->SetSelection(1);
1500 			m_networkpages[1].page->Show();
1501 			networks_notebook->SetSelection(0);
1502 			m_networkpages[0].page->Show();
1503 			replacement = networks_notebook;
1504 		} else if (newState == 1) {
1505 			replacement = m_networkpages[0].page;
1506 			networks_notebook->RemovePage(0);
1507 		} else {
1508 			replacement = m_networkpages[1].page;
1509 			networks_notebook->RemovePage(1);
1510 		}
1511 
1512 		replacement->Reparent(m_networknotebooksizer->GetContainingWindow());
1513 		replacement->Show();
1514 		m_networknotebooksizer->Add(replacement, 1, wxGROW | wxALIGN_CENTER_VERTICAL | wxTOP, 5);
1515 		m_networknotebooksizer->Layout();
1516 		currentState = newState;
1517 	}
1518 
1519 	// Tool bar
1520 
1521 	m_wndToolbar->InsertTool(2, toolbarTool);
1522 	m_wndToolbar->EnableTool(ID_BUTTONNETWORKS, (thePrefs::GetNetworkED2K() || thePrefs::GetNetworkKademlia()));
1523 	m_wndToolbar->EnableTool(ID_BUTTONCONNECT, (thePrefs::GetNetworkED2K() || thePrefs::GetNetworkKademlia()) && theApp->ipfilter->IsReady());
1524 
1525 	m_wndToolbar->Realize();
1526 
1527 	ShowConnectionState();	// status in the bottom right
1528 	m_searchwnd->FixSearchTypes();
1529 }
1530 
1531 // File_checked_for_headers
1532