1
2//
3// This file is part of the aMule Project.
4//
5// Copyright (c) 2003-2011 aMule Team ( admin@amule.org / http://www.amule.org )
6// Copyright (c) 2002-2011 Merkur ( devs@emule-project.net / http://www.emule-project.net )
7//
8// Any parts of this program derived from the xMule, lMule or eMule project,
9// or contributed by third-party developers are copyrighted by their
10// respective authors.
11//
12// This program is free software; you can redistribute it and/or modify
13// it under the terms of the GNU General Public License as published by
14// the Free Software Foundation; either version 2 of the License, or
15// (at your option) any later version.
16//
17// This program is distributed in the hope that it will be useful,
18// but WITHOUT ANY WARRANTY; without even the implied warranty of
19// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20// GNU General Public License for more details.
21//
22// You should have received a copy of the GNU General Public License
23// along with this program; if not, write to the Free Software
24// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA
25//
26
27#include <wx/app.h>
28
29#include <wx/archive.h>
30#include <wx/config.h>		// Do_not_auto_remove (MacOS 10.3, wx 2.7)
31#include <wx/confbase.h>	// Do_not_auto_remove (MacOS 10.3, wx 2.7)
32#include <wx/html/htmlwin.h>
33#include <wx/mimetype.h>	// Do_not_auto_remove (win32)
34#include <wx/stattext.h>
35#include <wx/stdpaths.h>
36#include <wx/textfile.h>	// Do_not_auto_remove (win32)
37#include <wx/tokenzr.h>
38#include <wx/wfstream.h>
39#include <wx/zipstrm.h>
40#include <wx/sysopt.h>
41#include <wx/wupdlock.h>	// Needed for wxWindowUpdateLocker
42
43#include <common/EventIDs.h>
44
45#ifdef HAVE_CONFIG_H
46#include "config.h"		// Needed for SVNDATE, PACKAGE, VERSION
47#else
48#include <common/ClientVersion.h>
49#endif // HAVE_CONFIG_H
50
51#include "amuleDlg.h"		// Interface declarations.
52
53#include <common/Format.h>	// Needed for CFormat
54#include "amule.h"		// Needed for theApp
55#include "ChatWnd.h"		// Needed for CChatWnd
56#include "SourceListCtrl.h"	// Needed for CSourceListCtrl
57#include "DownloadListCtrl.h"	// Needed for CDownloadListCtrl
58#include "DownloadQueue.h"	// Needed for CDownloadQueue
59#include "KadDlg.h"		// Needed for CKadDlg
60#include "Logger.h"
61#include "MuleTrayIcon.h"
62#include "muuli_wdr.h"		// Needed for ID_BUTTON*
63#include "Preferences.h"	// Needed for CPreferences
64#include "PrefsUnifiedDlg.h"
65#include "SearchDlg.h"		// Needed for CSearchDlg
66#include "Server.h"		// Needed for CServer
67#include "ServerConnect.h"	// Needed for CServerConnect
68#include "ServerWnd.h"		// Needed for CServerWnd
69#include "SharedFilesWnd.h"	// Needed for CSharedFilesWnd
70#include "SharedFilePeersListCtrl.h" // Needed for CSharedFilePeersListCtrl
71#include "Statistics.h"		// Needed for theStats
72#include "StatisticsDlg.h"	// Needed for CStatisticsDlg
73#include "TerminationProcess.h"	// Needed for CTerminationProcess
74#include "TransferWnd.h"	// Needed for CTransferWnd
75#ifndef CLIENT_GUI
76#include "PartFileConvertDlg.h"
77#endif
78#include "IPFilter.h"
79
80#ifndef __WXMSW__
81#include "aMule.xpm"
82#endif
83
84#include "kademlia/kademlia/Kademlia.h"
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.
92void CamuleDlg::IP2CountryDownloadFinished(uint32 result)
93{
94	m_IP2Country->DownloadFinished(result);
95}
96
97void CamuleDlg::EnableIP2Country()
98{
99	if (thePrefs::IsGeoIPEnabled()) {
100		m_IP2Country->Enable();
101	}
102}
103
104#else
105
106void CamuleDlg::IP2CountryDownloadFinished(uint32){}
107void CamuleDlg::EnableIP2Country(){}
108
109#endif
110
111BEGIN_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
139END_EVENT_TABLE()
140
141#ifndef wxCLOSE_BOX
142	#define wxCLOSE_BOX 0
143#endif
144
145CamuleDlg::CamuleDlg(
146	wxWindow* pParent,
147	const wxString &title,
148	wxPoint where,
149	wxSize dlg_size)
150:
151wxFrame(
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")),
156m_activewnd(NULL),
157m_transferwnd(NULL),
158m_serverwnd(NULL),
159m_sharedfileswnd(NULL),
160m_searchwnd(NULL),
161m_chatwnd(NULL),
162m_statisticswnd(NULL),
163m_kademliawnd(NULL),
164m_prefsDialog(NULL),
165m_srv_split_pos(0),
166m_imagelist(16,16),
167m_tblist(32,32),
168m_prefsVisible(false),
169m_wndToolbar(NULL),
170m_wndTaskbarNotifier(NULL),
171m_nActiveDialog(DT_NETWORKS_WND),
172m_is_safe_state(false),
173m_BlinkMessages(false),
174m_CurrentBlinkBitmap(24),
175m_last_iconizing(0),
176m_skinFileName(),
177m_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 __WXMSW__
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(theApp->ConfigDir);
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.
336void 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.
349void 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
359void 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
391void 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
406void 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
417void CamuleDlg::RemoveSystray()
418{
419	delete m_wndTaskbarNotifier;
420	m_wndTaskbarNotifier = NULL;
421}
422
423
424void 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
489void 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-2011 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
518void 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
532void 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
542CamuleDlg::~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
554void 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
598void 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
614void 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
651void 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
665void 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
827void 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
839void 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
885void 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
903void 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
929void 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()
947bool 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
1000bool 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
1041void 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
1060void CamuleDlg::OnMinimize(wxIconizeEvent& evt)
1061{
1062// Evil Hack: check if the mouse is inside the window
1063#ifndef __WXMSW__
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
1082void 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	}
1129
1130	if (msCur-msPrev1 > 1000) {  // every second
1131		msPrev1 = msCur;
1132		if (m_CurrentBlinkBitmap == 12) {
1133			m_CurrentBlinkBitmap = 7;
1134			SetMessagesTool();
1135		} else {
1136			if (m_BlinkMessages) {
1137				m_CurrentBlinkBitmap = 12;
1138				SetMessagesTool();
1139			}
1140		}
1141
1142	}
1143}
1144
1145
1146void CamuleDlg::SetMessagesTool()
1147{
1148	wxWindowUpdateLocker freezer(m_wndToolbar);
1149#ifdef __WXCOCOA__
1150	m_wndToolbar->FindById(ID_BUTTONMESSAGES)->SetNormalBitmap(m_tblist.GetBitmap(m_CurrentBlinkBitmap));
1151#else
1152	m_wndToolbar->SetToolNormalBitmap(ID_BUTTONMESSAGES, m_tblist.GetBitmap(m_CurrentBlinkBitmap));
1153#endif
1154}
1155
1156void CamuleDlg::LaunchUrl( const wxString& url )
1157{
1158	wxString cmd;
1159
1160	cmd = thePrefs::GetBrowser();
1161	wxString tmp = url;
1162	// Pipes cause problems, so escape them
1163	tmp.Replace( wxT("|"), wxT("%7C") );
1164
1165	if ( !cmd.IsEmpty() ) {
1166		if (!cmd.Replace(wxT("%s"), tmp)) {
1167			// No %s found, just append the url
1168			cmd += wxT(" ") + tmp;
1169		}
1170
1171		CTerminationProcess *p = new CTerminationProcess(cmd);
1172		if (wxExecute(cmd, wxEXEC_ASYNC, p)) {
1173			AddLogLineN(_("Launch Command: ") + cmd);
1174			return;
1175		} else {
1176			delete p;
1177		}
1178	} else {
1179		wxLaunchDefaultBrowser(tmp);
1180		return;
1181	}
1182	// Unable to execute browser. But this error message doesn't make sense,
1183	// cosidering that you _can't_ set the browser executable path... =/
1184	wxLogError(wxT("Unable to launch browser. Please set correct browser executable path in Preferences."));
1185}
1186
1187
1188wxString CamuleDlg::GenWebSearchUrl(const wxString &filename, WebSearch wsProvider )
1189{
1190	wxString URL;
1191	switch (wsProvider)  {
1192		case WS_FILEHASH:
1193			URL = wxT("http://www.filehash.com/search.html?pattern=FILENAME&submit=Find");
1194			break;
1195		default:
1196			wxFAIL;
1197	}
1198	URL.Replace(wxT("FILENAME"), filename);
1199
1200	return URL;
1201}
1202
1203
1204bool CamuleDlg::Check_and_Init_Skin()
1205{
1206	bool ret = true;
1207	wxString skinFileName(thePrefs::GetSkin());
1208
1209	if (skinFileName.IsEmpty() || skinFileName.IsSameAs(_("- default -"))) {
1210		return false;
1211	}
1212
1213	wxString userDir(JoinPaths(GetConfigDir(), wxT("skins")) + wxFileName::GetPathSeparator());
1214
1215	wxStandardPathsBase &spb(wxStandardPaths::Get());
1216#ifdef __WXMSW__
1217	wxString dataDir(spb.GetPluginsDir());
1218#elif defined(__WXMAC__)
1219		wxString dataDir(spb.GetDataDir());
1220#else
1221	wxString dataDir(spb.GetDataDir().BeforeLast(wxT('/')) + wxT("/amule"));
1222#endif
1223	wxString systemDir(JoinPaths(dataDir,wxT("skins")) + wxFileName::GetPathSeparator());
1224
1225
1226	skinFileName.Replace(wxT("User:"), userDir );
1227	skinFileName.Replace(wxT("System:"), systemDir );
1228
1229	m_skinFileName.Assign(skinFileName);
1230	if (!m_skinFileName.FileExists()) {
1231		AddLogLineC(CFormat(
1232			_("Skin directory '%s' does not exist")) %
1233			skinFileName );
1234		ret = false;
1235	} else if (!m_skinFileName.IsFileReadable()) {
1236		AddLogLineC(CFormat(
1237			_("WARNING: Unable to open skin file '%s' for read")) %
1238			skinFileName);
1239		ret = false;
1240	}
1241
1242	wxFFileInputStream in(m_skinFileName.GetFullPath());
1243	wxZipInputStream zip(in);
1244
1245	while ((entry = zip.GetNextEntry()) != NULL) {
1246		wxZipEntry*& current = cat[entry->GetInternalName()];
1247		delete current;
1248		current = entry;
1249	}
1250
1251	return ret;
1252}
1253
1254
1255void CamuleDlg::Add_Skin_Icon(
1256	const wxString &iconName,
1257	const wxBitmap &stdIcon,
1258	bool useSkins)
1259{
1260	wxImage new_image;
1261	if (useSkins) {
1262		wxFFileInputStream in(m_skinFileName.GetFullPath());
1263		wxZipInputStream zip(in);
1264
1265		it = cat.find(wxZipEntry::GetInternalName(iconName + wxT(".png")));
1266		if ( it != cat.end() ) {
1267			zip.OpenEntry(*it->second);
1268			if ( !new_image.LoadFile(zip,wxBITMAP_TYPE_PNG) ) {
1269				AddLogLineN(wxT("Warning: Error loading icon for ") +
1270						iconName);
1271				useSkins = false;
1272			}
1273		}else {
1274				AddLogLineN(wxT("Warning: Can't load icon for ") +
1275						iconName);
1276				useSkins = false;
1277		}
1278
1279	}
1280
1281	wxBitmap bmp(useSkins ? new_image : stdIcon);
1282	if (iconName.StartsWith(wxT("Client_"))) {
1283		m_imagelist.Add(bmp);
1284	} else if (iconName.StartsWith(wxT("Toolbar_"))) {
1285		m_tblist.Add(bmp);
1286	}
1287}
1288
1289
1290void CamuleDlg::Apply_Clients_Skin()
1291{
1292	bool useSkins = Check_and_Init_Skin();
1293
1294	// Clear the client image list
1295	m_imagelist.RemoveAll();
1296
1297	// Add the images to the image list
1298	for (int i = 0; i < CLIENT_SKIN_SIZE; ++i) {
1299		Add_Skin_Icon(wxT("Client_") + m_clientSkinNames[i],
1300			clientImages(i), useSkins);
1301	}
1302}
1303
1304
1305void CamuleDlg::Apply_Toolbar_Skin(wxToolBar *wndToolbar)
1306{
1307	bool useSkins = Check_and_Init_Skin();
1308
1309
1310	// Clear the toolbar image list
1311	m_tblist.RemoveAll();
1312
1313	// Add the images to the image list
1314	Add_Skin_Icon(wxT("Toolbar_Connect"),    connButImg(0),      useSkins);
1315	Add_Skin_Icon(wxT("Toolbar_Disconnect"), connButImg(1),      useSkins);
1316	Add_Skin_Icon(wxT("Toolbar_Connecting"), connButImg(2),      useSkins);
1317	Add_Skin_Icon(wxT("Toolbar_Network"),    amuleDlgImages(20), useSkins);
1318	Add_Skin_Icon(wxT("Toolbar_Transfers"),  amuleDlgImages(21), useSkins);
1319	Add_Skin_Icon(wxT("Toolbar_Search"),     amuleDlgImages(22), useSkins);
1320	Add_Skin_Icon(wxT("Toolbar_Shared"),     amuleDlgImages(23), useSkins);
1321	Add_Skin_Icon(wxT("Toolbar_Messages"),   amuleDlgImages(24), useSkins);
1322	Add_Skin_Icon(wxT("Toolbar_Stats"),      amuleDlgImages(25), useSkins);
1323	Add_Skin_Icon(wxT("Toolbar_Prefs"),      amuleDlgImages(26), useSkins);
1324	Add_Skin_Icon(wxT("Toolbar_Import"),     amuleDlgImages(32), useSkins);
1325	Add_Skin_Icon(wxT("Toolbar_About"),      amuleDlgImages(29), useSkins);
1326	Add_Skin_Icon(wxT("Toolbar_Blink"),	 amuleDlgImages(33), useSkins);
1327
1328	// Build aMule toolbar
1329	wndToolbar->SetMargins(0, 0);
1330
1331	// Placeholder. Gets updated by ShowConnectionState
1332	wndToolbar->AddTool(ID_BUTTONCONNECT, wxT("..."), m_tblist.GetBitmap(0));
1333
1334	wndToolbar->AddSeparator();
1335	wndToolbar->AddTool(ID_BUTTONNETWORKS, _("Networks"), m_tblist.GetBitmap(3), wxNullBitmap, wxITEM_CHECK, _("Networks Window"));
1336	wndToolbar->AddTool(ID_BUTTONSEARCH, _("Searches"), m_tblist.GetBitmap(5), wxNullBitmap, wxITEM_CHECK, _("Searches Window"));
1337	wndToolbar->AddTool(ID_BUTTONDOWNLOADS, _("Downloads"), m_tblist.GetBitmap(4), wxNullBitmap, wxITEM_CHECK, _("Downloads Window"));
1338	wndToolbar->AddTool(ID_BUTTONSHARED, _("Shared files"), m_tblist.GetBitmap(6), wxNullBitmap, wxITEM_CHECK, _("Shared Files Window"));
1339	wndToolbar->AddTool(ID_BUTTONMESSAGES, _("Messages"), m_tblist.GetBitmap(7), wxNullBitmap, wxITEM_CHECK, _("Messages Window"));
1340	wndToolbar->AddTool(ID_BUTTONSTATISTICS, _("Statistics"), m_tblist.GetBitmap(8), wxNullBitmap, wxITEM_CHECK, _("Statistics Graph Window"));
1341	wndToolbar->AddSeparator();
1342	wndToolbar->AddTool(ID_BUTTONNEWPREFERENCES, _("Preferences"), m_tblist.GetBitmap(9), wxNullBitmap, wxITEM_NORMAL, _("Preferences Settings Window"));
1343#ifndef CLIENT_GUI
1344	wndToolbar->AddTool(ID_BUTTONIMPORT, _("Import"), m_tblist.GetBitmap(10), wxNullBitmap, wxITEM_NORMAL, _("The partfile importer tool"));
1345#endif
1346	wndToolbar->AddTool(ID_ABOUT, _("About"), m_tblist.GetBitmap(11), wxNullBitmap, wxITEM_NORMAL, _("About/Help"));
1347
1348	wndToolbar->ToggleTool(ID_BUTTONDOWNLOADS, true);
1349
1350	// Needed for non-GTK platforms, where the
1351	// items don't get added immediatly.
1352	wndToolbar->Realize();
1353
1354	// Updates the "Connect" button, and so on.
1355	ShowConnectionState(true);
1356}
1357
1358
1359void CamuleDlg::Create_Toolbar(bool orientation)
1360{
1361	Freeze();
1362	// Create ToolBar from the one designed by wxDesigner (BigBob)
1363	wxToolBar *current = GetToolBar();
1364
1365	wxASSERT(current == m_wndToolbar);
1366
1367	if (current) {
1368		bool oldorientation = ((current->GetWindowStyle() & wxTB_VERTICAL) == wxTB_VERTICAL);
1369		if (oldorientation != orientation) {
1370			current->Destroy();
1371			SetToolBar(NULL); // Remove old one if present
1372			m_wndToolbar = NULL;
1373		} else {
1374			current->ClearTools();
1375		}
1376	}
1377
1378	if (!m_wndToolbar) {
1379		m_wndToolbar = CreateToolBar(
1380			(orientation ? wxTB_VERTICAL : wxTB_HORIZONTAL) |
1381			wxNO_BORDER | wxTB_TEXT | wxTB_3DBUTTONS |
1382			wxTB_FLAT | wxCLIP_CHILDREN | wxTB_NODIVIDER);
1383
1384
1385			m_wndToolbar->SetToolBitmapSize(wxSize(32, 32));
1386	}
1387
1388	Apply_Toolbar_Skin(m_wndToolbar);
1389
1390	Thaw();
1391}
1392
1393
1394void CamuleDlg::OnMainGUISizeChange(wxSizeEvent& evt)
1395{
1396	wxFrame::OnSize(evt);
1397	if (m_transferwnd && m_transferwnd->clientlistctrl) {
1398		// Transfer window's splitter set again if it's hidden.
1399		if (!m_transferwnd->clientlistctrl->GetShowing()) {
1400			int height = m_transferwnd->clientlistctrl->GetSize().GetHeight();
1401			wxSplitterWindow* splitter =
1402				CastChild(wxT("splitterWnd"), wxSplitterWindow);
1403			height += splitter->GetWindow1()->GetSize().GetHeight();
1404			splitter->SetSashPosition( height );
1405		}
1406	}
1407}
1408
1409
1410void CamuleDlg::OnKeyPressed(wxKeyEvent& event)
1411{
1412	if (event.GetKeyCode() == WXK_F1) {
1413		// Ctrl/Alt/Shift must not be pressed, to avoid
1414		// conflicts with other (global) shortcuts.
1415		if (!event.HasModifiers() && !event.ShiftDown()) {
1416			LaunchUrl(wxT("http://wiki.amule.org"));
1417			return;
1418		}
1419	}
1420
1421	event.Skip();
1422}
1423
1424
1425void CamuleDlg::OnExit(wxCommandEvent& WXUNUSED(evt))
1426{
1427	Close(true);
1428}
1429
1430void CamuleDlg::DoNetworkRearrange()
1431{
1432	wxWindowUpdateLocker freezer(this);
1433
1434	wxToolBarToolBase* toolbarTool = m_wndToolbar->RemoveTool(ID_BUTTONNETWORKS);
1435
1436	wxNotebook* logs_notebook = CastChild( ID_SRVLOG_NOTEBOOK, wxNotebook);
1437	wxNotebook* networks_notebook = CastChild( ID_NETNOTEBOOK, wxNotebook);
1438
1439	while (logs_notebook->GetPageCount() > 1) {
1440		logs_notebook->RemovePage(logs_notebook->GetPageCount() - 1);
1441	}
1442
1443	while (networks_notebook->GetPageCount() > 0) {
1444		networks_notebook->RemovePage(networks_notebook->GetPageCount() - 1);
1445	}
1446
1447	if (thePrefs::GetNetworkED2K()) {
1448#ifndef CLIENT_GUI
1449		logs_notebook->AddPage(m_logpages[1].page, m_logpages[1].name);
1450#endif
1451		logs_notebook->AddPage(m_logpages[2].page, m_logpages[2].name);
1452	}
1453
1454	m_networkpages[0].page->Show(thePrefs::GetNetworkED2K());
1455
1456	if (thePrefs::GetNetworkKademlia()) {
1457		logs_notebook->AddPage(m_logpages[3].page, m_logpages[3].name);
1458	}
1459
1460	m_networkpages[1].page->Show(thePrefs::GetNetworkKademlia());
1461
1462	networks_notebook->Show(thePrefs::GetNetworkED2K() && thePrefs::GetNetworkKademlia());
1463
1464	wxWindow* replacement = NULL;
1465
1466	m_networknotebooksizer->Clear();
1467
1468	if (thePrefs::GetNetworkED2K() && thePrefs::GetNetworkKademlia()) {
1469		toolbarTool->SetLabel(_("Networks"));
1470
1471		m_networkpages[0].page->Reparent(networks_notebook);
1472		m_networkpages[1].page->Reparent(networks_notebook);
1473
1474		networks_notebook->AddPage(m_networkpages[0].page, m_networkpages[0].name);
1475		networks_notebook->AddPage(m_networkpages[1].page, m_networkpages[1].name);
1476
1477		replacement = networks_notebook;
1478
1479	} else if (thePrefs::GetNetworkED2K()) {
1480		toolbarTool->SetLabel(_("eD2k network"));
1481		replacement = m_networkpages[0].page;
1482		m_networkpages[1].page->Reparent(m_networknotebooksizer->GetContainingWindow());
1483	} else if (thePrefs::GetNetworkKademlia()) {
1484		toolbarTool->SetLabel(_("Kad network"));
1485		m_networkpages[0].page->Reparent(m_networknotebooksizer->GetContainingWindow());
1486		replacement = m_networkpages[1].page;
1487	} else {
1488		// No networks.
1489		toolbarTool->SetLabel(_("No network"));
1490	}
1491
1492	if (replacement) {
1493		replacement->Reparent(m_networknotebooksizer->GetContainingWindow());
1494		m_networknotebooksizer->Add( replacement, 1, wxGROW|wxALIGN_CENTER_VERTICAL|wxTOP, 5 );
1495		m_networknotebooksizer->Layout();
1496	}
1497
1498	m_wndToolbar->InsertTool(2, toolbarTool);
1499
1500	m_wndToolbar->EnableTool(ID_BUTTONNETWORKS, (thePrefs::GetNetworkED2K() || thePrefs::GetNetworkKademlia()));
1501	m_wndToolbar->EnableTool(ID_BUTTONCONNECT, (thePrefs::GetNetworkED2K() || thePrefs::GetNetworkKademlia()) && theApp->ipfilter->IsReady());
1502
1503	m_wndToolbar->Realize();
1504
1505	m_searchwnd->FixSearchTypes();
1506}
1507
1508// File_checked_for_headers
1509