MGR: async GUI RPCs: Create SafeMessageBox function to suspend periodic RPCs during modal dialogs

svn path=/trunk/boinc/; revision=15901
This commit is contained in:
Charlie Fenton 2008-08-20 16:07:06 +00:00
parent ca82c70e07
commit f3146210d7
22 changed files with 111 additions and 28 deletions

View File

@ -6835,3 +6835,29 @@ Charlie 19 Aug 2008
samples/
mac_build/
UpperCase2.xcodeproj
Charlie 20 Aug 2008
- MGR: async GUI RPCs: Suspend periodic RPCs during modal dialogs.
clientgui/
AccountInfoPage.cpp
AdvancedFrame.cpp
BOINCBaseFrame.cpp,.h
BOINCDialupManager.cpp
BOINCGUIApp.cpp,.h
BOINCTaskBar.cpp
DlgAdvPreferences.cpp
hyperlink.cpp
MainDocument.cpp
sg_StatImageLoader.cpp
sg_ViewTabPage.cpp
ValidateAccountKey.cpp
ValidateEmailAddress.cpp
ValidateURL.cpp
ViewProjects.cpp
ViewTransfers.cpp
ViewWork.cpp
WizardAccountManager.cpp
WizardAttachProject.cpp
common/
wxFlatNotebook.cpp

View File

