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 "WizardAttach.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 "wizardex.h"
30 #include "error_numbers.h"
31 #include "browser.h"
32 #include "BOINCGUIApp.h"
33 #include "SkinManager.h"
34 #include "MainDocument.h"
35 #include "BOINCBaseWizard.h"
36 #include "BOINCBaseFrame.h"
37 #include "WizardAttach.h"
38 #include "ProjectInfoPage.h"
39 #include "ProjectPropertiesPage.h"
40 #include "ProjectProcessingPage.h"
41 #include "ProjectWelcomePage.h"
42 #include "AccountManagerInfoPage.h"
43 #include "AccountManagerPropertiesPage.h"
44 #include "AccountManagerProcessingPage.h"
45 #include "TermsOfUsePage.h"
46 #include "AccountInfoPage.h"
47 #include "CompletionPage.h"
48 #include "CompletionErrorPage.h"
49 #include "NotDetectedPage.h"
50 #include "UnavailablePage.h"
51 #include "NoInternetConnectionPage.h"
52 #include "NotFoundPage.h"
53 #include "AlreadyExistsPage.h"
54 #include "ProxyInfoPage.h"
55 #include "ProxyPage.h"
56
57
58 /*!
59 * CWizardAttach type definition
60 */
61
IMPLEMENT_DYNAMIC_CLASS(CWizardAttach,CBOINCBaseWizard)62 IMPLEMENT_DYNAMIC_CLASS( CWizardAttach, CBOINCBaseWizard )
63
64 /*!
65 * CWizardAttach event table definition
66 */
67
68 BEGIN_EVENT_TABLE( CWizardAttach, CBOINCBaseWizard )
69 ////@begin CWizardAttach event table entries
70 EVT_WIZARDEX_FINISHED( ID_ATTACHWIZARD, CWizardAttach::OnFinished )
71 ////@end CWizardAttach event table entries
72 END_EVENT_TABLE()
73
74 /*!
75 * CWizardAttach constructors
76 */
77
78 CWizardAttach::CWizardAttach()
79 {
80 }
81
CWizardAttach(wxWindow * parent,wxWindowID id,const wxString & title,const wxPoint & pos,long style)82 CWizardAttach::CWizardAttach( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, long style )
83 {
84 Create(parent, id, title, pos, style);
85 }
86
87 /*!
88 * CWizardAttach creator
89 */
90
Create(wxWindow * parent,wxWindowID id,const wxString &,const wxPoint & pos,long style)91 bool CWizardAttach::Create( wxWindow* parent, wxWindowID id, const wxString& /* title */, const wxPoint& pos, long style )
92 {
93
94 ////@begin CWizardAttach member initialisation
95 m_ProjectInfoPage = NULL;
96 m_ProjectPropertiesPage = NULL;
97 m_ProjectProcessingPage = NULL;
98 m_ProjectWelcomePage = NULL;
99 m_AccountManagerInfoPage = NULL;
100 m_AccountManagerPropertiesPage = NULL;
101 m_AccountManagerProcessingPage = NULL;
102 m_TermsOfUsePage = NULL;
103 m_AccountInfoPage = NULL;
104 m_CompletionPage = NULL;
105 m_CompletionErrorPage = NULL;
106 m_ErrNotDetectedPage = NULL;
107 m_ErrUnavailablePage = NULL;
108 m_ErrNoInternetConnectionPage = NULL;
109 m_ErrNotFoundPage = NULL;
110 m_ErrAlreadyExistsPage = NULL;
111 m_ErrProxyInfoPage = NULL;
112 m_ErrProxyPage = NULL;
113 m_ErrUserDisagreesPage = NULL;
114 ////@end CWizardAttach member initialisation
115
116 // Cancel Checking
117 m_bCancelInProgress = false;
118
119 // Wizard Detection
120
121 IsAttachToProjectWizard = true;
122 IsChangeWCGApps = false;
123 IsFirstPass = false;
124 IsAccountManagerWizard = false;
125 IsAccountManagerUpdateWizard = false;
126
127 // Global wizard status
128 project_config.clear();
129 account_in.clear();
130 account_out.clear();
131 account_created_successfully = false;
132 attached_to_project_successfully = false;
133 m_bCloseWhenCompleted = false;
134 m_strProjectName.Empty();
135 m_strProjectUrl.Empty();
136 m_strProjectAuthenticator.Empty();
137 m_strProjectSetupCookie.Empty();
138 m_strReturnURL.Empty();
139 m_bCredentialsCached = false;
140 m_bCredentialsDetected = false;
141 m_bCookieRequired = false;
142 m_strCookieFailureURL.Empty();
143
144
145 CSkinAdvanced* pSkinAdvanced = wxGetApp().GetSkinManager()->GetAdvanced();
146 CSkinWizardATP* pSkinWizardATP = wxGetApp().GetSkinManager()->GetWizards()->GetWizardATP();
147
148 wxASSERT(pSkinAdvanced);
149 wxASSERT(pSkinWizardATP);
150 wxASSERT(wxDynamicCast(pSkinAdvanced, CSkinAdvanced));
151 wxASSERT(wxDynamicCast(pSkinWizardATP, CSkinWizardATP));
152
153
154 wxString strTitle;
155 if (!pSkinWizardATP->GetWizardTitle().IsEmpty()) {
156 strTitle = pSkinWizardATP->GetWizardTitle();
157 } else {
158 strTitle = pSkinAdvanced->GetApplicationName();
159 }
160
161 ////@begin CWizardAttach creation
162 CBOINCBaseWizard::Create( parent, id, strTitle, pos, style );
163
164 CreateControls();
165 ////@end CWizardAttach creation
166
167 return TRUE;
168 }
169
170 /*!
171 * Control creation for CWizardAttach
172 */
173
CreateControls()174 void CWizardAttach::CreateControls()
175 {
176 wxLogTrace(wxT("Function Start/End"), wxT("CWizardAttach::CreateControls - Function Begin"));
177
178 ////@begin CWizardAttach content construction
179 CWizardAttach* itemWizard1 = this;
180
181 m_AccountManagerInfoPage = new CAccountManagerInfoPage;
182 m_AccountManagerInfoPage->Create( itemWizard1 );
183 GetPageAreaSizer()->Add(m_AccountManagerInfoPage);
184
185 m_AccountManagerPropertiesPage = new CAccountManagerPropertiesPage;
186 m_AccountManagerPropertiesPage->Create( itemWizard1 );
187 GetPageAreaSizer()->Add(m_AccountManagerPropertiesPage);
188
189 m_AccountManagerProcessingPage = new CAccountManagerProcessingPage;
190 m_AccountManagerProcessingPage->Create( itemWizard1 );
191 GetPageAreaSizer()->Add(m_AccountManagerProcessingPage);
192
193 m_ProjectInfoPage = new CProjectInfoPage;
194 m_ProjectInfoPage->Create( itemWizard1 );
195 GetPageAreaSizer()->Add(m_ProjectInfoPage);
196
197 m_ProjectPropertiesPage = new CProjectPropertiesPage;
198 m_ProjectPropertiesPage->Create( itemWizard1 );
199 GetPageAreaSizer()->Add(m_ProjectPropertiesPage);
200
201 m_ProjectProcessingPage = new CProjectProcessingPage;
202 m_ProjectProcessingPage->Create( itemWizard1 );
203 GetPageAreaSizer()->Add(m_ProjectProcessingPage);
204
205 m_ProjectWelcomePage = new CProjectWelcomePage;
206 m_ProjectWelcomePage->Create( itemWizard1 );
207 GetPageAreaSizer()->Add(m_ProjectWelcomePage);
208
209 m_AccountInfoPage = new CAccountInfoPage;
210 m_AccountInfoPage->Create( itemWizard1 );
211 GetPageAreaSizer()->Add(m_AccountInfoPage);
212
213 m_TermsOfUsePage = new CTermsOfUsePage;
214 m_TermsOfUsePage->Create( itemWizard1 );
215 GetPageAreaSizer()->Add(m_TermsOfUsePage);
216
217 m_CompletionPage = new CCompletionPage;
218 m_CompletionPage->Create( itemWizard1 );
219 GetPageAreaSizer()->Add(m_CompletionPage);
220
221 m_CompletionErrorPage = new CCompletionErrorPage;
222 m_CompletionErrorPage->Create( itemWizard1 );
223 GetPageAreaSizer()->Add(m_CompletionErrorPage);
224
225 m_ErrNotDetectedPage = new CErrNotDetectedPage;
226 m_ErrNotDetectedPage->Create( itemWizard1 );
227 GetPageAreaSizer()->Add(m_ErrNotDetectedPage);
228
229 m_ErrUnavailablePage = new CErrUnavailablePage;
230 m_ErrUnavailablePage->Create( itemWizard1 );
231 GetPageAreaSizer()->Add(m_ErrUnavailablePage);
232
233 m_ErrNoInternetConnectionPage = new CErrNoInternetConnectionPage;
234 m_ErrNoInternetConnectionPage->Create( itemWizard1 );
235 GetPageAreaSizer()->Add(m_ErrNoInternetConnectionPage);
236
237 m_ErrNotFoundPage = new CErrNotFoundPage;
238 m_ErrNotFoundPage->Create( itemWizard1 );
239 GetPageAreaSizer()->Add(m_ErrNotFoundPage);
240
241 m_ErrAlreadyExistsPage = new CErrAlreadyExistsPage;
242 m_ErrAlreadyExistsPage->Create( itemWizard1 );
243 GetPageAreaSizer()->Add(m_ErrAlreadyExistsPage);
244
245 m_ErrProxyInfoPage = new CErrProxyInfoPage;
246 m_ErrProxyInfoPage->Create( itemWizard1 );
247 GetPageAreaSizer()->Add(m_ErrProxyInfoPage);
248
249 m_ErrProxyPage = new CErrProxyPage;
250 m_ErrProxyPage->Create( itemWizard1 );
251 GetPageAreaSizer()->Add(m_ErrProxyPage);
252
253 ////@end CWizardAttach content construction
254
255 wxLogTrace(wxT("Function Start/End"), wxT("CWizardAttach::CreateControls - Function End"));
256 }
257
258 /*!
259 * Runs the wizard.
260 */
Run(wxString strProjectName,wxString strProjectURL,wxString strProjectAuthenticator,wxString strProjectInstitution,wxString strProjectDescription,wxString strProjectKnown,wxString strProjectSetupCookie,bool bAccountKeyDetected,bool bEmbedded)261 bool CWizardAttach::Run(
262 wxString strProjectName,
263 wxString strProjectURL,
264 wxString strProjectAuthenticator,
265 wxString strProjectInstitution,
266 wxString strProjectDescription,
267 wxString strProjectKnown,
268 wxString strProjectSetupCookie,
269 bool bAccountKeyDetected,
270 bool bEmbedded
271 ){
272 SetProjectName(strProjectName);
273 if (strProjectURL.size()) {
274 SetProjectURL(strProjectURL);
275 SetCredentialsCached(bAccountKeyDetected);
276 }
277 SetProjectInstitution(strProjectInstitution);
278 SetProjectDescription(strProjectDescription);
279 if (strProjectAuthenticator.size()) {
280 SetProjectAuthenticator(strProjectAuthenticator);
281 }
282 if (strProjectSetupCookie.size()) {
283 SetProjectSetupCookie(strProjectSetupCookie);
284 }
285 SetProjectKnown(strProjectKnown.length() > 0);
286
287 if (strProjectURL.size() && strProjectAuthenticator.size() && !bAccountKeyDetected) {
288 SetCredentialsDetected(true);
289 SetCloseWhenCompleted(true);
290 }
291
292 if (m_ProjectPropertiesPage && m_ProjectInfoPage && m_ProjectWelcomePage) {
293 IsAttachToProjectWizard = true;
294 IsAccountManagerWizard = false;
295 if (strProjectName.size() && strProjectURL.size() && ((strProjectSetupCookie.IsEmpty()) || !bEmbedded)) {
296 return RunWizard(m_ProjectWelcomePage);
297 } else if (strProjectURL.size() && (IsCredentialsCached() || IsCredentialsDetected() || (strProjectSetupCookie.size() && bEmbedded))) {
298 return RunWizard(m_ProjectPropertiesPage);
299 } else {
300 return RunWizard(m_ProjectInfoPage);
301 }
302 }
303
304 return FALSE;
305 }
306
307
SyncToAccountManager()308 bool CWizardAttach::SyncToAccountManager() {
309 ACCT_MGR_INFO ami;
310 CMainDocument* pDoc = wxGetApp().GetDocument();
311
312 wxASSERT(pDoc);
313 wxASSERT(wxDynamicCast(pDoc, CMainDocument));
314
315 IsAttachToProjectWizard = false;
316 IsAccountManagerWizard = true;
317
318 pDoc->rpc.acct_mgr_info(ami);
319
320 if (ami.acct_mgr_url.size()) {
321 SetProjectName(wxString(ami.acct_mgr_name.c_str(), wxConvUTF8));
322 SetProjectURL(wxString(ami.acct_mgr_url.c_str(), wxConvUTF8));
323
324 SetCredentialsCached(ami.have_credentials);
325 SetCookieRequired(ami.cookie_required);
326 SetCookieFailureURL(wxString(ami.cookie_failure_url.c_str(), wxConvUTF8));
327 if (IsCredentialsCached()) {
328 IsAccountManagerUpdateWizard = true;
329 }
330 }
331
332 if (ami.acct_mgr_url.size() && !m_bCredentialsCached) {
333 std::string login;
334 std::string password_hash;
335 std::string return_url;
336
337 if (detect_account_manager_credentials(ami.acct_mgr_url, login, password_hash, return_url)) {
338 wxString strLogin;
339 wxString strPasswordHash;
340 wxString strReturnURL;
341
342 strLogin = wxURL::Unescape(wxString(login.c_str(), wxConvUTF8));
343 strPasswordHash = wxURL::Unescape(wxString(password_hash.c_str(), wxConvUTF8));
344 strReturnURL = wxURL::Unescape(wxString(return_url.c_str(), wxConvUTF8));
345
346 SetCredentialsDetected(true);
347 SetReturnURL(strReturnURL);
348 SetAccountEmailAddress(strLogin);
349 SetAccountUsername(strLogin);
350 SetAccountPassword(
351 wxString(_T("hash:")) + strPasswordHash
352 );
353 }
354 }
355
356 if (m_AccountManagerInfoPage || m_AccountManagerPropertiesPage) {
357 IsAttachToProjectWizard = false;
358 IsAccountManagerWizard = true;
359 if (!ami.acct_mgr_url.size()) {
360 return RunWizard(m_AccountManagerInfoPage);
361 } else {
362 return RunWizard(m_AccountManagerPropertiesPage);
363 }
364 }
365
366 return FALSE;
367 }
368
369 /*!
370 * Should we show tooltips?
371 */
372
ShowToolTips()373 bool CWizardAttach::ShowToolTips()
374 {
375 return TRUE;
376 }
377
378 /*!
379 * Get bitmap resources
380 */
381
GetBitmapResource(const wxString & WXUNUSED (name))382 wxBitmap CWizardAttach::GetBitmapResource( const wxString& WXUNUSED(name) )
383 {
384 // Bitmap retrieval
385 ////@begin CWizardAttach bitmap retrieval
386 return wxNullBitmap;
387 ////@end CWizardAttach bitmap retrieval
388 }
389
390 /*!
391 * Get icon resources
392 */
393
GetIconResource(const wxString & WXUNUSED (name))394 wxIcon CWizardAttach::GetIconResource( const wxString& WXUNUSED(name) )
395 {
396 // Icon retrieval
397 ////@begin CWizardAttach icon retrieval
398 return wxNullIcon;
399 ////@end CWizardAttach icon retrieval
400 }
401
402 /*!
403 * Determine if the wizard page has a next page
404 */
405
HasNextPage(wxWizardPageEx * page)406 bool CWizardAttach::HasNextPage( wxWizardPageEx* page )
407 {
408 bool bNoNextPageDetected = false;
409
410 bNoNextPageDetected |= (page == m_CompletionPage);
411 bNoNextPageDetected |= (page == m_CompletionErrorPage);
412 bNoNextPageDetected |= (page == m_ErrNotDetectedPage);
413 bNoNextPageDetected |= (page == m_ErrUnavailablePage);
414 bNoNextPageDetected |= (page == m_ErrNoInternetConnectionPage);
415 bNoNextPageDetected |= (page == m_ErrAlreadyExistsPage);
416
417 if (bNoNextPageDetected)
418 return false;
419 return true;
420 }
421
422 /*!
423 * Determine if the wizard page has a previous page
424 */
425
HasPrevPage(wxWizardPageEx * page)426 bool CWizardAttach::HasPrevPage( wxWizardPageEx* page )
427 {
428 bool bNoPrevPageDetected = false;
429
430 bNoPrevPageDetected |= (page == m_ProjectWelcomePage);
431 bNoPrevPageDetected |= (page == m_ProjectInfoPage);
432 bNoPrevPageDetected |= (page == m_AccountManagerInfoPage);
433 bNoPrevPageDetected |= (page == m_CompletionPage);
434 bNoPrevPageDetected |= (page == m_CompletionErrorPage);
435
436 if (bNoPrevPageDetected)
437 return false;
438 return true;
439 }
440
441 /*!
442 * Translate a Page ID into the wxWizardPageEx instance pointer.
443 */
444
TranslatePage(unsigned long ulPageID)445 wxWizardPageEx* CWizardAttach::TranslatePage(unsigned long ulPageID) {
446 wxWizardPageEx* pPage = NULL;
447
448 if (ID_PROJECTINFOPAGE == ulPageID)
449 pPage = m_ProjectInfoPage;
450
451 if (ID_PROJECTPROPERTIESPAGE == ulPageID)
452 pPage = m_ProjectPropertiesPage;
453
454 if (ID_PROJECTPROCESSINGPAGE == ulPageID)
455 pPage = m_ProjectProcessingPage;
456
457 if (ID_PROJECTWELCOMEPAGE == ulPageID)
458 pPage = m_ProjectWelcomePage;
459
460 if (ID_ACCOUNTMANAGERINFOPAGE == ulPageID)
461 pPage = m_AccountManagerInfoPage;
462
463 if (ID_ACCOUNTMANAGERPROPERTIESPAGE == ulPageID)
464 pPage = m_AccountManagerPropertiesPage;
465
466 if (ID_ACCOUNTMANAGERPROCESSINGPAGE == ulPageID)
467 pPage = m_AccountManagerProcessingPage;
468
469 if (ID_TERMSOFUSEPAGE == ulPageID)
470 pPage = m_TermsOfUsePage;
471
472 if (ID_ACCOUNTINFOPAGE == ulPageID)
473 pPage = m_AccountInfoPage;
474
475 if (ID_COMPLETIONPAGE == ulPageID)
476 pPage = m_CompletionPage;
477
478 if (ID_COMPLETIONERRORPAGE == ulPageID)
479 pPage = m_CompletionErrorPage;
480
481 if (ID_ERRNOTDETECTEDPAGE == ulPageID)
482 pPage = m_ErrNotDetectedPage;
483
484 if (ID_ERRUNAVAILABLEPAGE == ulPageID)
485 pPage = m_ErrUnavailablePage;
486
487 if (ID_ERRNOINTERNETCONNECTIONPAGE == ulPageID)
488 pPage = m_ErrNoInternetConnectionPage;
489
490 if (ID_ERRNOTFOUNDPAGE == ulPageID)
491 pPage = m_ErrNotFoundPage;
492
493 if (ID_ERRALREADYEXISTSPAGE == ulPageID)
494 pPage = m_ErrAlreadyExistsPage;
495
496 if (ID_ERRPROXYINFOPAGE == ulPageID)
497 pPage = m_ErrProxyInfoPage;
498
499 if (ID_ERRPROXYPAGE == ulPageID)
500 pPage = m_ErrProxyPage;
501
502 return pPage;
503 }
504
505 /*!
506 * Remove the page transition from the stack.
507 */
PopPageTransition()508 wxWizardPageEx* CWizardAttach::PopPageTransition() {
509 wxWizardPageEx* pPage = NULL;
510 if (GetCurrentPage()) {
511 if (!m_PageTransition.empty()) {
512 pPage = m_PageTransition.top();
513
514 wxLogTrace(wxT("Function Status"), wxT("CWizardAttach::PopPageTransition - Popping Page: '%p'"), pPage);
515 m_PageTransition.pop();
516
517 // TODO: Figure out the best way to handle the situation where the wizard has been launched with a
518 // project init file and the volunteer hits the back button on the m_ProjectPropertiesPage/
519 // m_AccountManagerPropertiesPage page. Ideally they go back to the m_ProjectInfoPage/
520 // m_AccountManagerInfoPage page, but since the wizard launched in automatic attach mode
521 // that page isn't on the stack and the manager crashes.
522 //
523 // It is probably enough to just push the correct InfoPage on the stack before launching the
524 // wizard in automatic mode. I need to think about it some more.
525 //
526 if ((pPage == m_ProjectPropertiesPage) || (pPage == m_ProjectProcessingPage) ||
527 (pPage == m_AccountManagerPropertiesPage) || (pPage == m_AccountManagerProcessingPage))
528 {
529 // We want to go back to the page before we attempted to communicate
530 // with any server.
531 pPage = m_PageTransition.top();
532
533 wxLogTrace(wxT("Function Status"), wxT("CWizardAttach::PopPageTransition - Popping Page: '%p'"), pPage);
534 m_PageTransition.pop();
535
536 }
537 wxASSERT(pPage);
538 return pPage;
539 }
540 }
541 return NULL;
542 }
543
544
545 /*!
546 * Push a page onto the stack.
547 */
548
PushPage(unsigned long ulPageID)549 wxWizardPageEx* CWizardAttach::PushPage( unsigned long ulPageID ) {
550 if (GetCurrentPage()) {
551 wxWizardPageEx* pPage = TranslatePage(ulPageID);
552 if (pPage) {
553 wxLogTrace(wxT("Function Status"), wxT("CWizardAttach::PushPage - Pushing Page: '%p'"), pPage);
554 m_PageTransition.push(pPage);
555 return pPage;
556 }
557 }
558 return NULL;
559 }
560
561
562 /*!
563 * Add the page transition to the stack.
564 */
PushPageTransition(wxWizardPageEx * pCurrentPage,unsigned long ulPageID)565 wxWizardPageEx* CWizardAttach::PushPageTransition( wxWizardPageEx* pCurrentPage, unsigned long ulPageID ) {
566 if (GetCurrentPage()) {
567 wxWizardPageEx* pPage = TranslatePage(ulPageID);
568 if (pPage) {
569 if (m_PageTransition.empty()) {
570 wxLogTrace(wxT("Function Status"), wxT("CWizardAttach::PushPageTransition - Pushing Page: '%p'"), pPage);
571 m_PageTransition.push(NULL);
572 }
573 if (m_PageTransition.top() != pCurrentPage) {
574 wxLogTrace(wxT("Function Status"), wxT("CWizardAttach::PushPageTransition - Pushing Page: '%p'"), pPage);
575 m_PageTransition.push(pCurrentPage);
576 }
577 return pPage;
578 }
579 }
580 return NULL;
581 }
582
_ProcessCancelEvent(wxWizardExEvent & event)583 void CWizardAttach::_ProcessCancelEvent( wxWizardExEvent& event ) {
584
585 bool bCancelWithoutNextPage = false;
586 wxWizardPageEx* page = GetCurrentPage();
587
588 m_bCancelInProgress = true;
589
590 int iRetVal = wxGetApp().SafeMessageBox(
591 _("Do you really want to cancel?"),
592 _("Question"),
593 wxICON_QUESTION | wxYES_NO,
594 this
595 );
596
597 // Reenable the next and back buttons if they have been disabled
598 GetNextButton()->Enable(HasNextPage(page));
599 GetBackButton()->Enable(HasPrevPage(page));
600
601 // Generic rules
602 bCancelWithoutNextPage |= (page == m_ErrNotDetectedPage);
603 bCancelWithoutNextPage |= (page == m_ErrUnavailablePage);
604 bCancelWithoutNextPage |= (page == m_ErrNoInternetConnectionPage);
605
606 if (IsAttachToProjectWizard) {
607 bCancelWithoutNextPage |= (page == m_ErrAlreadyExistsPage);
608 } else {
609 bCancelWithoutNextPage |= (page == m_ProjectWelcomePage);
610 }
611
612 if (wxYES != iRetVal) {
613 event.Veto();
614 m_bCancelInProgress = false;
615 } else {
616 m_bCancelInProgress = true;
617 }
618 }
619
620 /*!
621 * wxEVT_WIZARD_FINISHED event handler for ID_ATTACHPROJECTWIZARD
622 */
623
OnFinished(wxWizardExEvent & event)624 void CWizardAttach::OnFinished( wxWizardExEvent& event ) {
625
626 if (IsAccountManagerWizard) {
627 // Attached to an account manager
628 if (!GetReturnURL().empty() && GetAttachedToProjectSuccessfully()) {
629 wxLaunchDefaultBrowser(GetReturnURL());
630 }
631 } else {
632 // Attached to a project
633 if (GetAccountCreatedSuccessfully() && GetAttachedToProjectSuccessfully()) {
634 wxLaunchDefaultBrowser(GetProjectURL() + wxT("account_finish.php?auth=") + GetProjectAuthenticator());
635 }
636 }
637
638 // Let the framework clean things up.
639 event.Skip();
640 }
641
642