KiCad PCB EDA Suite
Loading...
Searching...
No Matches
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 The 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, see <https://www.gnu.org/licenses/>.
19 */
20
21#include <confirm.h>
22
23#include <functional>
24#include <wx/app.h>
25#include <wx/stockitem.h>
26#include <wx/richmsgdlg.h>
27#include <wx/msgdlg.h>
28#include <wx/choicdlg.h>
29#include <wx/crt.h>
35static const wxChar traceConfirm[] = wxT( "KICAD_CONFIRM" );
36
37
38bool AskOverrideLock( wxWindow* aParent, const wxString& aMessage )
39{
40#ifdef __APPLE__
41 // wxMessageDialog gets the button spacing wrong on Mac so we have to use wxRichMessageDialog.
42 // Note that its warning icon is more like wxMessageDialog's error icon, so we use it instead
43 // of wxICON_ERROR.
44 wxRichMessageDialog dlg( aParent, aMessage, _( "File Open Warning" ),
45 wxYES_NO | wxICON_WARNING | wxCENTER );
46 dlg.SetExtendedMessage( _( "Interleaved saves may produce very unexpected results." )
47 + wxS( "\n" ) );
48 dlg.SetYesNoLabels( _( "&Cancel" ), _( "&Open Anyway" ) );
49#else
50 KICAD_MESSAGE_DIALOG_BASE dlg( aParent, aMessage, _( "File Open Warning" ),
51 wxYES_NO | wxICON_ERROR | wxCENTER );
52 dlg.SetExtendedMessage( _( "Interleaved saves may produce very unexpected results." ) );
53 dlg.SetYesNoLabels( _( "&Cancel" ), _( "&Open Anyway" ) );
54#endif
55
56 return dlg.ShowModal() == wxID_NO;
57}
58
59
60int UnsavedChangesDialog( wxWindow* parent, const wxString& aMessage, bool* aApplyToAll )
61{
62 static bool s_apply_to_all = false;
63
64 KICAD_RICH_MESSAGE_DIALOG_BASE dlg( parent, aMessage, _( "Save Changes?" ),
65 wxYES_NO | wxCANCEL |
66 wxYES_DEFAULT | wxICON_WARNING | wxCENTER );
67 dlg.SetExtendedMessage( _( "If you don't save, all your changes will be permanently lost." )
68 + wxS( "\n" ) );
69 dlg.SetYesNoLabels( _( "&Save" ), _( "&Discard Changes" ) );
70
71 if( aApplyToAll )
72 dlg.ShowCheckBox( _( "&Apply to all" ), s_apply_to_all );
73
74 int ret = dlg.ShowModal();
75
76 if( aApplyToAll )
77 {
78 *aApplyToAll = dlg.IsCheckBoxChecked();
79 s_apply_to_all = dlg.IsCheckBoxChecked();
80 }
81
82 // Returns wxID_YES, wxID_NO, or wxID_CANCEL
83 return ret;
84}
85
86
87int UnsavedChangesDialog( wxWindow* parent, const wxString& aMessage )
88{
89#ifdef __APPLE__
90 // wxMessageDialog gets the button order (and spacing) wrong on Mac so we have to use
91 // wxRichMessageDialog.
92 return UnsavedChangesDialog( parent, aMessage, nullptr );
93#else
94 int ret = wxID_CANCEL;
95
96 {
97 // Scoped so wxWindowDisabler and dlg are destroyed before we re-raise the parent
98#ifdef _WIN32
99 // wxMessageDialog on windows invokes TaskDialogIndirect which is a native function for a
100 // dialog. As a result it skips wxWidgets for modal management...and we don't parent frames
101 // properly among other things for Windows to do the right thing by default.
102 // Disable all the windows manually to avoid being able to hit this dialog from the tool
103 // frame and kicad frame at the same time.
104 wxWindowDisabler disable( true );
105#endif
106
107 KICAD_MESSAGE_DIALOG_BASE dlg( parent, aMessage, _( "Save Changes?" ),
108 wxYES_NO | wxCANCEL | wxYES_DEFAULT | wxICON_WARNING | wxCENTER );
109 dlg.SetExtendedMessage( _( "If you don't save, all your changes will be permanently lost." ) );
110 dlg.SetYesNoLabels( _( "&Save" ), _( "&Discard Changes" ) );
111
112 // Returns wxID_YES, wxID_NO, or wxID_CANCEL
113 ret = dlg.ShowModal();
114 }
115
116#ifdef _WIN32
117 // Counterpart to wxWindowDisabler above. After it re-enables all windows, the OS must
118 // choose which to activate and may pick an unrelated application. Raise and focus the
119 // parent explicitly so the user isn't left in another window.
120 if( parent )
121 {
122 parent->Raise();
123 wxSafeYield();
124 parent->SetFocus();
125 }
126#endif
127
128 return ret;
129#endif
130}
131
132
133bool ConfirmRevertDialog( wxWindow* parent, const wxString& aMessage )
134{
135 KICAD_MESSAGE_DIALOG_BASE dlg( parent, aMessage, wxEmptyString,
136 wxOK | wxCANCEL | wxOK_DEFAULT | wxICON_WARNING | wxCENTER );
137 dlg.SetExtendedMessage( _( "Your current changes will be permanently lost." ) );
138 dlg.SetOKCancelLabels( _( "&Revert" ), _( "&Cancel" ) );
139
140 return dlg.ShowModal() == wxID_OK;
141}
142
143
145
146bool HandleUnsavedChanges( wxWindow* aParent, const wxString& aMessage,
147 const std::function<bool()>& aSaveFunction )
148{
151 {
152 case wxID_YES: return aSaveFunction();
153 case wxID_NO: return true; // proceed without saving
154 default:
155 case wxID_CANCEL: return false;
156 }
157}
158
163
164
165int OKOrCancelDialog( wxWindow* aParent, const wxString& aWarning, const wxString& aMessage,
166 const wxString& aDetailedMessage, const wxString& aOKLabel,
167 const wxString& aCancelLabel, bool* aApplyToAll )
168{
169 KICAD_RICH_MESSAGE_DIALOG_BASE dlg( aParent, aMessage, aWarning,
170 wxOK | wxCANCEL | wxOK_DEFAULT | wxICON_WARNING | wxCENTER );
171
172 dlg.SetOKCancelLabels( ( aOKLabel.IsEmpty() ) ? _( "&OK" ) : aOKLabel,
173 ( aCancelLabel.IsEmpty() ) ? _( "&Cancel" ) : aCancelLabel );
174
175 if( !aDetailedMessage.IsEmpty() )
176 dlg.SetExtendedMessage( aDetailedMessage );
177
178 if( aApplyToAll )
179 dlg.ShowCheckBox( _( "&Apply to all" ), true );
180
181 int ret = dlg.ShowModal();
182
183 if( aApplyToAll )
184 *aApplyToAll = dlg.IsCheckBoxChecked();
185
186 // Returns wxID_OK or wxID_CANCEL
187 return ret;
188}
189
190
191// DisplayError should be deprecated, use DisplayErrorMessage instead
192void DisplayError( wxWindow* aParent, const wxString& aText )
193{
194 if( !wxTheApp || !wxTheApp->IsMainLoopRunning() )
195 {
196 wxLogError( "%s", aText );
197 return;
198 }
199
200 if( !wxTheApp->IsGUI() )
201 {
202 wxFprintf( stderr, aText );
203 return;
204 }
205
207
208 dlg = new KICAD_MESSAGE_DIALOG_BASE( aParent, aText, _( "Error" ),
209 wxOK | wxCENTRE | wxRESIZE_BORDER |
210 wxICON_ERROR | wxSTAY_ON_TOP );
211
212 dlg->ShowModal();
213 dlg->Destroy();
214}
215
216
217void DisplayErrorMessage( wxWindow* aParent, const wxString& aText, const wxString& aExtraInfo )
218{
219 if( !wxTheApp || !wxTheApp->IsMainLoopRunning() )
220 {
221 wxLogError( "%s %s", aText, aExtraInfo );
222 return;
223 }
224
225 if( !wxTheApp->IsGUI() )
226 {
227 wxFprintf( stderr, aText );
228 return;
229 }
230
232
233 dlg = new KICAD_MESSAGE_DIALOG_BASE( aParent, aText, _( "Error" ),
234 wxOK | wxCENTRE | wxRESIZE_BORDER |
235 wxICON_ERROR | wxSTAY_ON_TOP );
236
237 if( !aExtraInfo.IsEmpty() )
238 dlg->SetExtendedMessage( aExtraInfo );
239
240 dlg->ShowModal();
241 dlg->Destroy();
242}
243
244
245void DisplayInfoMessage( wxWindow* aParent, const wxString& aMessage, const wxString& aExtraInfo )
246{
247 if( !wxTheApp || !wxTheApp->GetTopWindow() )
248 {
249 wxLogTrace( traceConfirm, wxS( "%s %s" ), aMessage, aExtraInfo );
250 return;
251 }
252
253 if( !wxTheApp->IsGUI() )
254 {
255 wxFprintf( stdout, "%s %s", aMessage, aExtraInfo );
256 return;
257 }
258
260 int icon = wxICON_INFORMATION;
261
262 dlg = new KICAD_MESSAGE_DIALOG_BASE( aParent, aMessage, _( "Information" ),
263 wxOK | wxCENTRE | wxRESIZE_BORDER |
264 icon | wxSTAY_ON_TOP );
265
266 if( !aExtraInfo.IsEmpty() )
267 dlg->SetExtendedMessage( aExtraInfo );
268
269 dlg->ShowModal();
270 dlg->Destroy();
271}
272
273
274bool IsOK( wxWindow* aParent, const wxString& aMessage )
275{
276 // wxMessageDialog no longer responds correctly to the <ESC> key (on at least OSX and MSW)
277 // so we're now using wxRichMessageDialog.
278 //
279 // Note also that we have to repurpose an OK/Cancel version of it because otherwise wxWidgets
280 // uses "destructive" spacing for the "No" button.
281
282#ifdef __APPLE__
283 // Why is wxICON_QUESTION a light-bulb on Mac? That has more of a hint or info connotation.
284 int icon = wxICON_WARNING;
285#else
286 int icon = wxICON_QUESTION;
287#endif
288
289 KICAD_MESSAGE_DIALOG dlg( aParent, aMessage, _( "Confirmation" ),
290 wxOK | wxCANCEL | wxOK_DEFAULT |
291 wxCENTRE | icon | wxSTAY_ON_TOP );
292
293 dlg.SetOKCancelLabels( _( "&Yes" ), _( "&No" ) );
294
295 return dlg.ShowModal() == wxID_OK;
296}
297
298
299int SelectSingleOption( wxWindow* aParent, const wxString& aTitle,
300 const wxString& aMessage, const wxArrayString& aOptions )
301{
302 wxSingleChoiceDialog dlg( aParent, aMessage, aTitle, aOptions );
303
304 if( dlg.ShowModal() != wxID_OK )
305 return -1;
306
307 return dlg.GetSelection();
308}
309
bool AskOverrideLock(wxWindow *aParent, const wxString &aMessage)
Display a dialog indicating the file is already open, with an option to reset the lock.
Definition confirm.cpp:38
int SelectSingleOption(wxWindow *aParent, const wxString &aTitle, const wxString &aMessage, const wxArrayString &aOptions)
Display a dialog with radioboxes asking the user to select an option.
Definition confirm.cpp:299
int OKOrCancelDialog(wxWindow *aParent, const wxString &aWarning, const wxString &aMessage, const wxString &aDetailedMessage, const wxString &aOKLabel, const wxString &aCancelLabel, bool *aApplyToAll)
Display a warning dialog with aMessage and returns the user response.
Definition confirm.cpp:165
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition confirm.cpp:274
void DisplayInfoMessage(wxWindow *aParent, const wxString &aMessage, const wxString &aExtraInfo)
Display an informational message box with aMessage.
Definition confirm.cpp:245
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:146
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition confirm.cpp:217
int UnsavedChangesDialog(wxWindow *parent, const wxString &aMessage, bool *aApplyToAll)
A specialized version of HandleUnsavedChanges which handles an apply-to-all checkbox.
Definition confirm.cpp:60
bool ConfirmRevertDialog(wxWindow *parent, const wxString &aMessage)
Display a confirmation dialog for a revert action.
Definition confirm.cpp:133
static int g_lastUnsavedChangesResult
Definition confirm.cpp:144
int GetLastUnsavedChangesResponse()
Return the result code from the last call to HandleUnsavedChanges(): wxID_YES, wxID_NO or wxID_CANCEL...
Definition confirm.cpp:159
void DisplayError(wxWindow *aParent, const wxString &aText)
Display an error or warning message box with aMessage.
Definition confirm.cpp:192
This file is part of the common library.
#define KICAD_RICH_MESSAGE_DIALOG_BASE
Definition confirm.h:47
#define KICAD_MESSAGE_DIALOG
Definition confirm.h:48
#define KICAD_MESSAGE_DIALOG_BASE
Definition confirm.h:46
#define _(s)
static const wxChar traceConfirm[]
Flag to enable confirmation dialog debugging output.
Definition confirm.cpp:35