@ -492,7 +492,7 @@ void CAccountInfoPage::OnPageChanging( wxWizardExEvent& event )
}
if (bDisplayError) {
::wxMessageBox(
wxGetApp().SafeMessageBox(
strMessage,
strTitle,
wxICON_ERROR | wxOK,

View File

@ -1365,7 +1365,7 @@ void CAdvancedFrame::OnAccountManagerDetach(wxCommandEvent& WXUNUSED(event)) {
wxString(ami.acct_mgr_name.c_str(), wxConvUTF8).c_str()
);
iAnswer = ::wxMessageBox(
iAnswer = wxGetApp().SafeMessageBox(
strMessage,
strTitle,
wxYES_NO | wxICON_QUESTION,

View File

@ -240,7 +240,7 @@ void CBOINCBaseFrame::OnAlert(CFrameAlertEvent& event) {
Show();
}
retval = ::wxMessageBox(event.m_message, event.m_title, event.m_style, this);
retval = SafeMessageBox(event.m_message, event.m_title, event.m_style, this);
if (event.m_alert_event_type == AlertProcessResponse) {
event.ProcessResponse(retval);
}
@ -271,7 +271,7 @@ void CBOINCBaseFrame::OnAlert(CFrameAlertEvent& event) {
);
}
#elif defined (__WXMAC__)
// wxMessageBox() / ProcessResponse() hangs the Manager if hidden.
// SafeMessageBox() / ProcessResponse() hangs the Manager if hidden.
// Currently, the only non-notification-only alert is Connection Failed,
// which is now has logic to be displayed when Manager is maximized.
@ -282,7 +282,7 @@ void CBOINCBaseFrame::OnAlert(CFrameAlertEvent& event) {
if (IsShown() && !event.m_notification_only) {
int retval = 0;
retval = ::wxMessageBox(event.m_message, event.m_title, event.m_style, this);
retval = wxGetApp().SafeMessageBox(event.m_message, event.m_title, event.m_style, this);
if (event.m_alert_event_type == AlertProcessResponse) {
event.ProcessResponse(retval);
}

View File

@ -310,7 +310,7 @@ int CBOINCDialUpManager::Connect() {
_("%s needs to connect to the Internet.\nMay it do so now?"),
pSkinAdvanced->GetApplicationShortName().c_str()
);
iAnswer = ::wxMessageBox(
iAnswer = wxGetApp().SafeMessageBox(
strDialogMessage,
m_strDialogTitle,
wxYES_NO | wxICON_QUESTION,

View File

@ -92,6 +92,7 @@ bool CBOINCGUIApp::OnInit() {
m_strDefaultDesktop = wxEmptyString;
m_strDefaultDisplay = wxEmptyString;
m_iGUISelected = BOINC_SIMPLEGUI;
m_bSafeMessageBoxDisplayed = 0;
#ifdef __WXMSW__
m_hClientLibraryDll = NULL;
#endif
@ -574,10 +575,9 @@ OSErr CBOINCGUIApp::QuitAppleEventHandler( const AppleEvent *appleEvt, AppleEven
FSSpec fileSpec;
OSStatus anErr;
// Refuse to quit if a modal dialog is open. Search for the dialog
// by ID since all of BOINC Manager's dialog IDs are 10000.
// Refuse to quit if a modal dialog is open.
// Unfortunately, I know of no way to disable the Quit item in our Dock menu
if (wxDynamicCast(wxWindow::FindWindowById(ID_ANYDIALOG), wxDialog)) {
if (wxGetApp().IsModalDialogDisplayed()) {
SysBeep(4);
return userCanceledErr;
}
@ -833,4 +833,34 @@ int CBOINCGUIApp::ConfirmExit() {
}
// Use this instead of wxMessageBox from all tab Views to suppress
// Periodic RPCs. See comment in CMainDocument::RunPeriodicRPCs()
// for a fuller explanation.
int CBOINCGUIApp::SafeMessageBox(const wxString& message, const wxString& caption, long style,
wxWindow *parent, int x, int y )
{
int retval;
m_bSafeMessageBoxDisplayed++;
retval = wxMessageBox(message, caption, style, parent, x, y);
m_bSafeMessageBoxDisplayed--;
return retval;
}
bool CBOINCGUIApp::IsModalDialogDisplayed() {
if (m_bSafeMessageBoxDisplayed) return true;
// Search for the dialog by ID since all of BOINC Manager's
// dialog IDs are 10000.
if (wxDynamicCast(wxWindow::FindWindowById(ID_ANYDIALOG), wxDialog)) {
return true;
}
return false;
}
const char *BOINC_RCSID_487cbf3018 = "$Id$";

View File

@ -99,6 +99,8 @@ protected:
// The last value defined in the wxLanguage enum is wxLANGUAGE_USER_DEFINED.
// defined in: wx/intl.h
wxArrayString m_astrLanguages;
int m_bSafeMessageBoxDisplayed;
public:
@ -142,6 +144,14 @@ public:
int ConfirmExit();
int SafeMessageBox(const wxString& message,
const wxString& caption = wxMessageBoxCaptionStr,
long style = wxOK | wxCENTRE,
wxWindow *parent = NULL,
int x = wxDefaultCoord, int y = wxDefaultCoord);
bool IsModalDialogDisplayed();
DECLARE_EVENT_TABLE()
};

View File

@ -633,13 +633,12 @@ void CTaskBarIcon::AdjustMenuItems(wxMenu* pMenu) {
// BOINC Manager crashes if user selects "Exit" from taskbar menu while
// a dialog is open, so we must disable the "Exit" menu item if a dialog
// is open. So lets search for the dialog by ID since all of BOINC
// Manager's dialog IDs are 10000.
// is open.
// On the Mac, the user can open multiple instances of the About dialog
// by repeatedly selecting "About" menu item from the taskbar, so we
// must also disable that item. For consistency with the Mac standard,
// we disable the entire taskbar menu when a modal dialog is open.
if (wxDynamicCast(wxWindow::FindWindowById(ID_ANYDIALOG), wxDialog)) {
if (wxGetApp().IsModalDialogDisplayed()) {
is_dialog_detected = true;
}

View File

@ -572,7 +572,7 @@ void CDlgAdvPreferences::ShowErrorMessage(wxString& message,wxTextCtrl* errorCtr
if(message.IsEmpty()){
message = _("invalid input value detected");
}
wxMessageBox(message,_("Validation Error"),wxOK | wxCENTRE | wxICON_ERROR,this);
wxGetApp().SafeMessageBox(message,_("Validation Error"),wxOK | wxCENTRE | wxICON_ERROR,this);
}
/* checks if ch is a valid character for float values */
@ -706,7 +706,7 @@ void CDlgAdvPreferences::OnClear(wxCommandEvent& ev) {
}
bool CDlgAdvPreferences::ConfirmClear() {
int res = wxMessageBox(_("Do you really want to clear all local preferences ?"),
int res = wxGetApp().SafeMessageBox(_("Do you really want to clear all local preferences ?"),
_("Confirmation"),wxCENTER | wxICON_QUESTION | wxYES_NO | wxNO_DEFAULT,this);
return res==wxYES;

View File

@ -31,6 +31,7 @@
#include "BOINCBaseFrame.h"
#include "MainDocument.h"
#include "BOINCClientManager.h"
#include "Events.h"
#ifndef _WIN32
#include <sys/wait.h>
@ -731,6 +732,20 @@ void CMainDocument::RunPeriodicRPCs() {
// TODO: modify SimpleGUI to not do RPCs when hidden / minimized
if (! ((currentTabView & VW_SGUI) || pFrame->IsShown()) ) return;
// several functions (such as Abort, Reset, Detach) display an
// "Are you sure?" dialog before passing a pointer to a result
// or project in a demand RPC call. If Periodic RPCs continue
// to run during these dialogs, that pointer may no longer be
// valid by the time the demand RPC is executed. So we suspend
// periodic RPCs during modal dialogs. Search for the dialog
// by ID since all of BOINC Manager's dialog IDs are 10000.
//
// Note that this depends on using wxGetApp().SafeMessageBox()
// instead of wxMessageBox in all tab views.
if (wxGetApp().IsModalDialogDisplayed()) {
return;
}
wxDateTime dtNow(wxDateTime::Now());
// *********** RPC_GET_CC_STATUS **************

View File

@ -21,6 +21,7 @@
#include "stdwx.h"
#include "ValidateAccountKey.h"
#include "BOINCGUIApp.h"
IMPLEMENT_DYNAMIC_CLASS(CValidateAccountKey, wxValidator)
@ -78,7 +79,7 @@ bool CValidateAccountKey::Validate(wxWindow *parent) {
wxString buf;
buf.Printf(m_errormsg, control->GetValue().c_str());
wxMessageBox(buf, _("Validation conflict"),
wxGetApp().SafeMessageBox(buf, _("Validation conflict"),
wxOK | wxICON_EXCLAMATION, parent
);
}

View File

@ -21,6 +21,7 @@
#include "stdwx.h"
#include "ValidateEmailAddress.h"
#include "BOINCGUIApp.h"
IMPLEMENT_DYNAMIC_CLASS(CValidateEmailAddress, wxValidator)
@ -82,7 +83,7 @@ bool CValidateEmailAddress::Validate(wxWindow *parent) {
wxString buf;
buf.Printf(m_errormsg, control->GetValue().c_str());
wxMessageBox(buf, _("Validation conflict"),
wxGetApp().SafeMessageBox(buf, _("Validation conflict"),
wxOK | wxICON_EXCLAMATION, parent
);
}

View File

@ -21,6 +21,7 @@
#include "stdwx.h"
#include "ValidateURL.h"
#include "BOINCGUIApp.h"
#include "str_util.h"
@ -121,7 +122,7 @@ bool CValidateURL::Validate(wxWindow *parent) {
wxString buf;
buf.Printf(m_errormsg, control->GetValue().c_str());
wxMessageBox(buf, m_errortitle,
wxGetApp().SafeMessageBox(buf, m_errortitle,
wxOK | wxICON_EXCLAMATION, parent
);
}

View File

@ -392,7 +392,7 @@ void CViewProjects::OnProjectReset( wxCommandEvent& WXUNUSED(event) ) {
pProject->m_strProjectName.c_str()
);
iAnswer = ::wxMessageBox(
iAnswer = wxGetApp().SafeMessageBox(
strMessage,
_("Reset Project"),
wxYES_NO | wxICON_QUESTION,
@ -447,7 +447,7 @@ void CViewProjects::OnProjectDetach( wxCommandEvent& WXUNUSED(event) ) {
pProject->m_strProjectName.c_str()
);
iAnswer = ::wxMessageBox(
iAnswer = wxGetApp().SafeMessageBox(
strMessage,
_("Detach from Project"),
wxYES_NO | wxICON_QUESTION,

View File

@ -271,7 +271,7 @@ void CViewTransfers::OnTransfersAbort( wxCommandEvent& WXUNUSED(event) ) {
pTransfer->m_strFileName.c_str()
);
iAnswer = ::wxMessageBox(
iAnswer = wxGetApp().SafeMessageBox(
strMessage,
_("Abort File Transfer"),
wxYES_NO | wxICON_QUESTION,

View File

@ -297,7 +297,7 @@ void CViewWork::OnWorkShowGraphics( wxCommandEvent& WXUNUSED(event) ) {
#if (defined(_WIN32) || defined(__WXMAC__))
pDoc->GetConnectedComputerName(strMachineName);
if (!pDoc->IsComputerNameLocal(strMachineName)) {
iAnswer = ::wxMessageBox(
iAnswer = wxGetApp().SafeMessageBox(
_("Are you sure you want to display graphics on a remote machine?"),
_("Show graphics"),
wxYES_NO | wxICON_QUESTION,
@ -375,7 +375,7 @@ void CViewWork::OnWorkAbort( wxCommandEvent& WXUNUSED(event) ) {
strStatus.c_str()
);
iAnswer = ::wxMessageBox(
iAnswer = wxGetApp().SafeMessageBox(
strMessage,
_("Abort task"),
wxYES_NO | wxICON_QUESTION,

View File

@ -430,7 +430,7 @@ void CWizardAccountManager::_ProcessCancelEvent( wxWizardExEvent& event ) {
bool bCancelWithoutNextPage = false;
wxWizardPageEx* page = GetCurrentPage();
int iRetVal = ::wxMessageBox(
int iRetVal = wxGetApp().SafeMessageBox(
_("Do you really want to cancel?"),
_("Question"),
wxICON_QUESTION | wxYES_NO,

View File

@ -462,7 +462,7 @@ void CWizardAttachProject::_ProcessCancelEvent( wxWizardExEvent& event ) {
bool bCancelWithoutNextPage = false;
wxWizardPageEx* page = GetCurrentPage();
int iRetVal = ::wxMessageBox(
int iRetVal = wxGetApp().SafeMessageBox(
_("Do you really want to cancel?"),
_("Question"),
wxICON_QUESTION | wxYES_NO,

View File

@ -1390,7 +1390,7 @@ int wxPageContainerBase::HitTest(const wxPoint& pt, wxPageInfo& pageInfo, int &t
if(tabRect.Inside(pt))
{
// We have a match
// wxMessageBox(pgInfo.m_strCaption);
// wxGetApp().SafeMessageBox(pgInfo.m_strCaption);
pageInfo = pgInfo;
tabIdx = (int)cur;
return wxFNB_TAB;

View File

@ -195,7 +195,7 @@ void wxHyperLink::ExecuteLink (const wxString &strLink) {
wxGetApp().GetSkinManager()->GetAdvanced()->GetApplicationName().c_str()
);
::wxMessageBox(
::wxGetApp().SafeMessageBox(
strDialogMessage,
strDialogTitle,
wxOK | wxICON_INFORMATION

View File

@ -217,7 +217,7 @@ void StatImageLoader::OnProjectDetach() {
strProjectName.c_str()
);
iAnswer = ::wxMessageBox(
iAnswer = wxGetApp().SafeMessageBox(
strMessage,
_("Detach from Project"),
wxYES_NO | wxICON_QUESTION,

View File

@ -413,7 +413,7 @@ void CViewTabPage::OnWorkShowGraphics() {
#if (defined(_WIN32) || defined(__WXMAC__))
pDoc->GetConnectedComputerName(strMachineName);
if (!pDoc->IsComputerNameLocal(strMachineName)) {
iAnswer = ::wxMessageBox(
iAnswer = wxGetApp().SafeMessageBox(
_("Are you sure you want to display graphics on a remote machine?"),
_("Show graphics"),
wxYES_NO | wxICON_QUESTION,