Fix button order and genralize Exit dialog so it can be shared more.

This also fixes a bunch of bugs where an error during save would
still close the window (rather than cancelling the close action).

Fixes: lp:1785034
* https://bugs.launchpad.net/kicad/+bug/1785034
This commit is contained in:
Jeff Young 2018-08-02 00:06:12 +01:00
parent c655bffac1
commit d8d4f75fa1
18 changed files with 385 additions and 390 deletions

View File

@ -156,18 +156,20 @@ long KIDIALOG::getStyle( KD_TYPE aType )
class DIALOG_EXIT: public DIALOG_EXIT_BASE class DIALOG_EXIT: public DIALOG_EXIT_BASE
{ {
public: public:
DIALOG_EXIT( wxWindow *aParent, const wxString& aMessage ) : DIALOG_EXIT( wxWindow *aParent, const wxString& aWarning, const wxString& aMessage,
const wxString& aOKLabel, const wxString& aCancelLabel ) :
DIALOG_EXIT_BASE( aParent ) DIALOG_EXIT_BASE( aParent )
{ {
m_bitmap->SetBitmap( KiBitmap( dialog_warning_xpm ) ); m_bitmap->SetBitmap( KiBitmap( dialog_warning_xpm ) );
m_TextInfo->SetLabel( aWarning );
m_staticText2->SetLabel( aMessage );
if( !aMessage.IsEmpty() ) // Caller must eanble these if desired
m_TextInfo->SetLabel( aMessage ); m_ApplyToAllOpt->Show( false );
m_DiscardButton->Show( false );
m_ApplyToAllOpt->Show( false ); // Caller must enable this m_sdbSizer1OK->SetLabel( aOKLabel );
m_sdbSizer1Cancel->SetLabel( aCancelLabel );
m_sdbSizer1OK->SetLabel( _( "Save and Exit" ) );
m_sdbSizer1Apply->SetLabel( _( "Discard Changes" ) );
m_sdbSizer1OK->SetDefault(); m_sdbSizer1OK->SetDefault();
m_sdbSizer1->Layout(); m_sdbSizer1->Layout();
@ -177,14 +179,36 @@ public:
}; };
private: private:
void OnSaveAndExit( wxCommandEvent& event ) override { EndModal( wxID_YES ); } void OnSave( wxCommandEvent& event ) override { EndModal( wxID_YES ); }
void OnExitNoSave( wxCommandEvent& event ) override { EndModal( wxID_NO ); } void OnDiscard( wxCommandEvent& event ) override { EndModal( wxID_NO ); }
}; };
int DisplayExitDialog( wxWindow* parent, const wxString& aMessage, bool* aApplyToAll ) int UnsavedChangesDialog( wxWindow* parent, const wxString& aMessage, bool* aApplyToAll )
{ {
DIALOG_EXIT dlg( parent, aMessage ); DIALOG_EXIT dlg( parent, aMessage,
_( "If you don't save, all your changes will be permanently lost." ),
_( "Save" ), _( "Cancel" ) );
if( aApplyToAll )
dlg.m_ApplyToAllOpt->Show( true );
dlg.m_DiscardButton->Show( true );
int ret = dlg.ShowModal();
if( aApplyToAll )
*aApplyToAll = dlg.m_ApplyToAllOpt->GetValue();
// Returns wxID_YES, wxID_NO, or wxID_CANCEL
return ret;
}
int YesOrCancelDialog( wxWindow* aParent, const wxString& aWarning, const wxString& aMessage,
const wxString& aOKLabel, const wxString& aCancelLabel, bool* aApplyToAll )
{
DIALOG_EXIT dlg( aParent, aWarning, aMessage, aOKLabel, aCancelLabel );
if( aApplyToAll ) if( aApplyToAll )
dlg.m_ApplyToAllOpt->Show( true ); dlg.m_ApplyToAllOpt->Show( true );
@ -257,48 +281,6 @@ bool IsOK( wxWindow* aParent, const wxString& aMessage )
} }
class DIALOG_YES_NO_CANCEL : public DIALOG_EXIT
{
public:
DIALOG_YES_NO_CANCEL( wxWindow *aParent,
const wxString& aPrimaryMessage,
const wxString& aSecondaryMessage = wxEmptyString,
const wxString& aYesButtonText = wxEmptyString,
const wxString& aNoButtonText = wxEmptyString,
const wxString& aCancelButtonText = wxEmptyString ) :
DIALOG_EXIT( aParent, aPrimaryMessage )
{
if( aSecondaryMessage.IsEmpty() )
m_staticText2->Hide();
else
m_staticText2->SetLabel( aSecondaryMessage );
m_sdbSizer1OK->SetLabel( aYesButtonText.IsEmpty() ? wxGetStockLabel( wxID_YES ) :
aYesButtonText );
m_sdbSizer1Apply->SetLabel( aNoButtonText.IsEmpty() ? wxGetStockLabel( wxID_NO ) :
aNoButtonText );
m_sdbSizer1Cancel->SetLabel( aCancelButtonText.IsEmpty() ? wxGetStockLabel( wxID_CANCEL ) :
aCancelButtonText );
GetSizer()->Fit( this );
GetSizer()->SetSizeHints( this );
};
};
int YesNoCancelDialog( wxWindow* aParent,
const wxString& aPrimaryMessage,
const wxString& aSecondaryMessage,
const wxString& aYesButtonText,
const wxString& aNoButtonText,
const wxString& aCancelButtonText )
{
DIALOG_YES_NO_CANCEL dlg( aParent, aPrimaryMessage, aSecondaryMessage,
aYesButtonText, aNoButtonText, aCancelButtonText );
return dlg.ShowModal();
}
int SelectSingleOption( wxWindow* aParent, const wxString& aTitle, const wxString& aMessage, const wxArrayString& aOptions ) int SelectSingleOption( wxWindow* aParent, const wxString& aTitle, const wxString& aMessage, const wxArrayString& aOptions )
{ {
wxSingleChoiceDialog dlg( aParent, aMessage, aTitle, aOptions ); wxSingleChoiceDialog dlg( aParent, aMessage, aTitle, aOptions );

View File

@ -19,19 +19,13 @@ DIALOG_EXIT_BASE::DIALOG_EXIT_BASE( wxWindow* parent, wxWindowID id, const wxStr
wxBoxSizer* bSizerUpper; wxBoxSizer* bSizerUpper;
bSizerUpper = new wxBoxSizer( wxHORIZONTAL ); bSizerUpper = new wxBoxSizer( wxHORIZONTAL );
wxBoxSizer* bSizerBitmap;
bSizerBitmap = new wxBoxSizer( wxVERTICAL );
m_bitmap = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); m_bitmap = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 );
bSizerBitmap->Add( m_bitmap, 0, wxALL, 5 ); bSizerUpper->Add( m_bitmap, 0, wxALL, 5 );
bSizerUpper->Add( bSizerBitmap, 0, 0, 5 );
wxBoxSizer* bSizerMessages; wxBoxSizer* bSizerMessages;
bSizerMessages = new wxBoxSizer( wxVERTICAL ); bSizerMessages = new wxBoxSizer( wxVERTICAL );
m_TextInfo = new wxStaticText( this, wxID_ANY, _("Save the changes before closing?"), wxDefaultPosition, wxDefaultSize, 0 ); m_TextInfo = new wxStaticText( this, wxID_ANY, _("Save changes?"), wxDefaultPosition, wxDefaultSize, 0 );
m_TextInfo->Wrap( -1 ); m_TextInfo->Wrap( -1 );
m_TextInfo->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) ); m_TextInfo->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) );
@ -54,18 +48,25 @@ DIALOG_EXIT_BASE::DIALOG_EXIT_BASE( wxWindow* parent, wxWindowID id, const wxStr
m_buttonSizer->SetMinSize( wxSize( 475,-1 ) ); m_buttonSizer->SetMinSize( wxSize( 475,-1 ) );
m_ApplyToAllOpt = new wxCheckBox( this, wxID_ANY, _("Apply to all"), wxDefaultPosition, wxDefaultSize, 0 ); m_ApplyToAllOpt = new wxCheckBox( this, wxID_ANY, _("Apply to all"), wxDefaultPosition, wxDefaultSize, 0 );
m_buttonSizer->Add( m_ApplyToAllOpt, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 20 ); m_buttonSizer->Add( m_ApplyToAllOpt, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM, 5 );
m_buttonSizer->Add( 0, 0, 1, wxRIGHT|wxLEFT, 10 );
m_DiscardButton = new wxButton( this, wxID_ANY, _("Discard Changes"), wxDefaultPosition, wxDefaultSize, 0 );
m_buttonSizer->Add( m_DiscardButton, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
m_buttonSizer->Add( 0, 0, 0, wxRIGHT|wxLEFT, 5 );
m_sdbSizer1 = new wxStdDialogButtonSizer(); m_sdbSizer1 = new wxStdDialogButtonSizer();
m_sdbSizer1OK = new wxButton( this, wxID_OK ); m_sdbSizer1OK = new wxButton( this, wxID_OK );
m_sdbSizer1->AddButton( m_sdbSizer1OK ); m_sdbSizer1->AddButton( m_sdbSizer1OK );
m_sdbSizer1Apply = new wxButton( this, wxID_APPLY );
m_sdbSizer1->AddButton( m_sdbSizer1Apply );
m_sdbSizer1Cancel = new wxButton( this, wxID_CANCEL ); m_sdbSizer1Cancel = new wxButton( this, wxID_CANCEL );
m_sdbSizer1->AddButton( m_sdbSizer1Cancel ); m_sdbSizer1->AddButton( m_sdbSizer1Cancel );
m_sdbSizer1->Realize(); m_sdbSizer1->Realize();
m_buttonSizer->Add( m_sdbSizer1, 1, wxEXPAND|wxALL, 5 ); m_buttonSizer->Add( m_sdbSizer1, 0, wxALL, 5 );
bSizerMain->Add( m_buttonSizer, 0, wxEXPAND|wxLEFT, 10 ); bSizerMain->Add( m_buttonSizer, 0, wxEXPAND|wxLEFT, 10 );
@ -78,14 +79,14 @@ DIALOG_EXIT_BASE::DIALOG_EXIT_BASE( wxWindow* parent, wxWindowID id, const wxStr
this->Centre( wxBOTH ); this->Centre( wxBOTH );
// Connect Events // Connect Events
m_sdbSizer1Apply->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_EXIT_BASE::OnExitNoSave ), NULL, this ); m_DiscardButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_EXIT_BASE::OnDiscard ), NULL, this );
m_sdbSizer1OK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_EXIT_BASE::OnSaveAndExit ), NULL, this ); m_sdbSizer1OK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_EXIT_BASE::OnSave ), NULL, this );
} }
DIALOG_EXIT_BASE::~DIALOG_EXIT_BASE() DIALOG_EXIT_BASE::~DIALOG_EXIT_BASE()
{ {
// Disconnect Events // Disconnect Events
m_sdbSizer1Apply->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_EXIT_BASE::OnExitNoSave ), NULL, this ); m_DiscardButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_EXIT_BASE::OnDiscard ), NULL, this );
m_sdbSizer1OK->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_EXIT_BASE::OnSaveAndExit ), NULL, this ); m_sdbSizer1OK->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_EXIT_BASE::OnSave ), NULL, this );
} }

