diff options
Diffstat (limited to 'common/basicframe.cpp')
-rw-r--r-- | common/basicframe.cpp | 758 |
1 files changed, 758 insertions, 0 deletions
diff --git a/common/basicframe.cpp b/common/basicframe.cpp new file mode 100644 index 0000000..fad5e64 --- /dev/null +++ b/common/basicframe.cpp @@ -0,0 +1,758 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr + * Copyright (C) 2013-2015 Wayne Stambaugh <stambaughw@verizon.net> + * Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/** + * @file basicframe.cpp + * @brief EDA_BASE_FRAME class implementation. + */ +#include <config.h> + +// kicad_curl.h must be included before wx headers, to avoid +// conflicts for some defines, at least on Windows +#ifdef BUILD_GITHUB_PLUGIN +#include <curl/curlver.h> +#include <kicad_curl/kicad_curl.h> +#endif + +#include <wx/aboutdlg.h> +#include <wx/fontdlg.h> +#include <wx/clipbrd.h> +#include <wx/statline.h> +#include <wx/platinfo.h> +#include <wx/stdpaths.h> + +#include <build_version.h> +#include <fctsys.h> +#include <pgm_base.h> +#include <kiface_i.h> +#include <online_help.h> +#include <id.h> +#include <eda_doc.h> +#include <wxstruct.h> +#include <macros.h> +#include <menus_helpers.h> +#include <dialog_shim.h> + +#include <boost/version.hpp> +#include <typeinfo> +#include <wx/display.h> + +/// The default auto save interval is 10 minutes. +#define DEFAULT_AUTO_SAVE_INTERVAL 600 + + +const wxChar traceAutoSave[] = wxT( "KicadAutoSave" ); + +/// Configuration file entry name for auto save interval. +static const wxChar entryAutoSaveInterval[] = wxT( "AutoSaveInterval" ); + +/// Configuration file entry for wxAuiManger perspective. +static const wxChar entryPerspective[] = wxT( "Perspective" ); + +/// Configuration file entry for most recently used path. +static const wxChar entryMruPath[] = wxT( "MostRecentlyUsedPath" ); + + +EDA_BASE_FRAME::EDA_BASE_FRAME( wxWindow* aParent, FRAME_T aFrameType, + const wxString& aTitle, const wxPoint& aPos, const wxSize& aSize, + long aStyle, const wxString& aFrameName ) : + wxFrame( aParent, wxID_ANY, aTitle, aPos, aSize, aStyle, aFrameName ) +{ + wxSize minsize; + + m_Ident = aFrameType; + m_mainToolBar = NULL; + m_hasAutoSave = false; + m_autoSaveState = false; + m_autoSaveInterval = -1; + m_autoSaveTimer = new wxTimer( this, ID_AUTO_SAVE_TIMER ); + m_mruPath = wxStandardPaths::Get().GetDocumentsDir(); + minsize.x = 470; + minsize.y = 350; + + SetSizeHints( minsize.x, minsize.y, -1, -1, -1, -1 ); + + if( ( aSize.x < minsize.x ) || ( aSize.y < minsize.y ) ) + SetSize( 0, 0, minsize.x, minsize.y ); + + // Create child subwindows. + + // Dimensions of the user area of the main window. + GetClientSize( &m_FrameSize.x, &m_FrameSize.y ); + + m_FramePos.x = m_FramePos.y = 0; + + Connect( ID_HELP_COPY_VERSION_STRING, + wxEVT_COMMAND_MENU_SELECTED, + wxCommandEventHandler( EDA_BASE_FRAME::CopyVersionInfoToClipboard ) ); + + Connect( ID_AUTO_SAVE_TIMER, wxEVT_TIMER, + wxTimerEventHandler( EDA_BASE_FRAME::onAutoSaveTimer ) ); + + // hook wxEVT_CLOSE_WINDOW so we can call SaveSettings(). This function seems + // to be called before any other hook for wxCloseEvent, which is necessary. + Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( EDA_BASE_FRAME::windowClosing ) ); +} + + +void EDA_BASE_FRAME::windowClosing( wxCloseEvent& event ) +{ + DIALOG_SHIM* dlg = NULL; + wxWindowList list = GetChildren(); + + // Quasi modal dialogs create issues (crashes) when closing Kicad. + // I am guessing they are delete too late, when deleting main frames. + // AFAIK, only these DIALOG_SHIM dialogs create such issues. + // The policy is do not allow closing Kicad if a Quasi modal dialog is open. + // (Anyway, closing without prompting the user is certainly bad, + // because an edit is in preogress) + // Therefore, iterate through the child list to find at least + // a DIALOG_SHIM opened in quasi modal mode + for( wxWindowList::iterator iter = list.begin(); iter != list.end(); ++iter ) + { + if( (dlg = dynamic_cast<DIALOG_SHIM*> (*iter) ) != NULL ) + { + if( dlg->IsQuasiModal() ) + break; + else + dlg = NULL; + } + } + + if( dlg ) + { + // Happens when a quasi modal dialog is currently open. + // For example: if the Kicad manager try to close Kicad. + wxMessageBox( _( + "The program cannot be closed\n" + "A quasi-modal dialog window is currently open, please close it first." ) ); + event.Veto(); + return; + } + + wxConfigBase* cfg = config(); + + if( cfg ) + SaveSettings( cfg ); // virtual, wxFrame specific + + event.Skip(); // we did not "handle" the event, only eavesdropped on it. +} + + +EDA_BASE_FRAME::~EDA_BASE_FRAME() +{ + delete m_autoSaveTimer; + + // This is needed for OSX: avoids further OnDraw processing after this + // destructor and before the native window is destroyed + this->Freeze(); +} + + +bool EDA_BASE_FRAME::ProcessEvent( wxEvent& aEvent ) +{ + if( !wxFrame::ProcessEvent( aEvent ) ) + return false; + + if( IsShown() && m_hasAutoSave && + (m_autoSaveState != isAutoSaveRequired()) && (m_autoSaveInterval > 0) ) + { + if( !m_autoSaveState ) + { + wxLogTrace( traceAutoSave, wxT( "Starting auto save timer." ) ); + m_autoSaveTimer->Start( m_autoSaveInterval * 1000, wxTIMER_ONE_SHOT ); + m_autoSaveState = true; + } + else if( m_autoSaveTimer->IsRunning() ) + { + wxLogTrace( traceAutoSave, wxT( "Stopping auto save timer." ) ); + m_autoSaveTimer->Stop(); + m_autoSaveState = false; + } + } + + return true; +} + + +bool EDA_BASE_FRAME::Enable( bool enable ) +{ + // so we can do logging of this state change: + +#if defined(DEBUG) + const char* type_id = typeid( *this ).name(); + printf( "wxFrame %-28s: %s\n", type_id, enable ? "enabled" : "disabled" ); +#endif + + return wxFrame::Enable( enable ); +} + + +void EDA_BASE_FRAME::onAutoSaveTimer( wxTimerEvent& aEvent ) +{ + if( !doAutoSave() ) + m_autoSaveTimer->Start( m_autoSaveInterval * 1000, wxTIMER_ONE_SHOT ); +} + + +bool EDA_BASE_FRAME::doAutoSave() +{ + wxCHECK_MSG( false, true, wxT( "Auto save timer function not overridden. Bad programmer!" ) ); +} + + +void EDA_BASE_FRAME::ReCreateMenuBar() +{ +} + + +void EDA_BASE_FRAME::ShowChangedLanguage() +{ + ReCreateMenuBar(); + GetMenuBar()->Refresh(); +} + + +void EDA_BASE_FRAME::LoadSettings( wxConfigBase* aCfg ) +{ + int maximized = 0; + + wxString baseCfgName = ConfigBaseName(); + + wxString text = baseCfgName + wxT( "Pos_x" ); + aCfg->Read( text, &m_FramePos.x ); + + text = baseCfgName + wxT( "Pos_y" ); + aCfg->Read( text, &m_FramePos.y ); + + text = baseCfgName + wxT( "Size_x" ); + aCfg->Read( text, &m_FrameSize.x, 600 ); + + text = baseCfgName + wxT( "Size_y" ); + aCfg->Read( text, &m_FrameSize.y, 400 ); + + text = baseCfgName + wxT( "Maximized" ); + aCfg->Read( text, &maximized, 0 ); + + if( m_hasAutoSave ) + { + text = baseCfgName + entryAutoSaveInterval; + aCfg->Read( text, &m_autoSaveInterval, DEFAULT_AUTO_SAVE_INTERVAL ); + } + + // Ensure the window is on a connected display, and is visible. + // (at least a corner of the frame must be visible on screen) + // Sometimes, if a window was moved on an auxiliary display, and when this + // display is no more available, it is not the case. + wxRect rect( m_FramePos, m_FrameSize ); + + if( wxDisplay::GetFromPoint( rect.GetTopLeft() ) == wxNOT_FOUND && + wxDisplay::GetFromPoint( rect.GetTopRight() ) == wxNOT_FOUND && + wxDisplay::GetFromPoint( rect.GetBottomLeft() ) == wxNOT_FOUND && + wxDisplay::GetFromPoint( rect.GetBottomRight() ) == wxNOT_FOUND ) + { + m_FramePos = wxDefaultPosition; + } + + // Ensure Window title bar is visible +#if defined( __WXMAC__ ) + // for macOSX, the window must be below system (macOSX) toolbar + // Ypos_min = GetMBarHeight(); seems no more exist in new API (subject to change) + int Ypos_min = 20; +#else + int Ypos_min = 0; +#endif + if( m_FramePos.y < Ypos_min ) + m_FramePos.y = Ypos_min; + + if( maximized ) + Maximize(); + + aCfg->Read( baseCfgName + entryPerspective, &m_perspective ); + aCfg->Read( baseCfgName + entryMruPath, &m_mruPath ); +} + + +void EDA_BASE_FRAME::SaveSettings( wxConfigBase* aCfg ) +{ + wxString text; + + if( IsIconized() ) + return; + + wxString baseCfgName = ConfigBaseName(); + + m_FrameSize = GetSize(); + m_FramePos = GetPosition(); + + text = baseCfgName + wxT( "Pos_x" ); + aCfg->Write( text, (long) m_FramePos.x ); + + text = baseCfgName + wxT( "Pos_y" ); + aCfg->Write( text, (long) m_FramePos.y ); + + text = baseCfgName + wxT( "Size_x" ); + aCfg->Write( text, (long) m_FrameSize.x ); + + text = baseCfgName + wxT( "Size_y" ); + aCfg->Write( text, (long) m_FrameSize.y ); + + text = baseCfgName + wxT( "Maximized" ); + aCfg->Write( text, IsMaximized() ); + + if( m_hasAutoSave ) + { + text = baseCfgName + entryAutoSaveInterval; + aCfg->Write( text, m_autoSaveInterval ); + } + + // Once this is fully implemented, wxAuiManager will be used to maintain + // the persistance of the main frame and all it's managed windows and + // all of the legacy frame persistence position code can be removed. + wxString perspective = m_auimgr.SavePerspective(); + + // printf( "perspective(%s): %s\n", + // TO_UTF8( m_FrameName + entryPerspective ), TO_UTF8( perspective ) ); + aCfg->Write( baseCfgName + entryPerspective, perspective ); + aCfg->Write( baseCfgName + entryMruPath, m_mruPath ); +} + + +wxConfigBase* EDA_BASE_FRAME::config() +{ + // KICAD_MANAGER_FRAME overrides this + wxConfigBase* ret = Kiface().KifaceSettings(); + //wxASSERT( ret ); + return ret; +} + + +const SEARCH_STACK& EDA_BASE_FRAME::sys_search() +{ + return Kiface().KifaceSearch(); +} + + +wxString EDA_BASE_FRAME::help_name() +{ + return Kiface().GetHelpFileName(); +} + + +void EDA_BASE_FRAME::PrintMsg( const wxString& text ) +{ + SetStatusText( text ); +} + + +void EDA_BASE_FRAME::UpdateFileHistory( const wxString& FullFileName, + wxFileHistory* aFileHistory ) +{ + wxFileHistory* fileHistory = aFileHistory; + + if( !fileHistory ) + fileHistory = &Kiface().GetFileHistory(); + + fileHistory->AddFileToHistory( FullFileName ); +} + + +wxString EDA_BASE_FRAME::GetFileFromHistory( int cmdId, const wxString& type, + wxFileHistory* aFileHistory ) +{ + wxFileHistory* fileHistory = aFileHistory; + + if( !fileHistory ) + fileHistory = &Kiface().GetFileHistory(); + + int baseId = fileHistory->GetBaseId(); + + wxASSERT( cmdId >= baseId && cmdId < baseId + (int) fileHistory->GetCount() ); + + unsigned i = cmdId - baseId; + + if( i < fileHistory->GetCount() ) + { + wxString fn = fileHistory->GetHistoryFile( i ); + + if( wxFileName::FileExists( fn ) ) + return fn; + else + { + wxString msg = wxString::Format( + wxT( "file '%s' was not found." ), + GetChars( fn ) ); + + wxMessageBox( msg ); + + fileHistory->RemoveFileFromHistory( i ); + } + } + + return wxEmptyString; +} + + +void EDA_BASE_FRAME::GetKicadHelp( wxCommandEvent& event ) +{ + const SEARCH_STACK& search = sys_search(); + + /* We have to get document for beginners, + * or the full specific doc + * if event id is wxID_INDEX, we want the document for beginners. + * else the specific doc file (its name is in Kiface().GetHelpFileName()) + * The document for beginners is the same for all KiCad utilities + */ + if( event.GetId() == wxID_INDEX ) + { + // List of possible names for Getting Started in KiCad + const wxChar* names[2] = { + wxT( "getting_started_in_kicad" ), + wxT( "Getting_Started_in_KiCad" ) + }; + + wxString helpFile; + // Search for "getting_started_in_kicad.html" or "getting_started_in_kicad.pdf" + // or "Getting_Started_in_KiCad.html" or "Getting_Started_in_KiCad.pdf" + for( unsigned ii = 0; ii < DIM( names ); ii++ ) + { + helpFile = SearchHelpFileFullPath( search, names[ii] ); + + if( !helpFile.IsEmpty() ) + break; + } + + if( !helpFile ) + { + wxString msg = wxString::Format( _( + "Html or pdf help file \n'%s'\n or\n'%s' could not be found." ), names[0], names[1] ); + wxMessageBox( msg ); + } + else + { + GetAssociatedDocument( this, helpFile ); + } + + return; + } + + wxString base_name = help_name(); + wxString helpFile = SearchHelpFileFullPath( search, base_name ); + + if( !helpFile ) + { + wxString msg = wxString::Format( _( + "Help file '%s' could not be found." ), + GetChars( base_name ) + ); + wxMessageBox( msg ); + } + else + { + GetAssociatedDocument( this, helpFile ); + } +} + + +void EDA_BASE_FRAME::OnSelectPreferredEditor( wxCommandEvent& event ) +{ + // Ask for the current editor and instruct GetEditorName() to not show + // unless we pass false as argument. + wxString editorname = Pgm().GetEditorName( false ); + + // Ask the user to select a new editor, but suggest the current one as the default. + editorname = Pgm().AskUserForPreferredEditor( editorname ); + + // If we have a new editor name request it to be copied to m_editor_name and saved + // to the preferences file. If the user cancelled the dialog then the previous + // value will be retained. + if( !editorname.IsEmpty() ) + Pgm().SetEditorName( editorname ); +} + + +void EDA_BASE_FRAME::GetKicadAbout( wxCommandEvent& event ) +{ + bool ShowAboutDialog(wxWindow * parent); + ShowAboutDialog( this ); +} + + +void EDA_BASE_FRAME::AddHelpVersionInfoMenuEntry( wxMenu* aMenu ) +{ + wxASSERT( aMenu != NULL ); + + // Copy version string to clipboard for bug report purposes. + AddMenuItem( aMenu, ID_HELP_COPY_VERSION_STRING, + _( "Copy &Version Information" ), + _( "Copy the version string to clipboard to send with bug reports" ), + KiBitmap( copy_button_xpm ) ); +} + + +// This is an enhanced version of the compiler build macro provided by wxWidgets +// in <wx/build.h>. Please do not make any of these strings translatable. They +// are used for conveying troubleshooting information to developers. + +#if defined(__GXX_ABI_VERSION) + #define __ABI_VERSION ",compiler with C++ ABI " __WX_BO_STRINGIZE(__GXX_ABI_VERSION) +#else + #define __ABI_VERSION ",compiler without C++ ABI " +#endif + +#if defined(__INTEL_COMPILER) + #define __BO_COMPILER ",Intel C++" +#elif defined(__GNUG__) + #define __BO_COMPILER ",GCC " \ + __WX_BO_STRINGIZE(__GNUC__) "." \ + __WX_BO_STRINGIZE(__GNUC_MINOR__) "." \ + __WX_BO_STRINGIZE(__GNUC_PATCHLEVEL__) +#elif defined(__VISUALC__) + #define __BO_COMPILER ",Visual C++" +#elif defined(__BORLANDC__) + #define __BO_COMPILER ",Borland C++" +#elif defined(__DIGITALMARS__) + #define __BO_COMPILER ",DigitalMars" +#elif defined(__WATCOMC__) + #define __BO_COMPILER ",Watcom C++" +#else + #define __BO_COMPILER ",unknown" +#endif + + +static inline const char* KICAD_BUILD_OPTIONS_SIGNATURE() +{ + return +#ifdef __WXDEBUG__ + " (debug," +#else + " (release," +#endif + __WX_BO_UNICODE __ABI_VERSION __BO_COMPILER __WX_BO_STL + __WX_BO_WXWIN_COMPAT_2_8 ")" + ; +} + + +void EDA_BASE_FRAME::CopyVersionInfoToClipboard( wxCommandEvent& event ) +{ + if( !wxTheClipboard->Open() ) + { + wxMessageBox( _( "Could not open clipboard to write version information." ), + _( "Clipboard Error" ), wxOK | wxICON_EXCLAMATION, this ); + return; + } + + wxString msg_version; + wxPlatformInfo info; + + msg_version = wxT( "Application: " ) + Pgm().App().GetAppName() + wxT( "\n" ); + msg_version << wxT( "Version: " ) << GetBuildVersion() +#ifdef DEBUG + << wxT( " debug" ) +#else + << wxT( " release" ) +#endif + << wxT( " build\n" ); + msg_version << wxT( "wxWidgets: Version " ) << FROM_UTF8( wxVERSION_NUM_DOT_STRING ) + << FROM_UTF8( KICAD_BUILD_OPTIONS_SIGNATURE() ) << wxT( "\n" ) + << wxT( "Platform: " ) << wxGetOsDescription() << wxT( ", " ) + << info.GetArchName() << wxT( ", " ) << info.GetEndiannessName() + << wxT( ", " ) << info.GetPortIdName() << wxT( "\n" ); + + // Just in case someone builds KiCad with the platform native of Boost instead of + // the version included with the KiCad source. + msg_version << wxT( "Boost version: " ) << ( BOOST_VERSION / 100000 ) << wxT( "." ) + << ( BOOST_VERSION / 100 % 1000 ) << wxT( "." ) + << ( BOOST_VERSION % 100 ) << wxT( "\n" ); + +#ifdef BUILD_GITHUB_PLUGIN + // Shows the Curl library version in use: + msg_version << "Curl version: " << KICAD_CURL::GetVersion() << "\n"; +#endif + + msg_version << wxT( " USE_WX_GRAPHICS_CONTEXT=" ); +#ifdef USE_WX_GRAPHICS_CONTEXT + msg_version << wxT( "ON\n" ); +#else + msg_version << wxT( "OFF\n" ); +#endif + + msg_version << wxT( " USE_WX_OVERLAY=" ); +#ifdef USE_WX_OVERLAY + msg_version << wxT( "ON\n" ); +#else + msg_version << wxT( "OFF\n" ); +#endif + + msg_version << wxT( " KICAD_SCRIPTING=" ); +#ifdef KICAD_SCRIPTING + msg_version << wxT( "ON\n" ); +#else + msg_version << wxT( "OFF\n" ); +#endif + + msg_version << wxT( " KICAD_SCRIPTING_MODULES=" ); +#ifdef KICAD_SCRIPTING_MODULES + msg_version << wxT( "ON\n" ); +#else + msg_version << wxT( "OFF\n" ); +#endif + + msg_version << wxT( " KICAD_SCRIPTING_WXPYTHON=" ); +#ifdef KICAD_SCRIPTING_WXPYTHON + msg_version << wxT( "ON\n" ); +#else + msg_version << wxT( "OFF\n" ); +#endif + + msg_version << wxT( " USE_FP_LIB_TABLE=HARD_CODED_ON\n" ); + + msg_version << wxT( " BUILD_GITHUB_PLUGIN=" ); +#ifdef BUILD_GITHUB_PLUGIN + msg_version << wxT( "ON\n" ); +#else + msg_version << wxT( "OFF\n" ); +#endif + + wxTheClipboard->SetData( new wxTextDataObject( msg_version ) ); + wxTheClipboard->Close(); + + wxMessageBox( msg_version, _( "Version Information (copied to the clipboard)" ) ); +} + + +bool EDA_BASE_FRAME::IsWritable( const wxFileName& aFileName ) +{ + wxString msg; + wxFileName fn = aFileName; + + // Check for absence of a file path with a file name. Unfortunately KiCad + // uses paths relative to the current project path without the ./ part which + // confuses wxFileName. Making the file name path absolute may be less than + // elegant but it solves the problem. + if( fn.GetPath().IsEmpty() && fn.HasName() ) + fn.MakeAbsolute(); + + wxCHECK_MSG( fn.IsOk(), false, + wxT( "File name object is invalid. Bad programmer!" ) ); + wxCHECK_MSG( !fn.GetPath().IsEmpty(), false, + wxT( "File name object path <" ) + fn.GetFullPath() + + wxT( "> is not set. Bad programmer!" ) ); + + if( fn.IsDir() && !fn.IsDirWritable() ) + { + msg.Printf( _( "You do not have write permissions to folder <%s>." ), + GetChars( fn.GetPath() ) ); + } + else if( !fn.FileExists() && !fn.IsDirWritable() ) + { + msg.Printf( _( "You do not have write permissions to save file <%s> to folder <%s>." ), + GetChars( fn.GetFullName() ), GetChars( fn.GetPath() ) ); + } + else if( fn.FileExists() && !fn.IsFileWritable() ) + { + msg.Printf( _( "You do not have write permissions to save file <%s>." ), + GetChars( fn.GetFullPath() ) ); + } + + if( !msg.IsEmpty() ) + { + wxMessageBox( msg ); + return false; + } + + return true; +} + + +void EDA_BASE_FRAME::CheckForAutoSaveFile( const wxFileName& aFileName, + const wxString& aBackupFileExtension ) +{ + wxCHECK_RET( aFileName.IsOk(), wxT( "Invalid file name!" ) ); + wxCHECK_RET( !aBackupFileExtension.IsEmpty(), wxT( "Invalid backup file extension!" ) ); + + wxFileName autoSaveFileName = aFileName; + + // Check for auto save file. + autoSaveFileName.SetName( AUTOSAVE_PREFIX_FILENAME + aFileName.GetName() ); + + wxLogTrace( traceAutoSave, + wxT( "Checking for auto save file " ) + autoSaveFileName.GetFullPath() ); + + if( !autoSaveFileName.FileExists() ) + return; + + wxString msg = wxString::Format( _( + "Well this is potentially embarrassing!\n" + "It appears that the last time you were editing the file\n" + "'%s'\n" + "it was not saved properly. Do you wish to restore the last saved edits you made?" ), + GetChars( aFileName.GetFullName() ) + ); + + int response = wxMessageBox( msg, Pgm().App().GetAppName(), wxYES_NO | wxICON_QUESTION, this ); + + // Make a backup of the current file, delete the file, and rename the auto save file to + // the file name. + if( response == wxYES ) + { + // Get the backup file name. + wxFileName backupFileName = aFileName; + backupFileName.SetExt( aBackupFileExtension ); + + // If an old backup file exists, delete it. If an old copy of the file exists, rename + // it to the backup file name + if( aFileName.FileExists() ) + { + // Remove the old file backup file. + if( backupFileName.FileExists() ) + wxRemoveFile( backupFileName.GetFullPath() ); + + // Rename the old file to the backup file name. + if( !wxRenameFile( aFileName.GetFullPath(), backupFileName.GetFullPath() ) ) + { + msg.Printf( _( "Could not create backup file <%s>" ), + GetChars( backupFileName.GetFullPath() ) ); + wxMessageBox( msg ); + } + } + + if( !wxRenameFile( autoSaveFileName.GetFullPath(), aFileName.GetFullPath() ) ) + { + wxMessageBox( _( "The auto save file could not be renamed to the board file name." ), + Pgm().App().GetAppName(), wxOK | wxICON_EXCLAMATION, this ); + } + } + else + { + wxLogTrace( traceAutoSave, + wxT( "Removing auto save file " ) + autoSaveFileName.GetFullPath() ); + + // Remove the auto save file when using the previous file as is. + wxRemoveFile( autoSaveFileName.GetFullPath() ); + } +} + |