1 // This file is part of BOINC.
2 // http://boinc.berkeley.edu
3 // Copyright (C) 2008 University of California
4 //
5 // BOINC is free software; you can redistribute it and/or modify it
6 // under the terms of the GNU Lesser General Public License
7 // as published by the Free Software Foundation,
8 // either version 3 of the License, or (at your option) any later version.
9 //
10 // BOINC is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 // See the GNU Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public License
16 // along with BOINC.  If not, see <http://www.gnu.org/licenses/>.
17 
18 #if defined(__GNUG__) && !defined(__APPLE__)
19 #pragma implementation "BOINCBaseFrame.h"
20 #endif
21 
22 #include "stdwx.h"
23 #include "diagnostics.h"
24 #include "util.h"
25 #include "mfile.h"
26 #include "miofile.h"
27 #include "parse.h"
28 #include "error_numbers.h"
29 #include "BOINCGUIApp.h"
30 #include "SkinManager.h"
31 #include "MainDocument.h"
32 #include "BOINCClientManager.h"
33 #include "BOINCTaskBar.h"
34 #include "BOINCBaseFrame.h"
35 #include "BOINCDialupManager.h"
36 #include "Events.h"
37 #include "DlgEventLog.h"
38 #include "DlgSelectComputer.h"
39 
40 
41 DEFINE_EVENT_TYPE(wxEVT_FRAME_ALERT)
DEFINE_EVENT_TYPE(wxEVT_FRAME_CONNECT)42 DEFINE_EVENT_TYPE(wxEVT_FRAME_CONNECT)
43 DEFINE_EVENT_TYPE(wxEVT_FRAME_INITIALIZED)
44 DEFINE_EVENT_TYPE(wxEVT_FRAME_REFRESHVIEW)
45 DEFINE_EVENT_TYPE(wxEVT_FRAME_UPDATESTATUS)
46 DEFINE_EVENT_TYPE(wxEVT_FRAME_RELOADSKIN)
47 DEFINE_EVENT_TYPE(wxEVT_FRAME_NOTIFICATION)
48 
49 
50 IMPLEMENT_DYNAMIC_CLASS(CBOINCBaseFrame, wxFrame)
51 
52 BEGIN_EVENT_TABLE (CBOINCBaseFrame, wxFrame)
53     EVT_TIMER(ID_DOCUMENTPOLLTIMER, CBOINCBaseFrame::OnDocumentPoll)
54     EVT_TIMER(ID_ALERTPOLLTIMER, CBOINCBaseFrame::OnAlertPoll)
55     EVT_TIMER(ID_PERIODICRPCTIMER, CBOINCBaseFrame::OnPeriodicRPC)
56     EVT_FRAME_INITIALIZED(CBOINCBaseFrame::OnInitialized)
57     EVT_FRAME_ALERT(CBOINCBaseFrame::OnAlert)
58     EVT_FRAME_REFRESH(CBOINCBaseFrame::OnRefreshView)
59     EVT_ACTIVATE(CBOINCBaseFrame::OnActivate)
60     EVT_CLOSE(CBOINCBaseFrame::OnClose)
61     EVT_MENU(ID_CLOSEWINDOW, CBOINCBaseFrame::OnCloseWindow)
62     EVT_MENU(wxID_EXIT, CBOINCBaseFrame::OnExit)
63 END_EVENT_TABLE ()
64 
65 
66 CBOINCBaseFrame::CBOINCBaseFrame()
67 {
68     wxLogTrace(wxT("Function Start/End"), wxT("CBOINCBaseFrame::CBOINCBaseFrame - Default Constructor Function Begin"));
69     wxLogTrace(wxT("Function Start/End"), wxT("CBOINCBaseFrame::CBOINCBaseFrame - Default Constructor Function End"));
70 }
71 
72 
CBOINCBaseFrame(wxWindow * parent,const wxWindowID id,const wxString & title,const wxPoint & pos,const wxSize & size,const long style)73 CBOINCBaseFrame::CBOINCBaseFrame(wxWindow* parent, const wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, const long style) :
74     wxFrame(parent, id, title, pos, size, style)
75 {
76     wxLogTrace(wxT("Function Start/End"), wxT("CBOINCBaseFrame::CBOINCBaseFrame - Function Begin"));
77 
78     // Configuration Settings
79     m_iReminderFrequency = 0;
80     m_strNetworkDialupConnectionName = wxEmptyString;
81     m_aSelectedComputerMRU.Clear();
82     m_bShowConnectionFailedAlert = false;
83 
84 
85     m_pDialupManager = new CBOINCDialUpManager();
86     wxASSERT(m_pDialupManager->IsOk());
87 
88 
89     m_pDocumentPollTimer = new wxTimer(this, ID_DOCUMENTPOLLTIMER);
90     wxASSERT(m_pDocumentPollTimer);
91 
92     m_pDocumentPollTimer->Start(250);               // Send event every 250 milliseconds
93 
94     m_pAlertPollTimer = new wxTimer(this, ID_ALERTPOLLTIMER);
95     wxASSERT(m_pAlertPollTimer);
96 
97     m_pAlertPollTimer->Start(1000);                 // Send event every 1000 milliseconds
98 
99     m_pPeriodicRPCTimer = new wxTimer(this, ID_PERIODICRPCTIMER);
100     wxASSERT(m_pPeriodicRPCTimer);
101 
102     m_pPeriodicRPCTimer->Start(1000);               // Send event every 1000 milliseconds
103     m_iFrameRefreshRate = 1000;                     // Refresh frame every 1000 milliseconds
104 
105     // Limit the number of times the UI can update itself to two times a second
106     //   NOTE: Linux and Mac were updating several times a second and eating
107     //         CPU time
108     wxUpdateUIEvent::SetUpdateInterval(500);
109 
110     m_ptFramePos = wxPoint(0, 0);
111 
112     // The second half of the initialization process picks up in the OnFrameRender()
113     //   routine since the menus' and status bars' are drawn in the frameworks
114     //   on idle routines, on idle events are sent in between the end of the
115     //   constructor and the first call to OnFrameRender
116     //
117     // Look for the 'if (!bAlreadyRunOnce) {' statement
118 
119     wxLogTrace(wxT("Function Start/End"), wxT("CBOINCBaseFrame::CBOINCBaseFrame - Function End"));
120 }
121 
122 
~CBOINCBaseFrame()123 CBOINCBaseFrame::~CBOINCBaseFrame() {
124     wxLogTrace(wxT("Function Start/End"), wxT("CBOINCBaseFrame::~CBOINCBaseFrame - Function Begin"));
125 
126     wxASSERT(m_pPeriodicRPCTimer);
127     wxASSERT(m_pAlertPollTimer);
128     wxASSERT(m_pDocumentPollTimer);
129 
130     if (m_pPeriodicRPCTimer) {
131         m_pPeriodicRPCTimer->Stop();
132         delete m_pPeriodicRPCTimer;
133     }
134 
135     if (m_pAlertPollTimer) {
136         m_pAlertPollTimer->Stop();
137         delete m_pAlertPollTimer;
138     }
139 
140     if (m_pDocumentPollTimer) {
141         m_pDocumentPollTimer->Stop();
142         delete m_pDocumentPollTimer;
143     }
144 
145     if (m_pDialupManager) {
146         delete m_pDialupManager;
147     }
148 
149     wxLogTrace(wxT("Function Start/End"), wxT("CBOINCBaseFrame::~CBOINCBaseFrame - Function End"));
150 }
151 
152 
OnPeriodicRPC(wxTimerEvent & WXUNUSED (event))153 void CBOINCBaseFrame::OnPeriodicRPC(wxTimerEvent& WXUNUSED(event)) {
154     static bool        bAlreadyRunningLoop = false;
155     CMainDocument*     pDoc = wxGetApp().GetDocument();
156 
157     wxASSERT(pDoc);
158     wxASSERT(wxDynamicCast(pDoc, CMainDocument));
159 
160 #ifdef __WXMAC__
161     static bool first = true;
162     if (first) {
163         first = false;
164         wxGetApp().OnFinishInit();
165     }
166 
167     wxGetApp().CheckPartialActivation();
168 #endif
169 
170     if (!bAlreadyRunningLoop && m_pPeriodicRPCTimer->IsRunning()) {
171         bAlreadyRunningLoop = true;
172 
173         pDoc->RunPeriodicRPCs(m_iFrameRefreshRate);
174 
175         bAlreadyRunningLoop = false;
176     }
177 }
178 
179 
OnDocumentPoll(wxTimerEvent & WXUNUSED (event))180 void CBOINCBaseFrame::OnDocumentPoll(wxTimerEvent& WXUNUSED(event)) {
181     static bool        bAlreadyRunOnce = false;
182     CMainDocument*     pDoc = wxGetApp().GetDocument();
183 
184     wxASSERT(pDoc);
185     wxASSERT(wxDynamicCast(pDoc, CMainDocument));
186 
187     // Timer events are handled while the RPC Wait dialog is shown
188     // which may cause unintended recursion and repeatedly posting
189     // the same RPC requests from timer routines.
190     if (pDoc->WaitingForRPC()) return;
191 
192     if (!bAlreadyRunOnce && m_pDocumentPollTimer->IsRunning()) {
193         // Complete any remaining initialization that has to happen after we are up
194         //   and running
195         FireInitialize();
196         bAlreadyRunOnce = true;
197     }
198 
199     pDoc->OnPoll();
200 }
201 
202 
OnAlertPoll(wxTimerEvent & WXUNUSED (event))203 void CBOINCBaseFrame::OnAlertPoll(wxTimerEvent& WXUNUSED(event)) {
204     static bool       bAlreadyRunningLoop = false;
205     CMainDocument*    pDoc = wxGetApp().GetDocument();
206 
207     if (!bAlreadyRunningLoop && m_pAlertPollTimer->IsRunning()) {
208         bAlreadyRunningLoop = true;
209 
210         // Update idle detection if needed.
211         wxGetApp().UpdateSystemIdleDetection();
212 
213         // Check to see if there is anything that we need to do from the
214         //   dial up user perspective.
215         if (pDoc && m_pDialupManager) {
216             // Timer events are handled while the RPC Wait dialog is shown
217             // which may cause unintended recursion and repeatedly posting
218             // the same RPC requests from timer routines.
219             if (pDoc->IsConnected() && !pDoc->WaitingForRPC()) {
220                 m_pDialupManager->OnPoll();
221             }
222         }
223 
224         if (m_bShowConnectionFailedAlert && IsShown()) {
225             m_bShowConnectionFailedAlert = false;
226             ShowConnectionFailedAlert();
227         }
228 
229         bAlreadyRunningLoop = false;
230     }
231 }
232 
233 
OnInitialized(CFrameEvent & WXUNUSED (event))234 void CBOINCBaseFrame::OnInitialized(CFrameEvent& WXUNUSED(event)) {
235     wxLogTrace(wxT("Function Start/End"), wxT("CBOINCBaseFrame::OnInitialized - Function Begin"));
236     wxLogTrace(wxT("Function Start/End"), wxT("CBOINCBaseFrame::OnInitialized - Function End"));
237 }
238 
239 
OnRefreshView(CFrameEvent &)240 void CBOINCBaseFrame::OnRefreshView(CFrameEvent& ) {
241 }
242 
243 
OnAlert(CFrameAlertEvent & event)244 void CBOINCBaseFrame::OnAlert(CFrameAlertEvent& event) {
245     wxLogTrace(wxT("Function Start/End"), wxT("CBOINCBaseFrame::OnAlert - Function Begin"));
246     static bool       bAlreadyRunningLoop = false;
247 
248     if (!bAlreadyRunningLoop) {
249         bAlreadyRunningLoop = true;
250 
251 #ifdef __WXMSW__
252         CTaskBarIcon* pTaskbar = wxGetApp().GetTaskBarIcon();
253         wxASSERT(pTaskbar);
254 
255         if ((IsShown() && !event.m_notification_only) || (IsShown() && !pTaskbar->IsBalloonsSupported())) {
256             if (!event.m_notification_only) {
257                 int retval = 0;
258 
259                 if (!IsShown()) {
260                     Show();
261                 }
262 
263                 retval = wxGetApp().SafeMessageBox(event.m_message, event.m_title, event.m_style, this);
264                 if (event.m_alert_event_type == AlertProcessResponse) {
265                     event.ProcessResponse(retval);
266                 }
267             }
268         } else {
269             // If the main window is hidden or minimzed use the system tray ballon
270             //   to notify the user instead.  This keeps dialogs from interfering
271             //   with people typing email messages or any other activity where they
272             //   do not want keyboard focus changed to another window while typing.
273             unsigned int  icon_type;
274 
275             if (wxICON_ERROR & event.m_style) {
276                 icon_type = NIIF_ERROR;
277             } else if (wxICON_WARNING & event.m_style) {
278                 icon_type = NIIF_WARNING;
279             } else if (wxICON_INFORMATION & event.m_style) {
280                 icon_type = NIIF_INFO;
281             } else {
282                 icon_type = NIIF_NONE;
283             }
284 
285             pTaskbar->SetBalloon(
286                 pTaskbar->m_iconTaskBarNormal,
287                 event.m_title,
288                 event.m_message,
289                 icon_type
290             );
291         }
292 #elif defined (__WXMAC__)
293         // SafeMessageBox() / ProcessResponse() hangs the Manager if hidden.
294         // Currently, the only non-notification-only alert is Connection Failed,
295         // which is now has logic to be displayed when Manager is maximized.
296 
297         // Notification only events on platforms other than Windows are
298         //   currently discarded.  Otherwise the application would be restored
299         //   and input focus set on the notification which interrupts whatever
300         //   the user was doing.
301         if (IsShown() && !event.m_notification_only) {
302             int retval = 0;
303 
304             retval = wxGetApp().SafeMessageBox(event.m_message, event.m_title, event.m_style, this);
305             if (event.m_alert_event_type == AlertProcessResponse) {
306                 event.ProcessResponse(retval);
307             }
308         }
309 #endif
310 
311         bAlreadyRunningLoop = false;
312     }
313 
314     wxLogTrace(wxT("Function Start/End"), wxT("CBOINCBaseFrame::OnAlert - Function End"));
315 }
316 
317 
OnActivate(wxActivateEvent & event)318 void CBOINCBaseFrame::OnActivate(wxActivateEvent& event) {
319     bool isActive = event.GetActive();
320     if (isActive) wxGetApp().SetEventLogWasActive(false);
321     event.Skip();
322 }
323 
324 
OnClose(wxCloseEvent & event)325 void CBOINCBaseFrame::OnClose(wxCloseEvent& event) {
326     wxLogTrace(wxT("Function Start/End"), wxT("CBOINCBaseFrame::OnClose - Function Begin"));
327 
328     if (!event.CanVeto() || IsIconized()) {
329         wxGetApp().FrameClosed();
330         Destroy();
331     } else {
332 #ifdef __WXGTK__
333         // Apparently aborting a close event just causes the main window to be displayed
334         // again.  Just minimize the window instead.
335         Iconize();
336 #else
337         Hide();
338 #endif
339     }
340 
341     wxLogTrace(wxT("Function Start/End"), wxT("CBOINCBaseFrame::OnClose - Function End"));
342 }
343 
344 
OnCloseWindow(wxCommandEvent & WXUNUSED (event))345 void CBOINCBaseFrame::OnCloseWindow(wxCommandEvent& WXUNUSED(event)) {
346     wxLogTrace(wxT("Function Start/End"), wxT("CBOINCBaseFrame::OnCloseWindow - Function Begin"));
347 
348 #ifdef __WXMAC__
349     CFStringRef frontWindowTitle, eventLogTitle;
350     CDlgEventLog* eventLog = wxGetApp().GetEventLog();
351     if (eventLog) {
352         WindowRef win = FrontNonFloatingWindow();
353         if (win) {
354             CopyWindowTitleAsCFString(win, &frontWindowTitle);
355             eventLogTitle = CFStringCreateWithCString(NULL, eventLog->GetTitle().char_str(), kCFStringEncodingUTF8);
356             CFComparisonResult res = CFStringCompare(eventLogTitle, frontWindowTitle, 0);
357             CFRelease(eventLogTitle);
358             CFRelease(frontWindowTitle);
359             if (res == kCFCompareEqualTo) {
360                 wxCloseEvent eventClose;
361                 eventLog->OnClose(eventClose);
362                 return;
363             }
364         }
365     }
366 #endif
367 
368 	Close();
369 
370 	wxLogTrace(wxT("Function Start/End"), wxT("CBOINCBaseFrame::OnCloseWindow - Function End"));
371 }
372 
373 
OnExit(wxCommandEvent & WXUNUSED (event))374 void CBOINCBaseFrame::OnExit(wxCommandEvent& WXUNUSED(event)) {
375     wxLogTrace(wxT("Function Start/End"), wxT("CAdvancedFrame::OnExit - Function Begin"));
376 
377     if (wxGetApp().ConfirmExit()) {
378 
379         // Save state before exiting
380         SaveState();
381 
382         CDlgEventLog*   eventLog = wxGetApp().GetEventLog();
383         if (eventLog) {
384             eventLog->Destroy();
385         }
386 
387         Close(true);
388     }
389 
390     wxLogTrace(wxT("Function Start/End"), wxT("CAdvancedFrame::OnExit - Function End"));
391 }
392 
393 
GetCurrentViewPage()394 int CBOINCBaseFrame::GetCurrentViewPage() {
395     return _GetCurrentViewPage();
396 }
397 
398 
FireInitialize()399 void CBOINCBaseFrame::FireInitialize() {
400     CFrameEvent event(wxEVT_FRAME_INITIALIZED, this);
401     AddPendingEvent(event);
402 }
403 
404 
FireRefreshView()405 void CBOINCBaseFrame::FireRefreshView() {
406     CMainDocument* pDoc      = wxGetApp().GetDocument();
407 
408     wxASSERT(pDoc);
409     wxASSERT(wxDynamicCast(pDoc, CMainDocument));
410 
411     pDoc->RefreshRPCs();
412     pDoc->RunPeriodicRPCs(0);
413 }
414 
415 
FireConnect()416 void CBOINCBaseFrame::FireConnect() {
417     CFrameEvent event(wxEVT_FRAME_CONNECT, this);
418     AddPendingEvent(event);
419 }
420 
421 
FireReloadSkin()422 void CBOINCBaseFrame::FireReloadSkin() {
423     CFrameEvent event(wxEVT_FRAME_RELOADSKIN, this);
424     AddPendingEvent(event);
425 }
426 
427 
FireNotification()428 void CBOINCBaseFrame::FireNotification() {
429     CFrameEvent event(wxEVT_FRAME_NOTIFICATION, this);
430     AddPendingEvent(event);
431 }
432 
433 
SelectComputer(wxString & hostName,int & portNum,wxString & password,bool required)434 bool CBOINCBaseFrame::SelectComputer(wxString& hostName, int& portNum, wxString& password, bool required) {
435     wxLogTrace(wxT("Function Start/End"), wxT("CBOINCBaseFrame::SelectComputer - Function Begin"));
436 
437     CDlgSelectComputer  dlg(this, required);
438     size_t              lIndex = 0;
439     wxArrayString       aComputerNames;
440     bool                bResult = false;
441 
442     // Lets copy the template store in the system state
443     aComputerNames = m_aSelectedComputerMRU;
444 
445     // Lets populate the combo control with the MRU list
446     dlg.m_ComputerNameCtrl->Clear();
447     for (lIndex = 0; lIndex < aComputerNames.Count(); lIndex++) {
448         dlg.m_ComputerNameCtrl->Append(aComputerNames.Item(lIndex));
449     }
450 
451     if (wxID_OK == dlg.ShowModal()) {
452         hostName = dlg.m_ComputerNameCtrl->GetValue();
453         // Make a null hostname be the same thing as localhost
454         if (wxEmptyString == hostName) {
455             hostName = wxT("localhost");
456             portNum = GUI_RPC_PORT;
457             password = wxEmptyString;
458         } else {
459             // Parse the remote machine info
460             wxString sHost = dlg.m_ComputerNameCtrl->GetValue();
461             long lPort = GUI_RPC_PORT;
462             int iPos = sHost.Find(wxT(":"));
463             if (iPos != wxNOT_FOUND) {
464                 wxString sPort = sHost.substr(iPos + 1);
465                 if (!sPort.ToLong(&lPort)) lPort = GUI_RPC_PORT;
466                 sHost.erase(iPos);
467             }
468             hostName = sHost;
469             portNum = (int)lPort;
470             password = dlg.m_ComputerPasswordCtrl->GetValue();
471         }
472 
473         // Insert a copy of the current combo box value to the head of the
474         //   computer names string array
475         if (wxEmptyString != dlg.m_ComputerNameCtrl->GetValue()) {
476             aComputerNames.Insert(dlg.m_ComputerNameCtrl->GetValue(), 0);
477         }
478 
479         // Loops through the computer names and remove any duplicates that
480         //   might exist with the new head value
481         for (lIndex = 1; lIndex < aComputerNames.Count(); lIndex++) {
482             if (aComputerNames.Item(lIndex) == aComputerNames.Item(0))
483                 aComputerNames.RemoveAt(lIndex);
484         }
485 
486         // Store the modified computer name MRU list back to the system state
487         m_aSelectedComputerMRU = aComputerNames;
488         bResult = true;
489     } else {
490         bResult = false;        // User cancelled
491     }
492 
493     wxLogTrace(wxT("Function Start/End"), wxT("CBOINCBaseFrame::SelectComputer - Function End"));
494     return bResult;
495 }
496 
497 
ShowConnectionBadPasswordAlert(bool bUsedDefaultPassword,int iReadGUIRPCAuthFailure)498 void CBOINCBaseFrame::ShowConnectionBadPasswordAlert( bool bUsedDefaultPassword, int iReadGUIRPCAuthFailure ) {
499     CSkinAdvanced*      pSkinAdvanced = wxGetApp().GetSkinManager()->GetAdvanced();
500     wxString            strDialogTitle = wxEmptyString;
501 
502 
503     wxASSERT(pSkinAdvanced);
504     wxASSERT(wxDynamicCast(pSkinAdvanced, CSkinAdvanced));
505 
506 
507     wxLogTrace(wxT("Function Start/End"), wxT("CBOINCBaseFrame::ShowConnectionBadPasswordAlert - Function Begin"));
508 
509     // %s is the application name
510     //    i.e. 'BOINC Manager', 'GridRepublic Manager'
511     strDialogTitle.Printf(
512         _("%s - Connection Error"),
513         pSkinAdvanced->GetApplicationName().c_str()
514     );
515 
516     if ( bUsedDefaultPassword ) {
517 #ifdef __WXMSW__
518         if ( EACCES == iReadGUIRPCAuthFailure || ENOENT == iReadGUIRPCAuthFailure ) {
519             ShowAlert(
520                 strDialogTitle,
521                 _("You currently are not authorized to manage the client.\nPlease contact your administrator to add you to the 'boinc_users' local user group."),
522                 wxOK | wxICON_ERROR
523             );
524         } else
525 #endif
526         {
527             ShowAlert(
528                 strDialogTitle,
529 #ifndef __WXMAC__
530                 _("Authorization failed connecting to running client.\nMake sure you start this program in the same directory as the client."),
531 #else
532                 _("Authorization failed connecting to running client."),
533 #endif
534                 wxOK | wxICON_ERROR
535             );
536         }
537     } else {
538         ShowAlert(
539             strDialogTitle,
540             _("The password you have provided is incorrect, please try again."),
541             wxOK | wxICON_ERROR
542         );
543     }
544 
545     wxLogTrace(wxT("Function Start/End"), wxT("CBOINCBaseFrame::ShowConnectionBadPasswordAlert - Function End"));
546 }
547 
548 
ShowConnectionFailedAlert()549 void CBOINCBaseFrame::ShowConnectionFailedAlert() {
550     CSkinAdvanced*      pSkinAdvanced = wxGetApp().GetSkinManager()->GetAdvanced();
551     CMainDocument*      pDoc = wxGetApp().GetDocument();
552     wxString            strConnectedCompter = wxEmptyString;
553     wxString            strDialogTitle = wxEmptyString;
554     wxString            strDialogMessage = wxEmptyString;
555 
556     wxASSERT(pSkinAdvanced);
557     wxASSERT(wxDynamicCast(pSkinAdvanced, CSkinAdvanced));
558 
559     wxASSERT(pDoc);
560     wxASSERT(wxDynamicCast(pDoc, CMainDocument));
561 
562     wxLogTrace(wxT("Function Start/End"), wxT("CBOINCBaseFrame::ShowConnectionFailedAlert - Function Begin"));
563 
564     // Did BOINC crash on local computer? If so restart it and reconnect.
565     pDoc->GetConnectedComputerName(strConnectedCompter);
566     if (pDoc->IsComputerNameLocal(strConnectedCompter)) {
567         if (pDoc->m_pClientManager->AutoRestart()) {
568             boinc_sleep(0.5);       // Allow time for Client to restart
569             if (pDoc->m_pClientManager->IsBOINCCoreRunning()) {
570                 pDoc->Reconnect();
571                 return;
572             }
573         } else {
574             // Don't ask whether to reconnect to local client if it is not running
575             if (!pDoc->m_pClientManager->IsBOINCCoreRunning()) {
576                 return;
577             }
578         }
579     }
580 
581     // %s is the application name
582     //    i.e. 'BOINC Manager', 'GridRepublic Manager'
583     strDialogTitle.Printf(
584         _("%s - Connection Failed"),
585         pSkinAdvanced->GetApplicationName().c_str()
586     );
587 
588     // 1st %s is the application name
589     //    i.e. 'BOINC Manager', 'GridRepublic Manager'
590     // 2st %s is the project name
591     //    i.e. 'BOINC', 'GridRepublic'
592     strDialogMessage.Printf(
593         _("%s is not able to connect to a %s client.\nWould you like to try to connect again?"),
594         pSkinAdvanced->GetApplicationName().c_str(),
595         pSkinAdvanced->GetApplicationShortName().c_str()
596     );
597 
598     ShowAlert(
599         strDialogTitle,
600         strDialogMessage,
601         wxYES_NO | wxICON_QUESTION,
602         false,
603         AlertProcessResponse
604     );
605 
606     // If we are minimized, set flag to show alert when maximized
607     m_bShowConnectionFailedAlert = !IsShown();
608 
609     wxLogTrace(wxT("Function Start/End"), wxT("CBOINCBaseFrame::ShowConnectionFailedAlert - Function End"));
610 }
611 
612 
ShowDaemonStartFailedAlert()613 void CBOINCBaseFrame::ShowDaemonStartFailedAlert() {
614     CSkinAdvanced*      pSkinAdvanced = wxGetApp().GetSkinManager()->GetAdvanced();
615     wxString            strDialogTitle = wxEmptyString;
616     wxString            strDialogMessage = wxEmptyString;
617 
618 
619     wxASSERT(pSkinAdvanced);
620     wxASSERT(wxDynamicCast(pSkinAdvanced, CSkinAdvanced));
621 
622 
623     wxLogTrace(wxT("Function Start/End"), wxT("CBOINCBaseFrame::ShowDaemonStartFailedAlert - Function Begin"));
624 
625 
626     // %s is the application name
627     //    i.e. 'BOINC Manager', 'GridRepublic Manager'
628     strDialogTitle.Printf(
629         _("%s - Daemon Start Failed"),
630         pSkinAdvanced->GetApplicationName().c_str()
631     );
632 
633     // 1st %s is the application name
634     //    i.e. 'BOINC Manager', 'GridRepublic Manager'
635     // 2st %s is the project name
636     //    i.e. 'BOINC', 'GridRepublic'
637 #ifdef __WXMSW__
638     strDialogMessage.Printf(
639         _("%s is not able to start a %s client.\nPlease launch the Control Panel->Administative Tools->Services applet and start the BOINC service."),
640         pSkinAdvanced->GetApplicationName().c_str(),
641         pSkinAdvanced->GetApplicationShortName().c_str()
642     );
643 #else
644     strDialogMessage.Printf(
645         _("%s is not able to start a %s client.\nPlease start the daemon and try again."),
646         pSkinAdvanced->GetApplicationName().c_str(),
647         pSkinAdvanced->GetApplicationShortName().c_str()
648     );
649 #endif
650 
651     ShowAlert(
652         strDialogTitle,
653         strDialogMessage,
654         wxOK | wxICON_ERROR
655     );
656 
657     wxLogTrace(wxT("Function Start/End"), wxT("CBOINCBaseFrame::ShowDaemonStartFailedAlert - Function End"));
658 }
659 
660 
ShowNotCurrentlyConnectedAlert()661 void CBOINCBaseFrame::ShowNotCurrentlyConnectedAlert() {
662     CSkinAdvanced*      pSkinAdvanced = wxGetApp().GetSkinManager()->GetAdvanced();
663     CMainDocument*      pDoc = wxGetApp().GetDocument();
664     wxString            strConnectedCompter = wxEmptyString;
665     wxString            strDialogTitle = wxEmptyString;
666     wxString            strDialogMessage = wxEmptyString;
667 
668     wxASSERT(pSkinAdvanced);
669     wxASSERT(wxDynamicCast(pSkinAdvanced, CSkinAdvanced));
670 
671     wxASSERT(pDoc);
672     wxASSERT(wxDynamicCast(pDoc, CMainDocument));
673 
674     wxLogTrace(wxT("Function Start/End"), wxT("CBOINCBaseFrame::ShowNotCurrentlyConnectedAlert - Function Begin"));
675 
676     // Did BOINC crash on local computer? If so restart it and reconnect.
677     pDoc->GetConnectedComputerName(strConnectedCompter);
678     if (pDoc->IsComputerNameLocal(strConnectedCompter)) {
679         if (pDoc->m_pClientManager->AutoRestart()) {
680             boinc_sleep(0.5);       // Allow time for Client to restart
681             if (pDoc->m_pClientManager->IsBOINCCoreRunning()) {
682                 pDoc->Reconnect();
683                 return;
684             }
685         } else {
686             // Don't ask whether to reconnect to local client if it is not running
687             if (!pDoc->m_pClientManager->IsBOINCCoreRunning()) {
688                 return;
689             }
690         }
691     }
692 
693     // %s is the application name
694     //    i.e. 'BOINC Manager', 'GridRepublic Manager'
695     strDialogTitle.Printf(
696         _("%s - Connection Status"),
697         pSkinAdvanced->GetApplicationName().c_str()
698     );
699 
700     // 1st %s is the application name
701     //    i.e. 'BOINC Manager', 'GridRepublic Manager'
702     // 2nd %s is the project name
703     //    i.e. 'BOINC', 'GridRepublic'
704     // 3nd %s is the project name
705     //    i.e. 'BOINC', 'GridRepublic'
706     strDialogMessage.Printf(
707         _("%s is not currently connected to a %s client.\nPlease use the 'Advanced\\Select Computer...' menu option to connect up to a %s client.\nTo connect up to your local computer please use 'localhost' as the host name."),
708         pSkinAdvanced->GetApplicationName().c_str(),
709         pSkinAdvanced->GetApplicationShortName().c_str(),
710         pSkinAdvanced->GetApplicationShortName().c_str()
711     );
712     ShowAlert(
713         strDialogTitle,
714         strDialogMessage,
715         wxOK | wxICON_ERROR
716     );
717 
718     wxLogTrace(wxT("Function Start/End"), wxT("CBOINCBaseFrame::ShowNotCurrentlyConnectedAlert - Function End"));
719 }
720 
721 
StartTimers()722 void CBOINCBaseFrame::StartTimers() {
723     wxASSERT(m_pAlertPollTimer);
724     wxASSERT(m_pPeriodicRPCTimer);
725     wxASSERT(m_pDocumentPollTimer);
726     m_pAlertPollTimer->Start();
727     m_pPeriodicRPCTimer->Start();
728     m_pDocumentPollTimer->Start();
729 }
730 
731 
StopTimers()732 void CBOINCBaseFrame::StopTimers() {
733     wxASSERT(m_pAlertPollTimer);
734     wxASSERT(m_pPeriodicRPCTimer);
735     wxASSERT(m_pDocumentPollTimer);
736     m_pAlertPollTimer->Stop();
737     m_pPeriodicRPCTimer->Stop();
738     m_pDocumentPollTimer->Stop();
739 }
740 
741 
UpdateRefreshTimerInterval()742 void CBOINCBaseFrame::UpdateRefreshTimerInterval() {
743 }
744 
745 #if 0
746 void CBOINCBaseFrame::UpdateStatusText(const wxChar* szStatus) {
747     CFrameEvent event(wxEVT_FRAME_UPDATESTATUS, this, szStatus);
748     ProcessEvent(event);
749 }
750 #endif
751 
ShowAlert(const wxString title,const wxString message,const int style,const bool notification_only,const FrameAlertEventType alert_event_type)752 void CBOINCBaseFrame::ShowAlert( const wxString title, const wxString message, const int style, const bool notification_only, const FrameAlertEventType alert_event_type ) {
753     CFrameAlertEvent event(wxEVT_FRAME_ALERT, this, title, message, style, notification_only, alert_event_type);
754     AddPendingEvent(event);
755 }
756 
757 
SaveState()758 bool CBOINCBaseFrame::SaveState() {
759     wxLogTrace(wxT("Function Start/End"), wxT("CBOINCBaseFrame::SaveState - Function Begin"));
760 
761     wxString        strBaseConfigLocation = wxString(wxT("/"));
762     wxConfigBase*   pConfig = wxConfigBase::Get(FALSE);
763     wxString        strConfigLocation;
764     wxString        strPreviousLocation;
765     wxString        strBuffer;
766     int             iIndex;
767     int             iItemCount;
768 
769 
770     // An odd case happens every once and awhile where wxWidgets looses
771     //   the pointer to the config object, or it is cleaned up before
772     //   the window has finished it's cleanup duty.  If we detect a NULL
773     //   pointer, return false.
774     if (!pConfig) return false;
775 
776     //
777     // Save Frame State
778     //
779     pConfig->SetPath(strBaseConfigLocation);
780 
781     pConfig->Write(wxT("ReminderFrequencyV3"), m_iReminderFrequency);
782     pConfig->Write(wxT("NetworkDialupConnectionName"), m_strNetworkDialupConnectionName);
783 
784 
785     //
786     // Save Computer MRU list
787     //
788     strPreviousLocation = pConfig->GetPath();
789     strConfigLocation = strPreviousLocation + wxT("ComputerMRU");
790 
791     pConfig->SetPath(strConfigLocation);
792 
793     iItemCount = (int)m_aSelectedComputerMRU.GetCount() - 1;
794     for (iIndex = 0; iIndex <= iItemCount; iIndex++) {
795         strBuffer.Printf(wxT("%d"), iIndex);
796         pConfig->Write(
797             strBuffer,
798             m_aSelectedComputerMRU.Item(iIndex)
799         );
800     }
801 
802     pConfig->SetPath(strPreviousLocation);
803 
804 
805     wxLogTrace(wxT("Function Start/End"), wxT("CBOINCBaseFrame::SaveState - Function End"));
806     return true;
807 }
808 
809 
RestoreState()810 bool CBOINCBaseFrame::RestoreState() {
811     wxLogTrace(wxT("Function Start/End"), wxT("CBOINCBaseFrame::RestoreState - Function Begin"));
812 
813     wxString        strBaseConfigLocation = wxString(wxT("/"));
814     wxConfigBase*   pConfig = wxConfigBase::Get(FALSE);
815     wxString        strConfigLocation;
816     wxString        strPreviousLocation;
817     wxString        strBuffer;
818     wxString        strValue;
819     long            iIndex;
820     bool            bKeepEnumerating = false;
821 
822 
823     wxASSERT(pConfig);
824 
825     // An odd case happens every once and awhile where wxWidgets looses
826     //   the pointer to the config object, or it is cleaned up before
827     //   the window has finished it's cleanup duty.  If we detect a NULL
828     //   pointer, return false.
829     if (!pConfig) return false;
830 
831     //
832     // Restore Frame State
833     //
834     pConfig->SetPath(strBaseConfigLocation);
835 
836     pConfig->Read(wxT("ReminderFrequencyV3"), &m_iReminderFrequency, 360L);
837     pConfig->Read(wxT("NetworkDialupConnectionName"), &m_strNetworkDialupConnectionName, wxEmptyString);
838 
839 
840     //
841     // Restore Computer MRU list
842     //
843     strPreviousLocation = pConfig->GetPath();
844     strConfigLocation = strPreviousLocation + wxT("ComputerMRU");
845 
846     pConfig->SetPath(strConfigLocation);
847 
848     m_aSelectedComputerMRU.Clear();
849     bKeepEnumerating = pConfig->GetFirstEntry(strBuffer, iIndex);
850     while (bKeepEnumerating) {
851         pConfig->Read(strBuffer, &strValue);
852 
853         m_aSelectedComputerMRU.Add(strValue);
854         bKeepEnumerating = pConfig->GetNextEntry(strBuffer, iIndex);
855     }
856 
857     pConfig->SetPath(strPreviousLocation);
858 
859 
860     wxLogTrace(wxT("Function Start/End"), wxT("CBOINCBaseFrame::RestoreState - Function End"));
861     return true;
862 }
863 
Show(bool bShow)864 bool CBOINCBaseFrame::Show(bool bShow) {
865     wxLogTrace(wxT("Function Start/End"), wxT("CBOINCBaseFrame::Show - Function Begin"));
866     wxLogTrace(wxT("Function Start/End"), wxT("CBOINCBaseFrame::Show - Show: '%d'"), (int)bShow);
867 
868     bool    retval;
869 
870     if (bShow) {
871         wxGetApp().ShowApplication(true);
872     } else {
873         if ( this == wxGetApp().GetFrame() ) {
874             if (wxGetApp().IsApplicationVisible()) {
875                 wxGetApp().ShowApplication(false);
876             }
877         }
878     }
879 
880     CDlgEventLog* pEventLog = wxGetApp().GetEventLog();
881     if (pEventLog) {
882 #ifdef __WXMAC__
883         if (bShow) {
884             pEventLog->Show(bShow);
885         }
886 #else
887         pEventLog->Show(bShow);
888 #endif
889     }
890 
891 #ifdef __WXMAC__
892     retval = (wxGetApp().IsApplicationVisible() != bShow);
893     if (bShow) {
894         retval = wxFrame::Show(bShow);
895     }
896 #else
897     retval = wxFrame::Show(bShow);
898 #endif
899 
900     wxLogTrace(wxT("Function Start/End"), wxT("CBOINCBaseFrame::Show - Function End"));
901     return retval;
902 }
903 
_GetCurrentViewPage()904 int CBOINCBaseFrame::_GetCurrentViewPage() {
905     wxASSERT(false);
906     return 0;
907 }
908 
909 
ProcessResponse(const int response) const910 void CFrameAlertEvent::ProcessResponse(const int response) const {
911     CMainDocument*      pDoc = wxGetApp().GetDocument();
912 
913     wxASSERT(pDoc);
914     wxASSERT(wxDynamicCast(pDoc, CMainDocument));
915 
916     if ((AlertProcessResponse == m_alert_event_type) && (wxYES == response)) {
917         pDoc->Reconnect();
918     }
919 }
920 
921