Upstream tarball 20080603
[amule.git] / src / MuleTrayIcon.cpp
blob3ebdadb74e294e2eb88c7b1c4f85ae71831ca26a
1 //
2 // This file is part of the aMule Project.
3 //
4 // Copyright (c) 2003-2008 Angel Vidal (Kry) ( kry@amule.org )
5 // Copyright (c) 2003-2008 Patrizio Bassi (Hetfield) ( hetfield@amule.org )
6 // Copyright (c) 2003-2008 aMule Team ( admin@amule.org / http://www.amule.org )
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.
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.
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
27 #include <wx/app.h>
29 #include "MuleTrayIcon.h"
31 #include <common/ClientVersion.h>
32 #include <common/Constants.h>
34 #include "pixmaps/mule_TrayIcon_big.ico.xpm"
35 #include "pixmaps/mule_Tr_yellow_big.ico.xpm"
36 #include "pixmaps/mule_Tr_grey_big.ico.xpm"
38 #include <wx/menu.h>
40 #include "amule.h" // Needed for theApp
41 #include "amuleDlg.h" // Needed for IsShown
42 #include "Preferences.h" // Needed for thePrefs
43 #include "ServerConnect.h" // Needed for CServerConnect
44 #include "Server.h" // Needed for CServer
45 #include "StatisticsDlg.h" // Needed for CStatisticsDlg::getColors()
46 #include "Statistics.h" // Needed for theStats
47 #include <common/Format.h> // Needed for CFormat
50 // Pop-up menu clickable entries
51 enum {
52 TRAY_MENU_INFO = 0,
53 TRAY_MENU_CLIENTINFO=0,
54 TRAY_MENU_CLIENTINFO_ITEM = 13007,
55 TRAY_MENU_DISCONNECT,
56 TRAY_MENU_CONNECT,
57 TRAY_MENU_HIDE,
58 TRAY_MENU_SHOW,
59 TRAY_MENU_EXIT,
60 UPLOAD_ITEM1=12340,
61 UPLOAD_ITEM2=12341,
62 UPLOAD_ITEM3=12342,
63 UPLOAD_ITEM4=12343,
64 UPLOAD_ITEM5=12344,
65 UPLOAD_ITEM6=12345,
66 DOWNLOAD_ITEM1=54320,
67 DOWNLOAD_ITEM2=54321,
68 DOWNLOAD_ITEM3=54322,
69 DOWNLOAD_ITEM4=54323,
70 DOWNLOAD_ITEM5=54324,
71 DOWNLOAD_ITEM6=54325
74 /****************************************************/
75 /******************* Event Table ********************/
76 /****************************************************/
78 BEGIN_EVENT_TABLE(CMuleTrayIcon, wxTaskBarIcon)
79 EVT_TASKBAR_LEFT_DCLICK(CMuleTrayIcon::SwitchShow)
80 EVT_MENU( TRAY_MENU_EXIT, CMuleTrayIcon::Close)
81 EVT_MENU( TRAY_MENU_CONNECT, CMuleTrayIcon::ServerConnection)
82 EVT_MENU( TRAY_MENU_DISCONNECT, CMuleTrayIcon::ServerConnection)
83 EVT_MENU( TRAY_MENU_HIDE, CMuleTrayIcon::ShowHide)
84 EVT_MENU( TRAY_MENU_SHOW, CMuleTrayIcon::ShowHide)
85 EVT_MENU( UPLOAD_ITEM1, CMuleTrayIcon::SetUploadSpeed)
86 EVT_MENU( UPLOAD_ITEM2, CMuleTrayIcon::SetUploadSpeed)
87 EVT_MENU( UPLOAD_ITEM3, CMuleTrayIcon::SetUploadSpeed)
88 EVT_MENU( UPLOAD_ITEM4, CMuleTrayIcon::SetUploadSpeed)
89 EVT_MENU( UPLOAD_ITEM5, CMuleTrayIcon::SetUploadSpeed)
90 EVT_MENU( UPLOAD_ITEM6, CMuleTrayIcon::SetUploadSpeed)
91 EVT_MENU( DOWNLOAD_ITEM1, CMuleTrayIcon::SetDownloadSpeed)
92 EVT_MENU( DOWNLOAD_ITEM2, CMuleTrayIcon::SetDownloadSpeed)
93 EVT_MENU( DOWNLOAD_ITEM3, CMuleTrayIcon::SetDownloadSpeed)
94 EVT_MENU( DOWNLOAD_ITEM4, CMuleTrayIcon::SetDownloadSpeed)
95 EVT_MENU( DOWNLOAD_ITEM5, CMuleTrayIcon::SetDownloadSpeed)
96 EVT_MENU( DOWNLOAD_ITEM6, CMuleTrayIcon::SetDownloadSpeed)
97 END_EVENT_TABLE()
99 /****************************************************/
100 /************ Constructor / Destructor **************/
101 /****************************************************/
103 long GetSpeedFromString(wxString label){
104 long temp;
105 label.Replace(wxT("kB/s"),wxT(""),TRUE);
106 label.Trim(FALSE);
107 label.Trim(TRUE);
108 label.ToLong(&temp);
109 return temp;
112 void CMuleTrayIcon::SetUploadSpeed(wxCommandEvent& event){
114 wxObject* obj=event.GetEventObject();
115 if (obj!=NULL) {
116 wxMenu *menu = dynamic_cast<wxMenu *>(obj);
117 if (menu) {
118 wxMenuItem* item=menu->FindItem(event.GetId());
119 if (item!=NULL) {
120 long temp;
121 if (item->GetLabel()==(_("Unlimited"))) {
122 temp=UNLIMITED;
124 else {
125 temp=GetSpeedFromString(item->GetLabel());
127 thePrefs::SetMaxUpload(temp);
133 void CMuleTrayIcon::SetDownloadSpeed(wxCommandEvent& event){
135 wxObject* obj=event.GetEventObject();
136 if (obj!=NULL) {
137 wxMenu *menu = dynamic_cast<wxMenu *>(obj);
138 if (menu) {
139 wxMenuItem* item=menu->FindItem(event.GetId());
140 if (item!=NULL) {
141 long temp;
142 if (item->GetLabel()==(_("Unlimited"))) {
143 temp=UNLIMITED;
145 else {
146 temp=GetSpeedFromString(item->GetLabel());
148 thePrefs::SetMaxDownload(temp);
155 void CMuleTrayIcon::ServerConnection(wxCommandEvent& WXUNUSED(event))
157 wxCommandEvent evt;
158 theApp->amuledlg->OnBnConnect(evt);
162 void CMuleTrayIcon::ShowHide(wxCommandEvent& WXUNUSED(event))
164 theApp->amuledlg->DoIconize(theApp->amuledlg->IsShown());
168 void CMuleTrayIcon::Close(wxCommandEvent& WXUNUSED(event))
170 if (theApp->amuledlg->IsEnabled()) {
171 theApp->amuledlg->Close();
176 CMuleTrayIcon::CMuleTrayIcon()
178 Old_Icon = -1;
179 Old_SpeedSize = 0xFFFF; // must be > any possible one.
180 // Create the background icons (speed improvement)
181 HighId_Icon_size = wxIcon(mule_TrayIcon_big_ico_xpm).GetHeight();
182 LowId_Icon_size = wxIcon(mule_Tr_yellow_big_ico_xpm).GetHeight();
183 Disconnected_Icon_size = wxIcon(mule_Tr_grey_big_ico_xpm).GetHeight();
186 CMuleTrayIcon::~CMuleTrayIcon()
188 #ifdef __WXGTK__
189 // FIXME: EVIL HACK: We need to ensure that the superclass doesn't
190 // try to destroy a dangling pointer. See also CMuleTrayIcon::UpdateTray
191 // for comments on this issue.
192 if (m_iconWnd) {
193 if (wxTopLevelWindows.IndexOf((wxWindow*)m_iconWnd) == wxNOT_FOUND) {
194 m_iconWnd = NULL;
197 #endif
200 /****************************************************/
201 /***************** Public Functions *****************/
202 /****************************************************/
204 void CMuleTrayIcon::SetTrayIcon(int Icon, uint32 percent)
206 int Bar_ySize = 0;
208 switch (Icon) {
209 case TRAY_ICON_HIGHID:
210 // Most likely case, test first
211 Bar_ySize = HighId_Icon_size;
212 break;
213 case TRAY_ICON_LOWID:
214 Bar_ySize = LowId_Icon_size;
215 break;
216 case TRAY_ICON_DISCONNECTED:
217 Bar_ySize = Disconnected_Icon_size;
218 break;
219 default:
220 wxASSERT(0);
223 // Lookup this values for speed improvement: don't draw if not needed
224 int NewSize = (Bar_ySize * percent) / 100;
226 if ((Old_Icon != Icon) || (Old_SpeedSize != NewSize)) {
228 if ((Old_SpeedSize > NewSize) || (Old_Icon != Icon)) {
229 // We have to rebuild the icon, because bar is lower now.
230 switch (Icon) {
231 case TRAY_ICON_HIGHID:
232 // Most likely case, test first
233 CurrentIcon = wxIcon(mule_TrayIcon_big_ico_xpm);
234 break;
235 case TRAY_ICON_LOWID:
236 CurrentIcon = wxIcon(mule_Tr_yellow_big_ico_xpm);
237 break;
238 case TRAY_ICON_DISCONNECTED:
239 CurrentIcon = wxIcon(mule_Tr_grey_big_ico_xpm);
240 break;
241 default:
242 wxASSERT(0);
246 Old_Icon = Icon;
247 Old_SpeedSize = NewSize;
249 // Do whatever to the icon before drawing it (percent)
251 wxBitmap TempBMP;
252 TempBMP.CopyFromIcon(CurrentIcon);
254 TempBMP.SetMask(NULL);
256 IconWithSpeed.SelectObject(TempBMP);
259 // Speed bar is: centered, taking 80% of the icon heigh, and
260 // right-justified taking a 10% of the icon width.
262 // X
263 int Bar_xSize = 4;
264 int Bar_xPos = CurrentIcon.GetWidth() - 5;
266 wxColour col= WxColourFromCr( CStatisticsDlg::getColors(11) );
267 wxBrush brush(col);
268 IconWithSpeed.SetBrush(brush);
269 IconWithSpeed.SetPen(*wxTRANSPARENT_PEN);
271 IconWithSpeed.DrawRectangle(Bar_xPos + 1, Bar_ySize - NewSize, Bar_xSize -2 , NewSize);
273 // Unselect the icon.
274 IconWithSpeed.SelectObject(wxNullBitmap);
276 // Do transparency
278 // Set a new mask with transparency set to red.
279 wxMask* new_mask = new wxMask(TempBMP, wxColour(0xFF, 0x00, 0x00));
281 TempBMP.SetMask(new_mask);
282 CurrentIcon.CopyFromBitmap(TempBMP);
284 UpdateTray();
288 void CMuleTrayIcon::SetTrayToolTip(const wxString& Tip)
290 CurrentTip = Tip;
291 UpdateTray();
294 /****************************************************/
295 /**************** Private Functions *****************/
296 /****************************************************/
298 void CMuleTrayIcon::UpdateTray()
300 #ifdef __WXGTK__
301 // FIXME: EVIL HACK: As of wxGTK-2.8.7, closing of the trayicon
302 // window (caused for instance by a crashing kicker) is not
303 // handled, with the result that the pointer to the trayicon
304 // window becomes a dangling pointer. Since we have access to
305 // the pointer, and it's created as a top-level window, it's
306 // relatively easy to force the recreation of a valid window.
307 // Ugly as hell though ....
309 // This has been repported as bug #1872724:
310 // http://sourceforge.net/tracker/index.php?func=detail&aid=1872724&group_id=9863&atid=109863
311 if (m_iconWnd) {
312 if (wxTopLevelWindows.IndexOf((wxWindow*)m_iconWnd) == wxNOT_FOUND) {
313 printf("Traybar-icon lost, trying to recreate ...\n");
314 m_iconWnd = NULL;
317 #endif
319 // Icon update and Tip update
320 if (IsOk()) {
321 SetIcon(CurrentIcon, CurrentTip);
326 wxMenu* CMuleTrayIcon::CreatePopupMenu()
328 // Creates dinamically the menu to show the user.
329 wxMenu *traymenu = new wxMenu();
330 traymenu->SetTitle(_("aMule Tray Menu"));
332 // Build the Top string name
333 wxString label = MOD_VERSION_LONG;
334 traymenu->Append(TRAY_MENU_INFO, label);
335 traymenu->AppendSeparator();
336 label = wxString(_("Speed Limits:")) + wxT(" ");
338 // Check for upload limits
339 unsigned int max_upload = thePrefs::GetMaxUpload();
340 if ( max_upload == UNLIMITED ) {
341 label += _("UL: None");
343 else {
344 label += wxString::Format(_("UL: %u"), max_upload);
346 label += wxT(", ");
348 // Check for download limits
349 unsigned int max_download = thePrefs::GetMaxDownload();
350 if ( max_download == UNLIMITED ) {
351 label += _("DL: None");
353 else {
354 label += wxString::Format(_("DL: %u"), max_download);
357 traymenu->Append(TRAY_MENU_INFO, label);
358 label = wxString::Format(_("Download Speed: %.1f"), theStats::GetDownloadRate() / 1024.0);
359 traymenu->Append(TRAY_MENU_INFO, label);
360 label = wxString::Format(_("Upload Speed: %.1f"), theStats::GetUploadRate() / 1024.0);
361 traymenu->Append(TRAY_MENU_INFO, label);
362 traymenu->AppendSeparator();
364 // Client Info
365 wxMenu* ClientInfoMenu = new wxMenu();
366 ClientInfoMenu->SetTitle(_("Client Information"));
368 // User nick-name
370 wxString temp = CFormat(_("Nickname: %s")) % ( thePrefs::GetUserNick().IsEmpty() ? wxString(_("No Nickname Selected!")) : thePrefs::GetUserNick() );
372 ClientInfoMenu->Append(TRAY_MENU_CLIENTINFO_ITEM,temp);
375 // Client ID
377 wxString temp = _("ClientID: ");
379 if (theApp->IsConnectedED2K()) {
380 unsigned long id = theApp->GetED2KID();
381 temp += wxString::Format(wxT("%lu"), id);
382 } else {
383 temp += _("Not Connected");
385 ClientInfoMenu->Append(TRAY_MENU_CLIENTINFO_ITEM,temp);
388 // Current Server and Server IP
390 wxString temp_name = _("ServerName: ");
391 wxString temp_ip = _("ServerIP: ");
393 if ( theApp->serverconnect->GetCurrentServer() ) {
394 temp_name += theApp->serverconnect->GetCurrentServer()->GetListName();
395 temp_ip += theApp->serverconnect->GetCurrentServer()->GetFullIP();
396 } else {
397 temp_name += _("Not Connected");
398 temp_ip += _("Not Connected");
400 ClientInfoMenu->Append(TRAY_MENU_CLIENTINFO_ITEM,temp_name);
401 ClientInfoMenu->Append(TRAY_MENU_CLIENTINFO_ITEM,temp_ip);
404 // IP Address
406 wxString temp = CFormat(_("IP: %s")) % ( (theApp->GetPublicIP()) ? Uint32toStringIP(theApp->GetPublicIP()) : wxString(_("Unknown")) );
408 ClientInfoMenu->Append(TRAY_MENU_CLIENTINFO_ITEM,temp);
411 // TCP PORT
413 wxString temp;
414 if (thePrefs::GetPort()) {
415 temp = CFormat(_("TCP Port: %d")) % thePrefs::GetPort();
416 } else {
417 temp=_("TCP Port: Not Ready");
419 ClientInfoMenu->Append(TRAY_MENU_CLIENTINFO_ITEM,temp);
422 // UDP PORT
424 wxString temp;
425 if (thePrefs::GetEffectiveUDPPort()) {
426 temp = CFormat(_("UDP Port: %d")) % thePrefs::GetEffectiveUDPPort();
427 } else {
428 temp=_("UDP Port: Not Ready");
430 ClientInfoMenu->Append(TRAY_MENU_CLIENTINFO_ITEM,temp);
433 // Online Signature
435 wxString temp;
436 if (thePrefs::IsOnlineSignatureEnabled()) {
437 temp=_("Online Signature: Enabled");
439 else {
440 temp=_("Online Signature: Disabled");
442 ClientInfoMenu->Append(TRAY_MENU_CLIENTINFO_ITEM,temp);
445 // Uptime
447 wxString temp = CFormat(_("Uptime: %s")) % CastSecondsToHM(theStats::GetUptimeSeconds());
448 ClientInfoMenu->Append(TRAY_MENU_CLIENTINFO_ITEM,temp);
451 // Number of shared files
453 wxString temp = CFormat(_("Shared Files: %d")) % theStats::GetSharedFileCount();
454 ClientInfoMenu->Append(TRAY_MENU_CLIENTINFO_ITEM,temp);
457 // Number of queued clients
459 wxString temp = CFormat(_("Queued Clients: %d")) % theStats::GetWaitingUserCount();
460 ClientInfoMenu->Append(TRAY_MENU_CLIENTINFO_ITEM,temp);
463 // Total Downloaded
465 wxString temp = CastItoXBytes( theStats::GetSessionReceivedBytes() + thePrefs::GetTotalDownloaded() );
466 temp = CFormat(_("Total DL: %s")) % temp;
467 ClientInfoMenu->Append(TRAY_MENU_CLIENTINFO_ITEM,temp);
470 // Total Uploaded
472 wxString temp = CastItoXBytes( theStats::GetSessionSentBytes() + thePrefs::GetTotalUploaded() );
473 temp = CFormat(_("Total UL: %s")) % temp;
474 ClientInfoMenu->Append(TRAY_MENU_CLIENTINFO_ITEM,temp);
477 traymenu->Append(TRAY_MENU_CLIENTINFO,ClientInfoMenu->GetTitle(),ClientInfoMenu);
479 // Separator
480 traymenu->AppendSeparator();
482 // Upload Speed sub-menu
483 wxMenu* UploadSpeedMenu = new wxMenu();
484 UploadSpeedMenu->SetTitle(_("Upload Limit"));
486 // Download Speed sub-menu
487 wxMenu* DownloadSpeedMenu = new wxMenu();
488 DownloadSpeedMenu->SetTitle(_("Download Limit"));
490 // Upload Speed sub-menu
492 UploadSpeedMenu->Append(UPLOAD_ITEM1, _("Unlimited"));
494 uint32 max_ul_speed = thePrefs::GetMaxGraphUploadRate();
496 if ( max_ul_speed == UNLIMITED ) {
497 max_ul_speed = 100;
499 else if ( max_ul_speed < 10 ) {
500 max_ul_speed = 10;
503 for ( int i = 0; i < 5; i++ ) {
504 unsigned int tempspeed = (unsigned int)((double)max_ul_speed / 5) * (5 - i);
505 wxString temp = wxString::Format(wxT("%u kB/s"), tempspeed);
506 UploadSpeedMenu->Append((int)UPLOAD_ITEM1+i+1,temp);
509 traymenu->Append(0,UploadSpeedMenu->GetTitle(),UploadSpeedMenu);
511 // Download Speed sub-menu
513 DownloadSpeedMenu->Append(DOWNLOAD_ITEM1, _("Unlimited"));
515 uint32 max_dl_speed = thePrefs::GetMaxGraphDownloadRate();
517 if ( max_dl_speed == UNLIMITED ) {
518 max_dl_speed = 100;
520 else if ( max_dl_speed < 10 ) {
521 max_dl_speed = 10;
524 for ( int i = 0; i < 5; i++ ) {
525 unsigned int tempspeed = (unsigned int)((double)max_dl_speed / 5) * (5 - i);
526 wxString temp = wxString::Format(wxT("%d kB/s"), tempspeed);
527 DownloadSpeedMenu->Append((int)DOWNLOAD_ITEM1+i+1,temp);
531 traymenu->Append(0,DownloadSpeedMenu->GetTitle(),DownloadSpeedMenu);
532 // Separator
533 traymenu->AppendSeparator();
535 if (theApp->IsConnected()) {
536 //Disconnection Speed item
537 traymenu->Append(TRAY_MENU_DISCONNECT, _("Disconnect"));
538 } else {
539 //Connect item
540 traymenu->Append(TRAY_MENU_CONNECT, _("Connect"));
543 // Separator
544 traymenu->AppendSeparator();
546 if (theApp->amuledlg->IsShown()) {
547 //hide item
548 traymenu->Append(TRAY_MENU_HIDE, _("Hide aMule"));
549 } else {
550 //show item
551 traymenu->Append(TRAY_MENU_SHOW, _("Show aMule"));
554 // Separator
555 traymenu->AppendSeparator();
557 // Exit item
558 traymenu->Append(TRAY_MENU_EXIT, _("Exit"));
560 return traymenu;
563 void CMuleTrayIcon::SwitchShow(wxTaskBarIconEvent&)
565 if ( !theApp->amuledlg->IsIconized() ) {
566 theApp->amuledlg->Iconize(true);
567 if (thePrefs::DoMinToTray()) {
568 theApp->amuledlg->Show(false);
570 } else {
571 theApp->amuledlg->Iconize(false);
572 theApp->amuledlg->Show(true);
573 theApp->amuledlg->Raise();
576 // File_checked_for_headers