View File

@ -104,94 +104,83 @@
<property name="permission">none</property> <property name="permission">none</property>
<object class="sizeritem" expanded="1"> <object class="sizeritem" expanded="1">
<property name="border">5</property> <property name="border">5</property>
<property name="flag"></property> <property name="flag">wxALL</property>
<property name="proportion">0</property> <property name="proportion">0</property>
<object class="wxBoxSizer" expanded="1"> <object class="wxStaticBitmap" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="bitmap">Load From File; </property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property> <property name="minimum_size"></property>
<property name="name">bSizerBitmap</property> <property name="moveable">1</property>
<property name="orient">wxVERTICAL</property> <property name="name">m_bitmap</property>
<property name="permission">none</property> <property name="pane_border">1</property>
<object class="sizeritem" expanded="1"> <property name="pane_position"></property>
<property name="border">5</property> <property name="pane_size"></property>
<property name="flag">wxALL</property> <property name="permission">protected</property>
<property name="proportion">0</property> <property name="pin_button">1</property>
<object class="wxStaticBitmap" expanded="1"> <property name="pos"></property>
<property name="BottomDockable">1</property> <property name="resize">Resizable</property>
<property name="LeftDockable">1</property> <property name="show">1</property>
<property name="RightDockable">1</property> <property name="size"></property>
<property name="TopDockable">1</property> <property name="subclass"></property>
<property name="aui_layer"></property> <property name="toolbar_pane">0</property>
<property name="aui_name"></property> <property name="tooltip"></property>
<property name="aui_position"></property> <property name="window_extra_style"></property>
<property name="aui_row"></property> <property name="window_name"></property>
<property name="best_size"></property> <property name="window_style"></property>
<property name="bg"></property> <event name="OnChar"></event>
<property name="bitmap">Load From File; </property> <event name="OnEnterWindow"></event>
<property name="caption"></property> <event name="OnEraseBackground"></event>
<property name="caption_visible">1</property> <event name="OnKeyDown"></event>
<property name="center_pane">0</property> <event name="OnKeyUp"></event>
<property name="close_button">1</property> <event name="OnKillFocus"></event>
<property name="context_help"></property> <event name="OnLeaveWindow"></event>
<property name="context_menu">1</property> <event name="OnLeftDClick"></event>
<property name="default_pane">0</property> <event name="OnLeftDown"></event>
<property name="dock">Dock</property> <event name="OnLeftUp"></event>
<property name="dock_fixed">0</property> <event name="OnMiddleDClick"></event>
<property name="docking">Left</property> <event name="OnMiddleDown"></event>
<property name="enabled">1</property> <event name="OnMiddleUp"></event>
<property name="fg"></property> <event name="OnMotion"></event>
<property name="floatable">1</property> <event name="OnMouseEvents"></event>
<property name="font"></property> <event name="OnMouseWheel"></event>
<property name="gripper">0</property> <event name="OnPaint"></event>
<property name="hidden">0</property> <event name="OnRightDClick"></event>
<property name="id">wxID_ANY</property> <event name="OnRightDown"></event>
<property name="max_size"></property> <event name="OnRightUp"></event>
<property name="maximize_button">0</property> <event name="OnSetFocus"></event>
<property name="maximum_size"></property> <event name="OnSize"></event>
<property name="min_size"></property> <event name="OnUpdateUI"></event>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_bitmap</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="subclass"></property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnChar"></event>
<event name="OnEnterWindow"></event>
<event name="OnEraseBackground"></event>
<event name="OnKeyDown"></event>
<event name="OnKeyUp"></event>
<event name="OnKillFocus"></event>
<event name="OnLeaveWindow"></event>
<event name="OnLeftDClick"></event>
<event name="OnLeftDown"></event>
<event name="OnLeftUp"></event>
<event name="OnMiddleDClick"></event>
<event name="OnMiddleDown"></event>
<event name="OnMiddleUp"></event>
<event name="OnMotion"></event>
<event name="OnMouseEvents"></event>
<event name="OnMouseWheel"></event>
<event name="OnPaint"></event>
<event name="OnRightDClick"></event>
<event name="OnRightDown"></event>
<event name="OnRightUp"></event>
<event name="OnSetFocus"></event>
<event name="OnSize"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
</object> </object>
</object> </object>
<object class="sizeritem" expanded="1"> <object class="sizeritem" expanded="1">
@ -235,7 +224,7 @@
<property name="gripper">0</property> <property name="gripper">0</property>
<property name="hidden">0</property> <property name="hidden">0</property>
<property name="id">wxID_ANY</property> <property name="id">wxID_ANY</property>
<property name="label">Save the changes before closing?</property> <property name="label">Save changes?</property>
<property name="max_size"></property> <property name="max_size"></property>
<property name="maximize_button">0</property> <property name="maximize_button">0</property>
<property name="maximum_size"></property> <property name="maximum_size"></property>
@ -464,8 +453,8 @@
<property name="orient">wxHORIZONTAL</property> <property name="orient">wxHORIZONTAL</property>
<property name="permission">protected</property> <property name="permission">protected</property>
<object class="sizeritem" expanded="1"> <object class="sizeritem" expanded="1">
<property name="border">20</property> <property name="border">5</property>
<property name="flag">wxALIGN_CENTER_VERTICAL|wxRIGHT</property> <property name="flag">wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM</property>
<property name="proportion">0</property> <property name="proportion">0</property>
<object class="wxCheckBox" expanded="1"> <object class="wxCheckBox" expanded="1">
<property name="BottomDockable">1</property> <property name="BottomDockable">1</property>
@ -552,11 +541,119 @@
</object> </object>
</object> </object>
<object class="sizeritem" expanded="1"> <object class="sizeritem" expanded="1">
<property name="border">5</property> <property name="border">10</property>
<property name="flag">wxEXPAND|wxALL</property> <property name="flag">wxRIGHT|wxLEFT</property>
<property name="proportion">1</property> <property name="proportion">1</property>
<object class="spacer" expanded="1">
<property name="height">0</property>
<property name="permission">protected</property>
<property name="width">0</property>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxALIGN_CENTER_VERTICAL|wxALL</property>
<property name="proportion">0</property>
<object class="wxButton" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default">0</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Discard Changes</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_DiscardButton</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">public</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnButtonClick">OnDiscard</event>
<event name="OnChar"></event>
<event name="OnEnterWindow"></event>
<event name="OnEraseBackground"></event>
<event name="OnKeyDown"></event>
<event name="OnKeyUp"></event>
<event name="OnKillFocus"></event>
<event name="OnLeaveWindow"></event>
<event name="OnLeftDClick"></event>
<event name="OnLeftDown"></event>
<event name="OnLeftUp"></event>
<event name="OnMiddleDClick"></event>
<event name="OnMiddleDown"></event>
<event name="OnMiddleUp"></event>
<event name="OnMotion"></event>
<event name="OnMouseEvents"></event>
<event name="OnMouseWheel"></event>
<event name="OnPaint"></event>
<event name="OnRightDClick"></event>
<event name="OnRightDown"></event>
<event name="OnRightUp"></event>
<event name="OnSetFocus"></event>
<event name="OnSize"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxRIGHT|wxLEFT</property>
<property name="proportion">0</property>
<object class="spacer" expanded="1">
<property name="height">0</property>
<property name="permission">protected</property>
<property name="width">0</property>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxALL</property>
<property name="proportion">0</property>
<object class="wxStdDialogButtonSizer" expanded="1"> <object class="wxStdDialogButtonSizer" expanded="1">
<property name="Apply">1</property> <property name="Apply">0</property>
<property name="Cancel">1</property> <property name="Cancel">1</property>
<property name="ContextHelp">0</property> <property name="ContextHelp">0</property>
<property name="Help">0</property> <property name="Help">0</property>
@ -567,12 +664,12 @@
<property name="minimum_size"></property> <property name="minimum_size"></property>
<property name="name">m_sdbSizer1</property> <property name="name">m_sdbSizer1</property>
<property name="permission">protected</property> <property name="permission">protected</property>
<event name="OnApplyButtonClick">OnExitNoSave</event> <event name="OnApplyButtonClick"></event>
<event name="OnCancelButtonClick"></event> <event name="OnCancelButtonClick"></event>
<event name="OnContextHelpButtonClick"></event> <event name="OnContextHelpButtonClick"></event>
<event name="OnHelpButtonClick"></event> <event name="OnHelpButtonClick"></event>
<event name="OnNoButtonClick"></event> <event name="OnNoButtonClick"></event>
<event name="OnOKButtonClick">OnSaveAndExit</event> <event name="OnOKButtonClick">OnSave</event>
<event name="OnSaveButtonClick"></event> <event name="OnSaveButtonClick"></event>
<event name="OnYesButtonClick"></event> <event name="OnYesButtonClick"></event>
</object> </object>

