Regularize save-changes dialogs.

This commit is contained in:
Jeff Young 2018-08-11 21:46:03 +01:00
parent acec00f80a
commit 4b1a31ffad
20 changed files with 189 additions and 265 deletions

View File

@ -198,6 +198,19 @@ int UnsavedChangesDialog( wxWindow* parent, const wxString& aMessage, bool* aApp
}
bool HandleUnsavedChanges( wxWindow* aParent, const wxString& aMessage,
const std::function<bool()>& aSaveFunction )
{
switch( UnsavedChangesDialog( aParent, aMessage, nullptr ) )
{
case wxID_YES: return aSaveFunction();
case wxID_NO: return true;
default:
case wxID_CANCEL: return false;
}
}
int YesOrCancelDialog( wxWindow* aParent, const wxString& aWarning, const wxString& aMessage,
const wxString& aOKLabel, const wxString& aCancelLabel, bool* aApplyToAll )
{

View File

@ -260,20 +260,11 @@ void CVPCB_MAINFRAME::OnCloseWindow( wxCloseEvent& Event )
{
if( m_modified )
{
wxString msg = _( "Symbol to Footprint links have been modified.\nSave before exit?" );
switch( UnsavedChangesDialog( this, msg ) )
if( !HandleUnsavedChanges( this, _( "Symbol to Footprint links have been modified.\nSave before exit?" ),
[&]()->bool { return SaveFootprintAssociation( false ); } ) )
{
case wxID_CANCEL:
Event.Veto();
return;
case wxID_NO:
break;
case wxID_YES:
SaveFootprintAssociation( false );
break;
}
}

View File

@ -205,7 +205,7 @@ public:
* via the kiway.
* Optionally saves the schematic to disk as well.
*/
void SaveFootprintAssociation( bool doSaveSchematic );
bool SaveFootprintAssociation( bool doSaveSchematic );
/**
* Function ReadNetListAndFpFiles

View File

@ -371,7 +371,7 @@ bool CVPCB_MAINFRAME::ReadNetListAndFpFiles( const std::string& aNetlist )
}
void CVPCB_MAINFRAME::SaveFootprintAssociation( bool doSaveSchematic )
bool CVPCB_MAINFRAME::SaveFootprintAssociation( bool doSaveSchematic )
{
STRING_FORMATTER sf;
@ -381,4 +381,6 @@ void CVPCB_MAINFRAME::SaveFootprintAssociation( bool doSaveSchematic )
if( doSaveSchematic )
Kiway().ExpressMail( FRAME_SCH, MAIL_SCH_SAVE, std::string( "" ) );
return true; // we can't tell if it was successful, so just assume the best
}

View File

@ -979,24 +979,13 @@ void DIALOG_FIELDS_EDITOR_GLOBAL::OnClose( wxCloseEvent& event )
if( m_dataModel->IsEdited() )
{
switch( UnsavedChangesDialog( this, wxEmptyString ) )
if( !HandleUnsavedChanges( this, wxEmptyString,
[&]()->bool { return TransferDataFromWindow(); } ) )
{
case wxID_CANCEL:
event.Veto();
break;
return;
}
}
case wxID_YES:
if( TransferDataFromWindow() )
event.Skip();
break;
case wxID_NO:
event.Skip();
break;
}
}
else
{
event.Skip();
}
}

View File

@ -895,14 +895,10 @@ bool SCH_EDIT_FRAME::AskToSaveChanges()
{
if( screen->IsModify() )
{
wxString msg = _( "The current schematic has been modified. Save changes?" );
switch( UnsavedChangesDialog( this, msg ) )
if( !HandleUnsavedChanges( this, _( "The current schematic has been modified. Save changes?" ),
[&]()->bool { return SaveProject(); } ) )
{
default:
case wxID_CANCEL: return false;
case wxID_NO: return true;
case wxID_YES: return SaveProject();
return false;
}
}
}

View File

@ -742,6 +742,9 @@ private:
*/
bool saveAllLibraries( bool aRequireConfirmation );
///> Saves the current part.
bool saveCurrentPart();
///> Creates or adds an existing library to the symbol library table.
bool addLibraryFile( bool aCreateNew );

View File

@ -81,18 +81,35 @@ void LIB_EDIT_FRAME::SelectActiveLibrary( const wxString& aLibrary )
}
bool LIB_EDIT_FRAME::saveCurrentPart()
{
if( GetCurPart() )
{
LIB_ID libId = GetCurPart()->GetLibId();
const wxString& libName = libId.GetLibNickname();
const wxString& partName = libId.GetLibItemName();
if( m_libMgr->FlushPart( partName, libName ) )
{
m_libMgr->ClearPartModified( partName, libName );
return true;
}
}
return false;
}
bool LIB_EDIT_FRAME::LoadComponentAndSelectLib( const LIB_ID& aLibId )
{
if( GetScreen()->IsModify() )
if( GetScreen()->IsModify() && GetCurPart() )
{
if( !HandleUnsavedChanges( this, _( "The current symbol has been modified. Save changes?" ),
[&]()->bool { return saveCurrentPart(); } ) )
{
KIDIALOG dlg( this, _( "The current symbol contains unsaved changes." ),
_( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
dlg.SetOKLabel( _( "Discard Changes" ) );
dlg.DoNotShowCheckbox();
if( dlg.ShowModal() == wxID_CANCEL )
return false;
}
}
SelectActiveLibrary( aLibId.GetLibNickname() );
return LoadComponentFromCurrentLib( aLibId.GetLibItemName() );

View File

@ -632,20 +632,9 @@ void SCH_EDIT_FRAME::OnCloseWindow( wxCloseEvent& aEvent )
wxString fileName = Prj().AbsolutePath( g_RootSheet->GetScreen()->GetFileName() );
wxString msg = _( "Save changes to\n\"%s\"\nbefore closing?" );
switch( UnsavedChangesDialog( this, wxString::Format( msg, fileName ) ) )
if( !HandleUnsavedChanges( this, wxString::Format( msg, fileName ),
[&]()->bool { return SaveProject(); } ) )
{
case wxID_YES:
if( !SaveProject() )
{
aEvent.Veto();
return;
}
break;
case wxID_NO:
break;
case wxID_CANCEL:
aEvent.Veto();
return;
}

View File

@ -76,16 +76,31 @@ protected:
/**
* Function UnsavedChangesDialog
* Function HandleUnsavedChanges
* displays a dialog with Save, Cancel and Discard Changes buttons.
*
* @param aParent = the parent window
* @param aMessage = the main message to put in dialog
* @param aSaveFunction = a function to save changes, if requested. Must return true if
* the save was successful and false otherwise (which will result
* in HandleUnsavedChanges() returning wxID_CANCEL).
* @return wxID_YES, wxID_CANCEL, wxID_NO.
*/
bool HandleUnsavedChanges( wxWindow* aParent, const wxString& aMessage,
const std::function<bool()>& aSaveFunction );
/**
* Function UnsavedChangesDialog
* a specialized version of HandleUnsavedChanges which handles an apply-to-all checkbox.
*
* @param aParent = the parent window
* @param aMessage = the main message to put in dialog
* @param aApplyToAll = if non-null an "Apply to all" checkbox will be shown and it's value
* written back to the bool.
* @return wxID_YES, wxID_CANCEL, wxID_NO.
*/
int UnsavedChangesDialog( wxWindow* aParent, const wxString& aMessage, bool* aApplyToAll = nullptr );
int UnsavedChangesDialog( wxWindow* aParent, const wxString& aMessage, bool* aApplyToAll );
/**

View File

@ -41,6 +41,17 @@
#include <pl_editor_id.h>
#include <wildcards_and_files_ext.h>
bool PL_EDITOR_FRAME::saveCurrentPageLayout()
{
wxCommandEvent saveEvent;
saveEvent.SetId( wxID_SAVE );
Files_io( saveEvent );
return( !GetScreen()->IsModify() );
}
void PL_EDITOR_FRAME::OnFileHistory( wxCommandEvent& event )
{
wxString filename;
@ -49,10 +60,11 @@ void PL_EDITOR_FRAME::OnFileHistory( wxCommandEvent& event )
if( filename != wxEmptyString )
{
if( GetScreen()->IsModify() && !IsOK( this,
_( "The current page layout has been modified.\n"
"Do you wish to discard the changes?" ) ) )
if( !HandleUnsavedChanges( this, _( "The current page layout has been modified. Save changes?" ),
[&]()->bool { return saveCurrentPageLayout(); } ) )
{
return;
}
m_canvas->EndMouseCapture( ID_NO_TOOL_SELECTED, m_canvas->GetDefaultCursor() );
::wxSetWorkingDirectory( ::wxPathOnly( filename ) );
@ -80,18 +92,13 @@ void PL_EDITOR_FRAME::Files_io( wxCommandEvent& event )
if( filename.IsEmpty() && id == wxID_SAVE )
id = wxID_SAVEAS;
switch( id )
if( ( id == wxID_NEW || id == wxID_OPEN ) && GetScreen()->IsModify() )
{
if( !HandleUnsavedChanges( this, _( "The current page layout has been modified. Save changes?" ),
[&]()->bool { return saveCurrentPageLayout(); } ) )
{
case wxID_NEW:
case wxID_OPEN:
if( GetScreen()->IsModify() && !IsOK( this,
_( "The current page layout has been modified.\n"
"Do you wish to discard the changes?" ) ) )
return;
break;
default:
break;
}
}
switch( id )

View File

@ -185,48 +185,12 @@ void PL_EDITOR_FRAME::OnCloseWindow( wxCloseEvent& Event )
{
if( GetScreen()->IsModify() )
{
wxString msg;
wxString filename = GetCurrFileName();
if( filename.IsEmpty() )
msg = _( "Save changes before closing?" );
else
msg.Printf( _( "Save changes to\n\"%s\"\nbefore closing?" ), filename );
switch( UnsavedChangesDialog( this, msg ) )
{
case wxID_CANCEL:
Event.Veto();
return;
case wxID_NO:
break;
case wxID_YES:
if( filename.IsEmpty() )
{
wxFileDialog openFileDialog( this, _( "Save As" ), wxEmptyString, wxEmptyString,
PageLayoutDescrFileWildcard(), wxFD_SAVE );
if( openFileDialog.ShowModal() == wxID_CANCEL )
if( !HandleUnsavedChanges( this, _( "The current page layout has been modified. Save changes?" ),
[&]()->bool { return saveCurrentPageLayout(); } ) )
{
Event.Veto();
return;
}
filename = openFileDialog.GetPath();
}
if( !SavePageLayoutDescrFile( filename ) )
{
msg.Printf( _( "Unable to create \"%s\"" ), GetChars( filename ) );
wxMessageBox( msg );
Event.Veto();
return;
}
break;
}
}
// do not show the window because we do not want any paint event

View File

@ -405,6 +405,9 @@ public:
*/
void RemoveLastCommandInUndoList();
protected:
bool saveCurrentPageLayout();
DECLARE_EVENT_TABLE()
};

View File

@ -224,7 +224,8 @@ void PCB_EDIT_FRAME::Files_io( wxCommandEvent& event )
Files_io_from_id( id );
}
void PCB_EDIT_FRAME::Files_io_from_id( int id )
bool PCB_EDIT_FRAME::Files_io_from_id( int id )
{
wxString msg;
@ -242,24 +243,18 @@ void PCB_EDIT_FRAME::Files_io_from_id( int id )
int open_ctl = 0;
wxString fileName = Prj().AbsolutePath( GetBoard()->GetFileName() );
if( !AskLoadBoardFileName( this, &open_ctl, &fileName, true ) )
return;
OpenProjectFiles( std::vector<wxString>( 1, fileName ), open_ctl );
return AskLoadBoardFileName( this, &open_ctl, &fileName, true )
&& OpenProjectFiles( std::vector<wxString>( 1, fileName ), open_ctl );
}
break;
case ID_IMPORT_NON_KICAD_BOARD:
{
int open_ctl = 1;
wxString fileName; // = Prj().AbsolutePath( GetBoard()->GetFileName() );
if( !AskLoadBoardFileName( this, &open_ctl, &fileName, false ) )
return;
OpenProjectFiles( std::vector<wxString>( 1, fileName ), open_ctl );
return AskLoadBoardFileName( this, &open_ctl, &fileName, false )
&& OpenProjectFiles( std::vector<wxString>( 1, fileName ), open_ctl );
}
break;
case ID_MENU_READ_BOARD_BACKUP_FILE:
case ID_MENU_RECOVER_BOARD_AUTOSAVE:
@ -280,28 +275,27 @@ void PCB_EDIT_FRAME::Files_io_from_id( int id )
if( !fn.FileExists() )
{
msg.Printf( _( "Recovery file \"%s\" not found." ),
GetChars( fn.GetFullPath() ) );
msg.Printf( _( "Recovery file \"%s\" not found." ), fn.GetFullPath() );
DisplayInfoMessage( this, msg );
break;
return false;
}
msg.Printf( _( "OK to load recovery or backup file \"%s\"" ),
GetChars(fn.GetFullPath() ) );
msg.Printf( _( "OK to load recovery or backup file \"%s\"" ), fn.GetFullPath() );
if( !IsOK( this, msg ) )
break;
return false;
GetScreen()->ClrModify(); // do not prompt the user for changes
// LoadOnePcbFile( fn.GetFullPath(), aAppend=false, aForceFileDialog=false );
OpenProjectFiles( std::vector<wxString>( 1, fn.GetFullPath() ) );
if( OpenProjectFiles( std::vector<wxString>( 1, fn.GetFullPath() ) ) )
{
// Re-set the name since name or extension was changed
GetBoard()->SetFileName( currfn.GetFullPath() );
UpdateTitle();
return true;
}
return false;
}
break;
case ID_APPEND_FILE:
{
@ -309,18 +303,20 @@ void PCB_EDIT_FRAME::Files_io_from_id( int id )
wxString fileName;
if( !AskLoadBoardFileName( this, &open_ctl, &fileName, true ) )
break;
AppendBoardFile( fileName, open_ctl );
return false;
if( AppendBoardFile( fileName, open_ctl ) )
{
m_canvas->Refresh();
return true;
}
return false;
}
break;
case ID_NEW_BOARD:
{
if( !Clear_Pcb( true ) )
break;
return false;
wxFileName fn( wxStandardPaths::Get().GetDocumentsDir(), wxT( "noname" ),
ProjectFileExtension );
@ -334,16 +330,14 @@ void PCB_EDIT_FRAME::Files_io_from_id( int id )
onBoardLoaded();
OnModify();
break;
return true;
}
case ID_SAVE_BOARD:
if( !GetBoard()->GetFileName().IsEmpty() )
{
SavePcbFile( Prj().AbsolutePath( GetBoard()->GetFileName() ) );
break;
}
return SavePcbFile( Prj().AbsolutePath( GetBoard()->GetFileName() ) );
// Fall through
case ID_COPY_BOARD_AS:
case ID_SAVE_BOARD_AS:
{
@ -354,16 +348,16 @@ void PCB_EDIT_FRAME::Files_io_from_id( int id )
if( AskSaveBoardFileName( this, &filename ) )
{
if( id == ID_COPY_BOARD_AS )
SavePcbCopy( filename );
return SavePcbCopy( filename );
else
SavePcbFile( filename, NO_BACKUP_FILE );
return SavePcbFile( filename, NO_BACKUP_FILE );
}
return false;
}
break;
default:
DisplayError( this, wxT( "File_io Internal Error" ) );
break;
return false;
}
}
@ -427,21 +421,10 @@ bool PCB_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
if( GetScreen()->IsModify() && !GetBoard()->IsEmpty() )
{
wxString msg = _( "The current PCB has been modified. Save changes?" );
switch( UnsavedChangesDialog( this, msg ) )
if( !HandleUnsavedChanges( this, _( "The current PCB has been modified. Save changes?" ),
[&]()->bool { return SavePcbFile( GetBoard()->GetFileName(), CREATE_BACKUP_FILE ); } ) )
{
default:
case wxID_CANCEL:
return false;
case wxID_YES:
if( !SavePcbFile( GetBoard()->GetFileName(), CREATE_BACKUP_FILE ) )
return false;
break;
case wxID_NO:
break;
}
}

