KiCad PCB EDA Suite
confirm.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2007 Jean-Pierre Charras, jp.charras at wanadoo.fr
5  * Copyright (C) 1992-2019 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
25 #include <wx/stockitem.h>
26 #include <wx/richmsgdlg.h>
27 #include <confirm.h>
28 #include <bitmaps.h>
29 #include <html_messagebox.h>
30 #include <functional>
31 #include <unordered_map>
32 
33 // Set of dialogs that have been chosen not to be shown again
34 static std::unordered_map<unsigned long, int> doNotShowAgainDlgs;
35 
36 
37 KIDIALOG::KIDIALOG( wxWindow* aParent, const wxString& aMessage,
38  const wxString& aCaption, long aStyle )
39  : wxRichMessageDialog( aParent, aMessage, aCaption, aStyle | wxCENTRE | wxSTAY_ON_TOP ),
40  m_hash( 0 )
41 {
42 }
43 
44 
45 KIDIALOG::KIDIALOG( wxWindow* aParent, const wxString& aMessage,
46  KD_TYPE aType, const wxString& aCaption )
47  : wxRichMessageDialog( aParent, aMessage, getCaption( aType, aCaption ), getStyle( aType ) ),
48  m_hash( 0 )
49 {
50 }
51 
52 
53 void KIDIALOG::DoNotShowCheckbox( wxString aUniqueId, int line )
54 {
55  ShowCheckBox( _( "Do not show again" ), false );
56 
57  m_hash = std::hash<wxString>{}( aUniqueId ) + line;
58 }
59 
60 
62 {
63  return doNotShowAgainDlgs.count( m_hash ) > 0;
64 }
65 
66 
68 {
69  doNotShowAgainDlgs.erase( m_hash );
70 }
71 
72 
73 bool KIDIALOG::Show( bool aShow )
74 {
75  // We should check the do-not-show-again setting only when the dialog is displayed
76  if( aShow )
77  {
78  // Check if this dialog should be shown to the user
79  auto it = doNotShowAgainDlgs.find( m_hash );
80 
81  if( it != doNotShowAgainDlgs.end() )
82  return it->second;
83  }
84 
85  bool ret = wxRichMessageDialog::Show( aShow );
86 
87  // Has the user asked not to show the dialog again
88  if( IsCheckBoxChecked() )
90 
91  return ret;
92 }
93 
94 
96 {
97  // Check if this dialog should be shown to the user
98  auto it = doNotShowAgainDlgs.find( m_hash );
99 
100  if( it != doNotShowAgainDlgs.end() )
101  return it->second;
102 
103  int ret = wxRichMessageDialog::ShowModal();
104 
105  // Has the user asked not to show the dialog again
106  if( IsCheckBoxChecked() )
107  doNotShowAgainDlgs[m_hash] = ret;
108 
109  return ret;
110 }
111 
112 
113 wxString KIDIALOG::getCaption( KD_TYPE aType, const wxString& aCaption )
114 {
115  if( !aCaption.IsEmpty() )
116  return aCaption;
117 
118  switch( aType )
119  {
120  case KD_NONE: /* fall through */
121  case KD_INFO: return _( "Message" );
122  case KD_QUESTION: return _( "Question" );
123  case KD_WARNING: return _( "Warning" );
124  case KD_ERROR: return _( "Error" );
125  }
126 
127  return wxEmptyString;
128 }
129 
130 
132 {
133  long style = wxOK | wxCENTRE | wxSTAY_ON_TOP;
134 
135  switch( aType )
136  {
137  case KD_NONE: break;
138  case KD_INFO: style |= wxICON_INFORMATION; break;
139  case KD_QUESTION: style |= wxICON_QUESTION; break;
140  case KD_WARNING: style |= wxICON_WARNING; break;
141  case KD_ERROR: style |= wxICON_ERROR; break;
142  }
143 
144  return style;
145 }
146 
147 
148 int UnsavedChangesDialog( wxWindow* parent, wxString aMessage, bool* aApplyToAll )
149 {
150  static bool s_apply_to_all = false;
151 
152  wxRichMessageDialog dlg( parent, aMessage, wxEmptyString,
153  wxYES_NO | wxCANCEL | wxYES_DEFAULT | wxICON_WARNING | wxCENTER );
154  dlg.SetExtendedMessage( _( "If you don't save, all your changes will be permanently lost." ) );
155  dlg.SetYesNoLabels( _( "Save" ), _( "Discard Changes" ) );
156 
157  if( aApplyToAll )
158  dlg.ShowCheckBox( _( "Apply to all" ), s_apply_to_all );
159 
160  int ret = dlg.ShowModal();
161 
162  if( aApplyToAll )
163  {
164  *aApplyToAll = dlg.IsCheckBoxChecked();
165  s_apply_to_all = dlg.IsCheckBoxChecked();
166  }
167 
168  // Returns wxID_YES, wxID_NO, or wxID_CANCEL
169  return ret;
170 }
171 
172 
173 int UnsavedChangesDialog( wxWindow* parent, const wxString& aMessage )
174 {
175 #ifdef __APPLE__
176  // wxWidgets gets the button order wrong on Mac so use the other dialog.
177  return UnsavedChangesDialog( parent, aMessage, nullptr );
178 #else
179  wxMessageDialog dlg( parent, aMessage, wxEmptyString,
180  wxYES_NO | wxCANCEL | wxYES_DEFAULT | wxICON_WARNING | wxCENTER );
181  dlg.SetExtendedMessage( _( "If you don't save, all your changes will be permanently lost." ) );
182  dlg.SetYesNoLabels( _( "Save" ), _( "Discard Changes" ) );
183 
184  // Returns wxID_YES, wxID_NO, or wxID_CANCEL
185  return dlg.ShowModal();
186 #endif
187 }
188 
189 
190 bool ConfirmRevertDialog( wxWindow* parent, const wxString& aMessage )
191 {
192  wxMessageDialog dlg( parent, aMessage, wxEmptyString,
193  wxOK | wxCANCEL | wxOK_DEFAULT | wxICON_WARNING | wxCENTER );
194  dlg.SetExtendedMessage( _( "Your current changes will be permanently lost." ) );
195  dlg.SetOKCancelLabels( _( "Revert" ), _( "Cancel" ) );
196 
197  return dlg.ShowModal() == wxID_OK;
198 }
199 
200 
201 bool HandleUnsavedChanges( wxWindow* aParent, const wxString& aMessage,
202  const std::function<bool()>& aSaveFunction )
203 {
204  switch( UnsavedChangesDialog( aParent, aMessage ) )
205  {
206  case wxID_YES: return aSaveFunction();
207  case wxID_NO: return true;
208  default:
209  case wxID_CANCEL: return false;
210  }
211 }
212 
213 
214 int OKOrCancelDialog( wxWindow* aParent, const wxString& aWarning, const wxString& aMessage,
215  const wxString& aOKLabel, const wxString& aCancelLabel, bool* aApplyToAll )
216 {
217  wxRichMessageDialog dlg( aParent, aMessage, wxEmptyString,
218  wxOK | wxCANCEL | wxOK_DEFAULT | wxICON_WARNING | wxCENTER );
219  dlg.ShowDetailedText( _( "If you don't save, all your changes will be permanently lost." ) );
220  dlg.SetOKCancelLabels( aOKLabel, aCancelLabel );
221 
222  if( aApplyToAll )
223  dlg.ShowCheckBox( _( "Apply to all" ), true );
224 
225  int ret = dlg.ShowModal();
226 
227  if( aApplyToAll )
228  *aApplyToAll = dlg.IsCheckBoxChecked();
229 
230  // Returns wxID_OK or wxID_CANCEL
231  return ret;
232 }
233 
234 
235 // DisplayError should be deprecated, use DisplayErrorMessage instead
236 void DisplayError( wxWindow* aParent, const wxString& aText, int aDisplayTime )
237 {
238  wxMessageDialog* dlg;
239  int icon = aDisplayTime > 0 ? wxICON_INFORMATION : wxICON_ERROR;
240 
241  dlg = new wxMessageDialog( aParent, aText, _( "Warning" ),
242  wxOK | wxCENTRE | wxRESIZE_BORDER | icon | wxSTAY_ON_TOP );
243 
244  dlg->ShowModal();
245  dlg->Destroy();
246 }
247 
248 
249 void DisplayErrorMessage( wxWindow* aParent, const wxString& aText, const wxString& aExtraInfo )
250 {
251  wxRichMessageDialog* dlg;
252  int icon = wxICON_ERROR;
253 
254  dlg = new wxRichMessageDialog( aParent, aText, _( "Error" ),
255  wxOK | wxCENTRE | wxRESIZE_BORDER | icon | wxSTAY_ON_TOP );
256 
257  if( !aExtraInfo.IsEmpty() )
258  dlg->ShowDetailedText( aExtraInfo );
259 
260  dlg->ShowModal();
261  dlg->Destroy();
262 }
263 
264 
265 void DisplayInfoMessage( wxWindow* aParent, const wxString& aMessage, const wxString& aExtraInfo )
266 {
267  wxRichMessageDialog* dlg;
268  int icon = wxICON_INFORMATION;
269 
270  dlg = new wxRichMessageDialog( aParent, aMessage, _( "Info" ),
271  wxOK | wxCENTRE | wxRESIZE_BORDER | icon | wxSTAY_ON_TOP );
272 
273  if( !aExtraInfo.IsEmpty() )
274  dlg->ShowDetailedText( aExtraInfo );
275 
276  dlg->ShowModal();
277  dlg->Destroy();
278 }
279 
280 
281 bool IsOK( wxWindow* aParent, const wxString& aMessage )
282 {
283  wxMessageDialog dlg( aParent, aMessage, _( "Confirmation" ),
284  wxYES_NO | wxCENTRE | wxICON_QUESTION | wxSTAY_ON_TOP );
285  dlg.SetEscapeId( wxID_NO );
286 
287  return dlg.ShowModal() == wxID_YES;
288 }
289 
290 
291 int SelectSingleOption( wxWindow* aParent, const wxString& aTitle,
292  const wxString& aMessage, const wxArrayString& aOptions )
293 {
294  wxSingleChoiceDialog dlg( aParent, aMessage, aTitle, aOptions );
295 
296  if( dlg.ShowModal() != wxID_OK )
297  return -1;
298 
299  return dlg.GetSelection();
300 }
301 
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:236
bool HandleUnsavedChanges(wxWindow *aParent, const wxString &aMessage, const std::function< bool()> &aSaveFunction)
Display a dialog with Save, Cancel and Discard Changes buttons.
Definition: confirm.cpp:201
void DoNotShowCheckbox(wxString file, int line)
Shows the 'do not show again' checkbox
Definition: confirm.cpp:53
bool ConfirmRevertDialog(wxWindow *parent, const wxString &aMessage)
Display a confirmation dialog for a revert action.
Definition: confirm.cpp:190
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition: confirm.cpp:249
This file is part of the common library.
KD_TYPE
Dialog type. Selects appropriate icon and default dialog title
Definition: confirm.h:48
int OKOrCancelDialog(wxWindow *aParent, const wxString &aWarning, const wxString &aMessage, const wxString &aOKLabel, const wxString &aCancelLabel, bool *aApplyToAll)
Displays a warning dialog with aMessage and returns the user response.
Definition: confirm.cpp:214
static std::unordered_map< unsigned long, int > doNotShowAgainDlgs
Definition: confirm.cpp:34
static wxString getCaption(KD_TYPE aType, const wxString &aCaption)
Definition: confirm.cpp:113
Subclass of DIALOG_DISPLAY_HTML_TEXT_BASE, which is generated by wxFormBuilder.
bool Show(bool aShow=true) override
Definition: confirm.cpp:73
static long getStyle(KD_TYPE aType)
Definition: confirm.cpp:131
void ForceShowAgain()
Definition: confirm.cpp:67
int UnsavedChangesDialog(wxWindow *parent, wxString aMessage, bool *aApplyToAll)
A specialized version of HandleUnsavedChanges which handles an apply-to-all checkbox.
Definition: confirm.cpp:148
#define _(s)
bool DoNotShowAgain() const
Checks the 'do not show again' setting for the dialog
Definition: confirm.cpp:61
KIDIALOG(wxWindow *aParent, const wxString &aMessage, const wxString &aCaption, long aStyle=wxOK)
Definition: confirm.cpp:37
int ShowModal() override
Definition: confirm.cpp:95
int SelectSingleOption(wxWindow *aParent, const wxString &aTitle, const wxString &aMessage, const wxArrayString &aOptions)
Displays a dialog with radioboxes asking the user to select an option.
Definition: confirm.cpp:291
void DisplayInfoMessage(wxWindow *aParent, const wxString &aMessage, const wxString &aExtraInfo)
Display an informational message box with aMessage.
Definition: confirm.cpp:265
unsigned long m_hash
Unique identifier of the dialog
Definition: confirm.h:67
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition: confirm.cpp:281