View File

@ -21,8 +21,8 @@
#include <wx/colour.h> #include <wx/colour.h>
#include <wx/settings.h> #include <wx/settings.h>
#include <wx/string.h> #include <wx/string.h>
#include <wx/sizer.h>
#include <wx/stattext.h> #include <wx/stattext.h>
#include <wx/sizer.h>
#include <wx/statline.h> #include <wx/statline.h>
#include <wx/checkbox.h> #include <wx/checkbox.h>
#include <wx/button.h> #include <wx/button.h>
@ -46,16 +46,16 @@ class DIALOG_EXIT_BASE : public DIALOG_SHIM
wxBoxSizer* m_buttonSizer; wxBoxSizer* m_buttonSizer;
wxStdDialogButtonSizer* m_sdbSizer1; wxStdDialogButtonSizer* m_sdbSizer1;
wxButton* m_sdbSizer1OK; wxButton* m_sdbSizer1OK;
wxButton* m_sdbSizer1Apply;
wxButton* m_sdbSizer1Cancel; wxButton* m_sdbSizer1Cancel;
// Virtual event handlers, overide them in your derived class // Virtual event handlers, overide them in your derived class
virtual void OnExitNoSave( wxCommandEvent& event ) { event.Skip(); } virtual void OnDiscard( wxCommandEvent& event ) { event.Skip(); }
virtual void OnSaveAndExit( wxCommandEvent& event ) { event.Skip(); } virtual void OnSave( wxCommandEvent& event ) { event.Skip(); }
public: public:
wxCheckBox* m_ApplyToAllOpt; wxCheckBox* m_ApplyToAllOpt;
wxButton* m_DiscardButton;
DIALOG_EXIT_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); DIALOG_EXIT_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );
~DIALOG_EXIT_BASE(); ~DIALOG_EXIT_BASE();

View File