View File

@ -494,21 +494,9 @@ void FOOTPRINT_EDIT_FRAME::OnCloseWindow( wxCloseEvent& Event )
{
if( GetScreen()->IsModify() && GetBoard()->m_Modules )
{
switch( UnsavedChangesDialog( this, _( "Save changes to footprint before closing?" ) ) )
if( !HandleUnsavedChanges( this, _( "Save changes to footprint before closing?" ),
[&]()->bool { return SaveFootprint( GetBoard()->m_Modules ); } ) )
{
default:
case wxID_NO:
break;
case wxID_YES:
if( !SaveFootprint( GetBoard()->m_Modules ) )
{
Event.Veto();
return;
}
break;
case wxID_CANCEL:
Event.Veto();
return;
}

View File

@ -176,13 +176,6 @@ BOARD_ITEM* FOOTPRINT_EDIT_FRAME::ModeditLocateAndDisplay( int aHotKeyCode )
void FOOTPRINT_EDIT_FRAME::LoadModuleFromBoard( wxCommandEvent& event )
{
if( GetScreen()->IsModify() )
{
if( !IsOK( this,
_( "Current footprint changes will be lost and this operation cannot be undone. Continue?" ) ) )
return;
}
if( ! Load_Module_From_BOARD( NULL ) )
return;
@ -294,23 +287,13 @@ void FOOTPRINT_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event )
case ID_MODEDIT_NEW_MODULE:
{
LIB_ID selected = m_treePane->GetLibTree()->GetSelectedLibId();
if( GetScreen()->IsModify() && !GetBoard()->IsEmpty() )
{
KIDIALOG dlg( this, _( "The current footprint contains unsaved changes." ),
_( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
dlg.SetOKLabel( _( "Discard Changes" ) );
dlg.DoNotShowCheckbox();
if( dlg.ShowModal() == wxID_CANCEL )
break;
}
MODULE* module = CreateNewModule( wxEmptyString );
if( module ) // i.e. if create module command not aborted
{
Clear_Pcb( false );
if( !module )
break;
if( !Clear_Pcb( true ) )
break;
SetCrossHairPosition( wxPoint( 0, 0 ) );
AddModuleToBoard( module );
@ -336,7 +319,6 @@ void FOOTPRINT_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event )
SaveFootprint( module );
GetScreen()->ClrModify();
}
}
updateView();
m_canvas->Refresh();
@ -352,14 +334,12 @@ void FOOTPRINT_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event )
if( GetScreen()->IsModify() && !GetBoard()->IsEmpty() )
{
KIDIALOG dlg( this, _( "The current footprint contains unsaved changes." ),
_( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
dlg.SetOKLabel( _( "Discard Changes" ) );
dlg.DoNotShowCheckbox();
if( dlg.ShowModal() == wxID_CANCEL )
if( !HandleUnsavedChanges( this, _( "The current footprint has been modified. Save changes?" ),
[&]()->bool { return SaveFootprint( GetBoard()->m_Modules ); } ) )
{
break;
}
}
FOOTPRINT_WIZARD_FRAME* wizard = (FOOTPRINT_WIZARD_FRAME*) Kiway().Player(
FRAME_PCB_FOOTPRINT_WIZARD, true, this );
@ -593,25 +573,14 @@ void FOOTPRINT_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event )
case ID_MODEDIT_EDIT_MODULE:
{
if( GetScreen()->IsModify() && !GetBoard()->IsEmpty() )
{
KIDIALOG dlg( this, _( "The current footprint contains unsaved changes." ),
_( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
dlg.SetOKLabel( _( "Discard Changes" ) );
dlg.DoNotShowCheckbox();
if( dlg.ShowModal() == wxID_CANCEL )
break;
}
LIB_ID partId = m_treePane->GetLibTree()->GetSelectedLibId();
MODULE* module = LoadFootprint( partId );
if( !module )
break;
Clear_Pcb( false );
if( !Clear_Pcb( true ) )
break;
SetCrossHairPosition( wxPoint( 0, 0 ) );
AddModuleToBoard( module );

View File

@ -100,10 +100,12 @@ bool FOOTPRINT_EDIT_FRAME::Clear_Pcb( bool aQuery )
{
wxSafeYield( this, true ); // Allow frame to come to front before showing warning.
if( !IsOK( this,
_( "Current Footprint will be lost and this operation cannot be undone. Continue ?" ) ) )
if( !HandleUnsavedChanges( this, _( "The current footprint has been modified. Save changes?" ),
[&]()->bool { return SaveFootprint( GetBoard()->m_Modules ); } ) )
{
return false;
}
}
// Clear undo and redo lists because we want a full deletion
GetScreen()->ClearUndoRedoList();

View File

@ -147,6 +147,7 @@ bool FOOTPRINT_EDIT_FRAME::Load_Module_From_BOARD( MODULE* aModule )
if( IsGalCanvasActive() )
updateView();
m_canvas->Refresh();
return true;
}

View File

@ -590,19 +590,11 @@ void PCB_EDIT_FRAME::OnCloseWindow( wxCloseEvent& Event )
{
wxString msg = _( "Save changes to\n\"%s\"\nbefore closing?" );
switch( UnsavedChangesDialog( this, wxString::Format( msg, GetBoard()->GetFileName() ) ) )
if( !HandleUnsavedChanges( this, wxString::Format( msg, GetBoard()->GetFileName() ),
[&]()->bool { return Files_io_from_id( ID_SAVE_BOARD ); } ) )
{
default:
case wxID_CANCEL:
Event.Veto();
return;
case wxID_NO:
break;
case wxID_YES:
Files_io_from_id( ID_SAVE_BOARD );
break;
}
}

View File

@ -839,7 +839,7 @@ public:
* ID_SAVE_BOARD_AS
* Files_io_from_id prepare parameters and calls the specialized function
*/
void Files_io_from_id( int aId );
bool Files_io_from_id( int aId );
/**
* Function OpenProjectFiles (was LoadOnePcbFile)