@ -271,10 +271,9 @@ void CVPCB_MAINFRAME::OnCloseWindow( wxCloseEvent& Event )
{ {
if( m_modified ) if( m_modified )
{ {
wxString msg = _( "Component to Footprint links modified.\nSave before exit?" ); wxString msg = _( "Symbol to Footprint links have been modified.\nSave before exit?" );
int ii = DisplayExitDialog( this, msg );
switch( ii ) switch( UnsavedChangesDialog( this, msg ) )
{ {
case wxID_CANCEL: case wxID_CANCEL:
Event.Veto(); Event.Veto();

View File

@ -138,8 +138,7 @@ std::string FormatProbeItem( EDA_ITEM* aItem, SCH_COMPONENT* aPart )
case SCH_FIELD_T: case SCH_FIELD_T:
case LIB_FIELD_T: case LIB_FIELD_T:
if( aPart ) if( aPart )
return StrPrintf( "$PART: %s", return StrPrintf( "$PART: %s", TO_UTF8( aPart->GetField( REFERENCE )->GetText() ) );
TO_UTF8( aPart->GetField( REFERENCE )->GetText() ) );
break; break;
case SCH_COMPONENT_T: case SCH_COMPONENT_T:
@ -233,10 +232,8 @@ void SCH_EDIT_FRAME::KiwayMailIn( KIWAY_EXPRESS& mail )
break; break;
case MAIL_SCH_PCB_UPDATE_REQUEST: case MAIL_SCH_PCB_UPDATE_REQUEST:
{
doUpdatePcb( payload ); doUpdatePcb( payload );
break; break;
}
case MAIL_BACKANNOTATE_FOOTPRINTS: case MAIL_BACKANNOTATE_FOOTPRINTS:
try try
@ -279,13 +276,8 @@ void SCH_EDIT_FRAME::KiwayMailIn( KIWAY_EXPRESS& mail )
break; break;
case MAIL_SCH_SAVE: case MAIL_SCH_SAVE:
{ if( SaveProject() )
wxCommandEvent dummyEvent;
OnSaveProject( dummyEvent );
if( !isAutoSaveRequired() ) // proxy for save completed
Kiway().ExpressMail( FRAME_CVPCB, MAIL_STATUS, _( "Schematic saved" ).ToStdString() ); Kiway().ExpressMail( FRAME_CVPCB, MAIL_STATUS, _( "Schematic saved" ).ToStdString() );
}
break; break;
default: default:

View File

@ -962,10 +962,7 @@ void DIALOG_FIELDS_EDITOR_GLOBAL::OnSizeFieldList( wxSizeEvent& event )
void DIALOG_FIELDS_EDITOR_GLOBAL::OnSaveAndContinue( wxCommandEvent& aEvent ) void DIALOG_FIELDS_EDITOR_GLOBAL::OnSaveAndContinue( wxCommandEvent& aEvent )
{ {
if( TransferDataFromWindow() ) if( TransferDataFromWindow() )
{ m_parent->SaveProject();
wxCommandEvent dummyEvent;
m_parent->OnSaveProject( dummyEvent );
}
} }
@ -982,7 +979,7 @@ void DIALOG_FIELDS_EDITOR_GLOBAL::OnClose( wxCloseEvent& event )
if( m_dataModel->IsEdited() ) if( m_dataModel->IsEdited() )
{ {
switch( DisplayExitDialog( this, wxEmptyString ) ) switch( UnsavedChangesDialog( this, wxEmptyString ) )
{ {
case wxID_CANCEL: case wxID_CANCEL:
event.Veto(); event.Veto();

View File

@ -337,7 +337,10 @@ void PANEL_SYM_LIB_TABLE::browseLibrariesHandler( wxCommandEvent& event )
m_lastBrowseDir = dlg.GetDirectory(); m_lastBrowseDir = dlg.GetDirectory();
const ENV_VAR_MAP& envVars = Pgm().GetLocalEnvVariables(); const ENV_VAR_MAP& envVars = Pgm().GetLocalEnvVariables();
bool skipRemainingDuplicates = false; bool addDuplicates = false;
bool applyToAll = false;
wxString warning = _( "Warning: Duplicate Nickname" );
wxString msg = _( "A library nicknamed \"%s\" already exists." );
wxArrayString files; wxArrayString files;
dlg.GetFilenames( files ); dlg.GetFilenames( files );
@ -346,29 +349,21 @@ void PANEL_SYM_LIB_TABLE::browseLibrariesHandler( wxCommandEvent& event )
wxString filePath = dlg.GetDirectory() + wxFileName::GetPathSeparator() + file; wxString filePath = dlg.GetDirectory() + wxFileName::GetPathSeparator() + file;
wxFileName fn( filePath ); wxFileName fn( filePath );
wxString nickname = LIB_ID::FixIllegalChars( fn.GetName(), LIB_ID::ID_SCH ); wxString nickname = LIB_ID::FixIllegalChars( fn.GetName(), LIB_ID::ID_SCH );
bool doAdd = true;
if( cur_model()->ContainsNickname( nickname ) ) if( cur_model()->ContainsNickname( nickname ) )
{ {
if( skipRemainingDuplicates ) if( !applyToAll )
continue;
int ret = YesNoCancelDialog( this,
_( "Warning: Duplicate Nickname" ),
wxString::Format( _( "A library nicknamed \"%s\" already exists." ), nickname ),
_( "Skip" ),
_( "Skip All Remaining Duplicates" ),
_( "Add Anyway" ) );
if( ret == wxID_YES )
continue;
else if ( ret == wxID_NO )
{ {
skipRemainingDuplicates = true; int ret = YesOrCancelDialog( this, warning, wxString::Format( msg, nickname ),
continue; _( "Skip" ), _( "Add Anyway" ), &applyToAll );
addDuplicates = (ret == wxID_CANCEL );
} }
doAdd = addDuplicates;
} }
if( m_cur_grid->AppendRows( 1 ) ) if( doAdd && m_cur_grid->AppendRows( 1 ) )
{ {
int last_row = m_cur_grid->GetNumberRows() - 1; int last_row = m_cur_grid->GetNumberRows() - 1;

View File

@ -73,8 +73,7 @@ bool SCH_EDIT_FRAME::SaveEEFile( SCH_SCREEN* aScreen, bool aSaveUnderNewName,
if( aSaveUnderNewName ) if( aSaveUnderNewName )
{ {
wxFileDialog dlg( this, _( "Schematic Files" ), wxFileDialog dlg( this, _( "Schematic Files" ), wxPathOnly( Prj().GetProjectFullName() ),
wxPathOnly( Prj().GetProjectFullName() ),
schematicFileName.GetFullName(), SchematicFileWildcard(), schematicFileName.GetFullName(), SchematicFileWildcard(),
wxFD_SAVE | wxFD_OVERWRITE_PROMPT ); wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
@ -203,15 +202,12 @@ bool SCH_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
wxString fullFileName( aFileSet[0] ); wxString fullFileName( aFileSet[0] );
// We insist on caller sending us an absolute path, if it does not, we say it's a bug. // We insist on caller sending us an absolute path, if it does not, we say it's a bug.
wxASSERT_MSG( wxFileName( fullFileName ).IsAbsolute(), wxASSERT_MSG( wxFileName( fullFileName ).IsAbsolute(), wxT( "Path is not absolute!" ) );
wxT( "bug in single_top.cpp or project manager." ) );
if( !LockFile( fullFileName ) ) if( !LockFile( fullFileName ) )
{ {
wxString msg = wxString::Format( _( wxString msg = wxString::Format( _( "Schematic file \"%s\" is already open." ),
"Schematic file \"%s\" is already open." ), fullFileName );
GetChars( fullFileName )
);
DisplayError( this, msg ); DisplayError( this, msg );
return false; return false;
} }
@ -228,10 +224,8 @@ bool SCH_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
if( is_new && !( aCtl & KICTL_CREATE ) ) if( is_new && !( aCtl & KICTL_CREATE ) )
{ {
// notify user that fullFileName does not exist, ask if user wants to create it. // notify user that fullFileName does not exist, ask if user wants to create it.
wxString ask = wxString::Format( _( wxString ask = wxString::Format( _( "Schematic \"%s\" does not exist. Do you wish to create it?" ),
"Schematic \"%s\" does not exist. Do you wish to create it?" ), fullFileName );
GetChars( fullFileName )
);
if( !IsOK( this, ask ) ) if( !IsOK( this, ask ) )
return false; return false;
} }
@ -384,7 +378,6 @@ bool SCH_EDIT_FRAME::AppendSchematic()
{ {
wxString msg; wxString msg;
wxString fullFileName; wxString fullFileName;
SCH_SCREEN* screen = GetScreen(); SCH_SCREEN* screen = GetScreen();
if( !screen ) if( !screen )
@ -396,9 +389,8 @@ bool SCH_EDIT_FRAME::AppendSchematic()
// open file chooser dialog // open file chooser dialog
wxString path = wxPathOnly( Prj().GetProjectFullName() ); wxString path = wxPathOnly( Prj().GetProjectFullName() );
wxFileDialog dlg( this, _( "Append Schematic" ), path, wxFileDialog dlg( this, _( "Append Schematic" ), path, wxEmptyString,
wxEmptyString, SchematicFileWildcard(), SchematicFileWildcard(), wxFD_OPEN | wxFD_FILE_MUST_EXIST );
wxFD_OPEN | wxFD_FILE_MUST_EXIST );
if( dlg.ShowModal() == wxID_CANCEL ) if( dlg.ShowModal() == wxID_CANCEL )
return false; return false;
@ -536,7 +528,6 @@ bool SCH_EDIT_FRAME::AppendSchematic()
// Don't expand environment variable because KIPRJMOD will not be correct // Don't expand environment variable because KIPRJMOD will not be correct
// for a different project. // for a different project.
wxString uri = table.GetFullURI( libName, false ); wxString uri = table.GetFullURI( libName, false );
wxFileName newLib; wxFileName newLib;
if( uri.Contains( "${KIPRJMOD}" ) ) if( uri.Contains( "${KIPRJMOD}" ) )
@ -569,15 +560,10 @@ bool SCH_EDIT_FRAME::AppendSchematic()
// Rename the imported symbol library if it already exists. // Rename the imported symbol library if it already exists.
while( Prj().SchSymbolLibTable()->HasLibrary( newLibName ) ) while( Prj().SchSymbolLibTable()->HasLibrary( newLibName ) )
{
newLibName = wxString::Format( "%s%d", libName, libNameCnt ); newLibName = wxString::Format( "%s%d", libName, libNameCnt );
}
SYMBOL_LIB_TABLE_ROW* newRow = new SYMBOL_LIB_TABLE_ROW( newLibName, auto newRow = new SYMBOL_LIB_TABLE_ROW( newLibName, uri, row->GetType(),
uri, row->GetOptions(), row->GetDescr() );
row->GetType(),
row->GetOptions(),
row->GetDescr() );
Prj().SchSymbolLibTable()->InsertRow( newRow ); Prj().SchSymbolLibTable()->InsertRow( newRow );
if( libName != newLibName ) if( libName != newLibName )
@ -653,7 +639,7 @@ void SCH_EDIT_FRAME::OnAppendProject( wxCommandEvent& event )
"Do you want to save the current document before proceeding?" ); "Do you want to save the current document before proceeding?" );
if( IsOK( this, msg ) ) if( IsOK( this, msg ) )
OnSaveProject( event ); SaveProject();
} }
AppendSchematic(); AppendSchematic();
@ -669,9 +655,8 @@ void SCH_EDIT_FRAME::OnImportProject( wxCommandEvent& aEvent )
bool setProject = Prj().GetProjectFullName().IsEmpty(); bool setProject = Prj().GetProjectFullName().IsEmpty();
wxString path = wxPathOnly( Prj().GetProjectFullName() ); wxString path = wxPathOnly( Prj().GetProjectFullName() );
wxFileDialog dlg( this, _( "Import Schematic" ), path, wxFileDialog dlg( this, _( "Import Schematic" ), path, wxEmptyString,
wxEmptyString, EagleSchematicFileWildcard(), EagleSchematicFileWildcard(), wxFD_OPEN | wxFD_FILE_MUST_EXIST );
wxFD_OPEN | wxFD_FILE_MUST_EXIST );
if( dlg.ShowModal() == wxID_CANCEL ) if( dlg.ShowModal() == wxID_CANCEL )
return; return;
@ -689,29 +674,35 @@ void SCH_EDIT_FRAME::OnImportProject( wxCommandEvent& aEvent )
void SCH_EDIT_FRAME::OnSaveProject( wxCommandEvent& aEvent ) void SCH_EDIT_FRAME::OnSaveProject( wxCommandEvent& aEvent )
{
SaveProject();
}
bool SCH_EDIT_FRAME::SaveProject()
{ {
SCH_SCREEN* screen; SCH_SCREEN* screen;
SCH_SCREENS screenList; SCH_SCREENS screenList;
bool success = true;
// I want to see it in the debugger, show me the string! Can't do that with wxFileName. // I want to see it in the debugger, show me the string! Can't do that with wxFileName.
wxString fileName = Prj().AbsolutePath( g_RootSheet->GetFileName() ); wxString fileName = Prj().AbsolutePath( g_RootSheet->GetFileName() );
wxFileName fn = fileName; wxFileName fn = fileName;
if( !fn.IsDirWritable() ) if( !fn.IsDirWritable() )
{ {
wxString msg = wxString::Format( _( "Directory \"%s\" is not writable." ), fn.GetPath() ); wxString msg = wxString::Format( _( "Directory \"%s\" is not writable." ), fn.GetPath() );
DisplayError( this, msg ); DisplayError( this, msg );
return; return false;
} }
for( screen = screenList.GetFirst(); screen; screen = screenList.GetNext() ) for( screen = screenList.GetFirst(); screen; screen = screenList.GetNext() )
SaveEEFile( screen ); success &= SaveEEFile( screen );
CreateArchiveLibraryCacheFile(); CreateArchiveLibraryCacheFile();
UpdateTitle(); UpdateTitle();
return success;
} }
@ -762,7 +753,6 @@ bool SCH_EDIT_FRAME::doAutoSave()
bool SCH_EDIT_FRAME::importFile( const wxString& aFileName, int aFileType ) bool SCH_EDIT_FRAME::importFile( const wxString& aFileName, int aFileType )
{ {
wxString fullFileName( aFileName );
wxString projectpath; wxString projectpath;
wxFileName newfilename; wxFileName newfilename;
SCH_SHEET_LIST sheetList( g_RootSheet ); SCH_SHEET_LIST sheetList( g_RootSheet );
@ -771,13 +761,13 @@ bool SCH_EDIT_FRAME::importFile( const wxString& aFileName, int aFileType )
{ {
case SCH_IO_MGR::SCH_EAGLE: case SCH_IO_MGR::SCH_EAGLE:
// We insist on caller sending us an absolute path, if it does not, we say it's a bug. // We insist on caller sending us an absolute path, if it does not, we say it's a bug.
wxASSERT_MSG( wxFileName( fullFileName ).IsAbsolute(), wxASSERT_MSG( wxFileName( aFileName ).IsAbsolute(),
wxT( "Import eagle schematic caller didn't send full filename" ) ); wxT( "Import eagle schematic caller didn't send full filename" ) );
if( !LockFile( fullFileName ) ) if( !LockFile( aFileName ) )
{ {
wxString msg = wxString::Format( _( "Schematic file \"%s\" is already open." ), wxString msg = wxString::Format( _( "Schematic file \"%s\" is already open." ),
GetChars( fullFileName ) ); aFileName );
DisplayError( this, msg ); DisplayError( this, msg );
return false; return false;
} }
@ -787,7 +777,7 @@ bool SCH_EDIT_FRAME::importFile( const wxString& aFileName, int aFileType )
delete g_RootSheet; delete g_RootSheet;
g_RootSheet = nullptr; g_RootSheet = nullptr;
SCH_PLUGIN::SCH_PLUGIN_RELEASER pi( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_EAGLE ) ); SCH_PLUGIN::SCH_PLUGIN_RELEASER pi( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_EAGLE ) );
g_RootSheet = pi->Load( fullFileName, &Kiway() ); g_RootSheet = pi->Load( aFileName, &Kiway() );
// Eagle sheets do not use a worksheet frame by default, so set it to an empty one // Eagle sheets do not use a worksheet frame by default, so set it to an empty one
@ -819,7 +809,7 @@ bool SCH_EDIT_FRAME::importFile( const wxString& aFileName, int aFileType )
GetScreen()->SetModify(); GetScreen()->SetModify();
SaveProjectSettings( false ); SaveProjectSettings( false );
UpdateFileHistory( fullFileName ); UpdateFileHistory( aFileName );
SCH_SCREENS schematic; SCH_SCREENS schematic;
schematic.UpdateSymbolLinks(); // Update all symbol library links for all sheets. schematic.UpdateSymbolLinks(); // Update all symbol library links for all sheets.
@ -861,7 +851,6 @@ bool SCH_EDIT_FRAME::importFile( const wxString& aFileName, int aFileType )
} }
} }
GetScreen()->ClearUndoORRedoList( GetScreen()->m_UndoList, 1 ); GetScreen()->ClearUndoORRedoList( GetScreen()->m_UndoList, 1 );
// Only perform the dangling end test on root sheet. // Only perform the dangling end test on root sheet.
GetScreen()->TestDanglingEnds(); GetScreen()->TestDanglingEnds();
@ -880,11 +869,10 @@ bool SCH_EDIT_FRAME::importFile( const wxString& aFileName, int aFileType )
Zoom_Automatique( false ); Zoom_Automatique( false );
wxString msg; wxString msg;
msg.Printf( _( "Error loading schematic file \"%s\".\n%s" ), msg.Printf( _( "Error loading schematic \"%s\".\n%s" ), aFileName, ioe.What() );
fullFileName, ioe.What() );
DisplayError( this, msg ); DisplayError( this, msg );
msg.Printf( _( "Failed to load \"%s\"" ), fullFileName ); msg.Printf( _( "Failed to load \"%s\"" ), aFileName );
AppendMsgPanel( wxEmptyString, msg, CYAN ); AppendMsgPanel( wxEmptyString, msg, CYAN );
return false; return false;
@ -895,8 +883,6 @@ bool SCH_EDIT_FRAME::importFile( const wxString& aFileName, int aFileType )
default: default:
return false; return false;
} }
return false;
} }
@ -909,25 +895,15 @@ bool SCH_EDIT_FRAME::AskToSaveChanges()
{ {
if( screen->IsModify() ) if( screen->IsModify() )
{ {
int response = YesNoCancelDialog( m_parent, _( wxString msg = _( "The current schematic has been modified. Save changes?" );
"The current schematic has been modified. Do you wish to save the changes?" ),
wxEmptyString,
_( "Save and Load" ),
_( "Load Without Saving" )
);
if( response == wxID_CANCEL ) switch( UnsavedChangesDialog( this, msg ) )
{ {
return false; default:
case wxID_CANCEL: return false;
case wxID_NO: return true;
case wxID_YES: return SaveProject();
} }
else if( response == wxID_YES )
{
wxCommandEvent dummy;
OnSaveProject( dummy );
}
// else wxID_NO, so do not save
break;
} }
} }

View File

@ -695,7 +695,7 @@ bool LIB_EDIT_FRAME::saveAllLibraries( bool aRequireConfirmation )
wxString msg = wxString::Format( _( "Save changes to \"%s\" before closing?" ), wxString msg = wxString::Format( _( "Save changes to \"%s\" before closing?" ),
libNickname ); libNickname );
switch( DisplayExitDialog( this, msg, dirtyCount > 1 ? &applyToAll : nullptr ) ) switch( UnsavedChangesDialog( this, msg, dirtyCount > 1 ? &applyToAll : nullptr ) )
{ {
case wxID_YES: doSave = true; break; case wxID_YES: doSave = true; break;
case wxID_NO: doSave = false; break; case wxID_NO: doSave = false; break;
@ -706,9 +706,10 @@ bool LIB_EDIT_FRAME::saveAllLibraries( bool aRequireConfirmation )
if( doSave ) if( doSave )
{ {
// If saving under existing name fails then do a Save As... // If saving under existing name fails then do a Save As..., and if that
if( !saveLibrary( libNickname, false ) ) // fails then cancel close action.
saveLibrary( libNickname, true ); if( !saveLibrary( libNickname, false ) && !saveLibrary( libNickname, true ) )
return false;
} }
} }
} }

View File

@ -655,26 +655,24 @@ void SCH_EDIT_FRAME::OnCloseWindow( wxCloseEvent& aEvent )
if( sheetList.IsModified() ) if( sheetList.IsModified() )
{ {
wxString fileName = Prj().AbsolutePath( g_RootSheet->GetScreen()->GetFileName() ); wxString fileName = Prj().AbsolutePath( g_RootSheet->GetScreen()->GetFileName() );
wxString msg = wxString::Format( _( wxString msg = _( "Save changes to\n\"%s\"\nbefore closing?" );
"Save the changes in\n\"%s\"\nbefore closing?"),
GetChars( fileName )
);
int ii = DisplayExitDialog( this, msg ); switch( UnsavedChangesDialog( this, wxString::Format( msg, fileName ) ) )
switch( ii )
{ {
case wxID_CANCEL: case wxID_YES:
aEvent.Veto(); if( !SaveProject() )
return; {
aEvent.Veto();
return;
}
break;
case wxID_NO: case wxID_NO:
break; break;
case wxID_YES: case wxID_CANCEL:
wxCommandEvent tmp( ID_SAVE_PROJECT ); aEvent.Veto();
OnSaveProject( tmp ); return;
break;
} }
} }

View File

@ -730,6 +730,7 @@ public:
* The component library archive name is &ltroot_name&gt-cache.lib * The component library archive name is &ltroot_name&gt-cache.lib
*/ */
void OnSaveProject( wxCommandEvent& aEvent ); void OnSaveProject( wxCommandEvent& aEvent );
bool SaveProject();
bool OpenProjectFiles( const std::vector<wxString>& aFileSet, int aCtl = 0 ) override; bool OpenProjectFiles( const std::vector<wxString>& aFileSet, int aCtl = 0 ) override;

View File

@ -76,21 +76,16 @@ protected:
/** /**
* Function DisplayExitDialog * Function UnsavedChangesDialog
* displays a dialog with 3 buttons: * displays a dialog with Save, Cancel and Discard Changes buttons.
* Save and Exit
* Cancel
* Exit without save
* *
* @param aParent = the parent window * @param aParent = the parent window
* @param aMessage = the main message to put in dialog * @param aMessage = the main message to put in dialog
* If empty, the standard message will be shown: * @param aApplyToAll = if non-null an "Apply to all" checkbox will be shown and it's value
* Save the changes before closing? * written back to the bool.
* @param aApplyToAll = if non-null an "Apply to all" checkbox will be shown and the value
* written to the bool.
* @return wxID_YES, wxID_CANCEL, wxID_NO. * @return wxID_YES, wxID_CANCEL, wxID_NO.
*/ */
int DisplayExitDialog( wxWindow* aParent, const wxString& aMessage, bool* aApplyToAll = nullptr ); int UnsavedChangesDialog( wxWindow* aParent, const wxString& aMessage, bool* aApplyToAll = nullptr );
/** /**
@ -134,26 +129,21 @@ void DisplayInfoMessage( wxWindow* parent, const wxString& aMessage, const wxStr
bool IsOK( wxWindow* aParent, const wxString& aMessage ); bool IsOK( wxWindow* aParent, const wxString& aMessage );
/** /**
* Function YesNoCancelDialog * Function YesOrCancelDialog
* displays a yes/no/cancel dialog with \a aMessage and returns the user response. * displays a warning dialog with \a aMessage and returns the user response.
* *
* @param aParent is the parent window. NULL can be used if the parent is the top level window. * @param aParent is the parent window. NULL can be used if the parent is the top level window.
* @param aPrimaryMessage is the message to display in the top part of the dialog box using * @param aWarning is the warning to display in the top part of the dialog box using a bold font.
* a bold font. * @param aMessage is the message to display in the lower part of the dialog box using the
* @param aSecondaryMessage is the message to display in the lower part of the dialog box * default system UI font.
* using the default system UI font. * @param aOKLabel is the text to display in the OK button.
* @param aYesButtonText is the text to display in the yes button when defined. * @param aCancelLabel is the text to display in the cancel button.
* @param aNoButtonText is the text to display in the no button when defiend.
* @param aCancelButtonText is the text to display in the cancel button when defined.
* *
* @return wxID_YES, wxID_NO, or wxID_CANCEL depending on the button the user selected. * @return wxID_YES or wxID_CANCEL depending on the button the user selected.
*/ */
int YesNoCancelDialog( wxWindow* aParent, int YesOrCancelDialog( wxWindow* aParent, const wxString& aWarning, const wxString& aMessage,
const wxString& aPrimaryMessage, const wxString& aOKLabel, const wxString& aCancelLabel,
const wxString& aSecondaryMessage, bool* aApplyToAll = nullptr );
const wxString& aYesButtonText = wxEmptyString,
const wxString& aNoButtonText = wxEmptyString,
const wxString& aCancelButtonText = wxEmptyString );

View File

@ -223,14 +223,11 @@ void PL_EDITOR_FRAME::OnCloseWindow( wxCloseEvent& Event )
wxString filename = GetCurrFileName(); wxString filename = GetCurrFileName();
if( filename.IsEmpty() ) if( filename.IsEmpty() )
msg = _( "Save changes in a new file before closing?" ); msg = _( "Save changes before closing?" );
else else
msg.Printf( _( "Save the changes in\n\"%s\"\nbefore closing?" ), msg.Printf( _( "Save changes to\n\"%s\"\nbefore closing?" ), filename );
GetChars( filename ) );
int ii = DisplayExitDialog( this, msg ); switch( UnsavedChangesDialog( this, msg ) )
switch( ii )
{ {
case wxID_CANCEL: case wxID_CANCEL:
Event.Veto(); Event.Veto();
@ -239,16 +236,17 @@ void PL_EDITOR_FRAME::OnCloseWindow( wxCloseEvent& Event )
case wxID_NO: case wxID_NO:
break; break;
case wxID_OK:
case wxID_YES: case wxID_YES:
{
if( filename.IsEmpty() ) if( filename.IsEmpty() )
{ {
wxFileDialog openFileDialog( this, _( "Save As" ), wxEmptyString, wxEmptyString, wxFileDialog openFileDialog( this, _( "Save As" ), wxEmptyString, wxEmptyString,
PageLayoutDescrFileWildcard(), wxFD_SAVE ); PageLayoutDescrFileWildcard(), wxFD_SAVE );
if(openFileDialog.ShowModal() == wxID_CANCEL ) if( openFileDialog.ShowModal() == wxID_CANCEL )
{
Event.Veto();
return; return;
}
filename = openFileDialog.GetPath(); filename = openFileDialog.GetPath();
} }
@ -257,8 +255,10 @@ void PL_EDITOR_FRAME::OnCloseWindow( wxCloseEvent& Event )
{ {
msg.Printf( _( "Unable to create \"%s\"" ), GetChars( filename ) ); msg.Printf( _( "Unable to create \"%s\"" ), GetChars( filename ) );
wxMessageBox( msg ); wxMessageBox( msg );
Event.Veto();
return;
} }
}
break; break;
} }
} }

View File

@ -587,7 +587,10 @@ void PANEL_FP_LIB_TABLE::browseLibrariesHandler( wxCommandEvent& event )
m_lastBrowseDir = m_lastBrowseDir.BeforeLast( wxFileName::GetPathSeparator() ); m_lastBrowseDir = m_lastBrowseDir.BeforeLast( wxFileName::GetPathSeparator() );
const ENV_VAR_MAP& envVars = Pgm().GetLocalEnvVariables(); const ENV_VAR_MAP& envVars = Pgm().GetLocalEnvVariables();
bool skipRemainingDuplicates = false; bool addDuplicates = false;
bool applyToAll = false;
wxString warning = _( "Warning: Duplicate Nickname" );
wxString msg = _( "A library nicknamed \"%s\" already exists." );
wxArrayString files; wxArrayString files;
dlg.GetFilenames( files ); dlg.GetFilenames( files );
@ -595,29 +598,21 @@ void PANEL_FP_LIB_TABLE::browseLibrariesHandler( wxCommandEvent& event )
{ {
wxFileName fn( filePath ); wxFileName fn( filePath );
wxString nickname = LIB_ID::FixIllegalChars( fn.GetName(), LIB_ID::ID_PCB ); wxString nickname = LIB_ID::FixIllegalChars( fn.GetName(), LIB_ID::ID_PCB );
bool doAdd = true;
if( cur_model()->ContainsNickname( nickname ) ) if( cur_model()->ContainsNickname( nickname ) )
{ {
if( skipRemainingDuplicates ) if( !applyToAll )
continue;
int ret = YesNoCancelDialog( this,
_( "Warning: Duplicate Nickname" ),
wxString::Format( _( "A library nicknamed \"%s\" already exists." ), nickname ),
_( "Skip" ),
_( "Skip All Remaining Duplicates" ),
_( "Add Anyway" ) );
if( ret == wxID_YES )
continue;
else if ( ret == wxID_NO )
{ {
skipRemainingDuplicates = true; int ret = YesOrCancelDialog( this, warning, wxString::Format( msg, nickname ),
continue; _( "Skip" ), _( "Add Anyway" ), &applyToAll );
addDuplicates = (ret == wxID_CANCEL );
} }
doAdd = addDuplicates;
} }
if( m_cur_grid->AppendRows( 1 ) ) if( doAdd && m_cur_grid->AppendRows( 1 ) )
{ {
int last_row = m_cur_grid->GetNumberRows() - 1; int last_row = m_cur_grid->GetNumberRows() - 1;

View File

@ -416,35 +416,32 @@ bool PCB_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
wxString fullFileName( aFileSet[0] ); wxString fullFileName( aFileSet[0] );
// We insist on caller sending us an absolute path, if it does not, we say it's a bug. // We insist on caller sending us an absolute path, if it does not, we say it's a bug.
wxASSERT_MSG( wxFileName( fullFileName ).IsAbsolute(), wxASSERT_MSG( wxFileName( fullFileName ).IsAbsolute(), wxT( "Path is not absolute!" ) );
wxT( "bug in single_top.cpp or project manager." ) );
if( !LockFile( fullFileName ) ) if( !LockFile( fullFileName ) )
{ {
wxString msg = wxString::Format( _( wxString msg = wxString::Format( _( "PCB file \"%s\" is already open." ), fullFileName );
"PCB file \"%s\" is already open." ),
GetChars( fullFileName )
);
DisplayError( this, msg ); DisplayError( this, msg );
return false; return false;
} }
if( GetScreen()->IsModify() && !GetBoard()->IsEmpty() ) if( GetScreen()->IsModify() && !GetBoard()->IsEmpty() )
{ {
int response = YesNoCancelDialog( this, _( wxString msg = _( "The current PCB has been modified. Save changes?" );
"The current board has been modified. Do you wish to save the changes?" ),
wxEmptyString,
_( "Save and Load" ),
_( "Load Without Saving" )
);
if( response == wxID_CANCEL ) switch( UnsavedChangesDialog( this, msg ) )
return false;
else if( response == wxID_YES )
SavePcbFile( GetBoard()->GetFileName(), CREATE_BACKUP_FILE );
else
{ {
// response == wxID_NO, fall thru default:
case wxID_CANCEL:
return false;
case wxID_YES:
if( !SavePcbFile( GetBoard()->GetFileName(), CREATE_BACKUP_FILE ) )
return false;
break;
case wxID_NO:
break;
} }
} }
@ -457,10 +454,8 @@ bool PCB_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
if( is_new && !( aCtl & KICTL_CREATE ) ) if( is_new && !( aCtl & KICTL_CREATE ) )
{ {
// notify user that fullFileName does not exist, ask if user wants to create it. // notify user that fullFileName does not exist, ask if user wants to create it.
wxString ask = wxString::Format( _( wxString ask = wxString::Format( _( "PCB \"%s\" does not exist. Do you wish to create it?" ),
"Board \"%s\" does not exist. Do you wish to create it?" ), fullFileName );
GetChars( fullFileName )
);
if( !IsOK( this, ask ) ) if( !IsOK( this, ask ) )
return false; return false;
} }

View File

@ -517,9 +517,7 @@ void FOOTPRINT_EDIT_FRAME::OnCloseWindow( wxCloseEvent& Event )
{ {
if( GetScreen()->IsModify() && GetBoard()->m_Modules ) if( GetScreen()->IsModify() && GetBoard()->m_Modules )
{ {
int ii = DisplayExitDialog( this, _( "Save changes to footprint before closing?" ) ); switch( UnsavedChangesDialog( this, _( "Save changes to footprint before closing?" ) ) )
switch( ii )
{ {
default: default:
case wxID_NO: case wxID_NO:

View File

@ -630,16 +630,11 @@ void PCB_EDIT_FRAME::OnCloseWindow( wxCloseEvent& Event )
if( GetScreen()->IsModify() && !GetBoard()->IsEmpty() ) if( GetScreen()->IsModify() && !GetBoard()->IsEmpty() )
{ {
wxString msg = wxString::Format( _( wxString msg = _( "Save changes to\n\"%s\"\nbefore closing?" );
"Save the changes in\n"
"\"%s\"\n"
"before closing?" ),
GetChars( GetBoard()->GetFileName() )
);
int ii = DisplayExitDialog( this, msg ); switch( UnsavedChangesDialog( this, wxString::Format( msg, GetBoard()->GetFileName() ) ) )
switch( ii )
{ {
default:
case wxID_CANCEL: case wxID_CANCEL:
Event.Veto(); Event.Veto();
return; return;
@ -648,8 +643,6 @@ void PCB_EDIT_FRAME::OnCloseWindow( wxCloseEvent& Event )
break; break;
case wxID_YES: case wxID_YES:
// save the board. if the board has no name,
// the ID_SAVE_BOARD_AS will actually made
Files_io_from_id( ID_SAVE_BOARD ); Files_io_from_id( ID_SAVE_BOARD );
break; break;
} }
@ -684,11 +677,8 @@ void PCB_EDIT_FRAME::OnCloseWindow( wxCloseEvent& Event )
// Remove the auto save file on a normal close of Pcbnew. // Remove the auto save file on a normal close of Pcbnew.
if( fn.FileExists() && !wxRemoveFile( fn.GetFullPath() ) ) if( fn.FileExists() && !wxRemoveFile( fn.GetFullPath() ) )
{ {
wxString msg = wxString::Format( _( wxString msg = wxString::Format( _( "The auto save file \"%s\" could not be removed!" ),
"The auto save file \"%s\" could not be removed!" ), fn.GetFullPath() );
GetChars( fn.GetFullPath() )
);
wxMessageBox( msg, Pgm().App().GetAppName(), wxOK | wxICON_ERROR, this ); wxMessageBox( msg, Pgm().App().GetAppName(), wxOK | wxICON_ERROR, this );
} }
@ -816,12 +806,7 @@ void PCB_EDIT_FRAME::LoadSettings( wxConfigBase* aCfg )
double dtmp; double dtmp;
aCfg->Read( PlotLineWidthEntry, &dtmp, 0.1 ); // stored in mm aCfg->Read( PlotLineWidthEntry, &dtmp, 0.1 ); // stored in mm
dtmp = std::max( 0.01, std::min( dtmp, 5.0 ) );
if( dtmp < 0.01 )
dtmp = 0.01;
if( dtmp > 5.0 )
dtmp = 5.0;
g_DrawDefaultLineThickness = Millimeter2iu( dtmp ); g_DrawDefaultLineThickness = Millimeter2iu( dtmp );
@ -1082,20 +1067,13 @@ void PCB_EDIT_FRAME::UpdateTitle()
wxString fileinfo; wxString fileinfo;
if( fileName.IsOk() && fileName.FileExists() ) if( fileName.IsOk() && fileName.FileExists() )
{
fileinfo = fileName.IsFileWritable() ? wxString( wxEmptyString ) : _( " [Read Only]" ); fileinfo = fileName.IsFileWritable() ? wxString( wxEmptyString ) : _( " [Read Only]" );
}
else else
{ fileinfo = _( " [Unsaved]" );
fileinfo = _( " [new file]" );
}
wxString title; SetTitle( wxString::Format( _( "Pcbnew" ) + wxT( " \u2014 %s%s" ),
title.Printf( _( "Pcbnew" ) + wxT( " \u2014 %s%s" ), fileName.GetFullPath(),
fileName.GetFullPath(), fileinfo ) );
fileinfo );
SetTitle( title );
} }