2011-10-13 15:56:32 -04:00
|
|
|
/*
|
|
|
|
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
|
|
|
|
*
|
2015-03-17 08:34:02 +01:00
|
|
|
* Copyright (C) 2004-2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
2016-08-11 15:13:47 -04:00
|
|
|
* Copyright (C) 2011-2016 Wayne Stambaugh <stambaughw@verizon.net>
|
2016-05-10 15:07:35 -04:00
|
|
|
* Copyright (C) 2016 KiCad Developers, see AUTHORS.txt for contributors.
|
2011-10-13 15:56:32 -04:00
|
|
|
*
|
|
|
|
|
* 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
|
|
|
|
|
*/
|
|
|
|
|
|
2011-09-23 09:57:12 -04:00
|
|
|
/**
|
|
|
|
|
* @file pcbnew/files.cpp
|
|
|
|
|
* @brief Read and write board files.
|
|
|
|
|
*/
|
2007-06-05 12:10:51 +00:00
|
|
|
|
2012-01-22 22:33:36 -06:00
|
|
|
#include <fctsys.h>
|
|
|
|
|
#include <class_drawpanel.h>
|
|
|
|
|
#include <confirm.h>
|
|
|
|
|
#include <kicad_string.h>
|
|
|
|
|
#include <gestfich.h>
|
|
|
|
|
#include <wxPcbStruct.h>
|
|
|
|
|
#include <macros.h>
|
2016-07-19 13:35:25 -04:00
|
|
|
#include <3d_viewer/eda_3d_viewer.h>
|
2012-01-22 22:33:36 -06:00
|
|
|
#include <richio.h>
|
|
|
|
|
#include <filter_reader.h>
|
2014-03-19 19:42:08 -05:00
|
|
|
#include <pgm_base.h>
|
2013-01-12 12:32:24 -05:00
|
|
|
#include <msgpanel.h>
|
2013-10-13 12:29:20 -04:00
|
|
|
#include <fp_lib_table.h>
|
2015-12-10 16:29:12 +01:00
|
|
|
#include <ratsnest_data.h>
|
2007-06-05 12:10:51 +00:00
|
|
|
|
2012-01-22 22:33:36 -06:00
|
|
|
#include <pcbnew.h>
|
|
|
|
|
#include <pcbnew_id.h>
|
|
|
|
|
#include <io_mgr.h>
|
2012-02-16 21:03:33 +01:00
|
|
|
#include <wildcards_and_files_ext.h>
|
2011-09-23 09:57:12 -04:00
|
|
|
|
2012-01-22 22:33:36 -06:00
|
|
|
#include <class_board.h>
|
2012-04-07 14:05:56 -04:00
|
|
|
#include <build_version.h> // LEGACY_BOARD_FILE_VERSION
|
2013-10-13 12:29:20 -04:00
|
|
|
#include <module_editor_frame.h>
|
|
|
|
|
#include <modview_frame.h>
|
|
|
|
|
|
2015-09-25 15:38:09 -04:00
|
|
|
#include <wx/stdpaths.h>
|
|
|
|
|
|
2011-09-23 09:57:12 -04:00
|
|
|
|
2016-01-14 20:48:44 -05:00
|
|
|
//#define USE_INSTRUMENTATION 1
|
|
|
|
|
#define USE_INSTRUMENTATION 0
|
2013-07-01 01:47:36 -05:00
|
|
|
|
2011-12-05 11:22:19 -06:00
|
|
|
|
2014-08-13 15:28:54 -05:00
|
|
|
static const wxChar backupSuffix[] = wxT( "-bak" );
|
|
|
|
|
static const wxChar autosavePrefix[] = wxT( "_autosave-" );
|
|
|
|
|
|
|
|
|
|
|
2016-08-11 15:13:47 -04:00
|
|
|
wxString PCB_EDIT_FRAME::GetAutoSaveFilePrefix()
|
|
|
|
|
{
|
|
|
|
|
return wxString( autosavePrefix );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2014-08-13 15:28:54 -05:00
|
|
|
/**
|
|
|
|
|
* Function AskLoadBoardFileName
|
|
|
|
|
* puts up a wxFileDialog asking for a BOARD filename to open.
|
|
|
|
|
*
|
|
|
|
|
* @param aParent is a wxFrame passed to wxFileDialog.
|
|
|
|
|
* @param aCtl is where to put the OpenProjectFiles() control bits.
|
|
|
|
|
*
|
|
|
|
|
* @param aFileName on entry is a probable choice, on return is the chosen filename.
|
2016-03-04 19:48:08 +01:00
|
|
|
* @param aKicadFilesOnly true to list kiacad pcb files plugins only, false to list import plugins.
|
2014-08-13 15:28:54 -05:00
|
|
|
*
|
|
|
|
|
* @return bool - true if chosen, else false if user aborted.
|
|
|
|
|
*/
|
2016-03-04 19:48:08 +01:00
|
|
|
bool AskLoadBoardFileName( wxWindow* aParent, int* aCtl, wxString* aFileName, bool aKicadFilesOnly )
|
2014-08-13 15:28:54 -05:00
|
|
|
{
|
|
|
|
|
// This is a subset of all PLUGINs which are trusted to be able to
|
|
|
|
|
// load a BOARD. User may occasionally use the wrong plugin to load a
|
|
|
|
|
// *.brd file (since both legacy and eagle use *.brd extension),
|
|
|
|
|
// but eventually *.kicad_pcb will be more common than legacy *.brd files.
|
|
|
|
|
static const struct
|
|
|
|
|
{
|
|
|
|
|
const wxString& filter;
|
|
|
|
|
IO_MGR::PCB_FILE_T pluginType;
|
|
|
|
|
} loaders[] =
|
|
|
|
|
{
|
2016-03-04 19:48:08 +01:00
|
|
|
{ PcbFileWildcard, IO_MGR::KICAD }, // Current Kicad board files
|
|
|
|
|
{ LegacyPcbFileWildcard, IO_MGR::LEGACY }, // Old Kicad board files
|
|
|
|
|
{ EaglePcbFileWildcard, IO_MGR::EAGLE }, // Import board files
|
|
|
|
|
{ PCadPcbFileWildcard, IO_MGR::PCAD }, // Import board files
|
2014-08-13 15:28:54 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
wxFileName fileName( *aFileName );
|
|
|
|
|
wxString fileFilters;
|
|
|
|
|
|
2016-03-04 19:48:08 +01:00
|
|
|
if( aKicadFilesOnly )
|
|
|
|
|
{
|
|
|
|
|
for( unsigned ii = 0; ii < 2; ++ii )
|
|
|
|
|
{
|
|
|
|
|
if( !fileFilters.IsEmpty() )
|
|
|
|
|
fileFilters += wxChar( '|' );
|
2014-09-24 18:56:20 +02:00
|
|
|
|
2016-03-04 19:48:08 +01:00
|
|
|
fileFilters += wxGetTranslation( loaders[ii].filter );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
2014-08-13 15:28:54 -05:00
|
|
|
{
|
2016-03-04 19:48:08 +01:00
|
|
|
for( unsigned ii = 2; ii < DIM( loaders ); ++ii )
|
|
|
|
|
{
|
|
|
|
|
if( !fileFilters.IsEmpty() )
|
|
|
|
|
fileFilters += wxChar( '|' );
|
2014-08-13 15:28:54 -05:00
|
|
|
|
2016-03-04 19:48:08 +01:00
|
|
|
fileFilters += wxGetTranslation( loaders[ii].filter );
|
|
|
|
|
}
|
2014-08-13 15:28:54 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
wxString path;
|
|
|
|
|
wxString name;
|
|
|
|
|
|
|
|
|
|
if( fileName.FileExists() )
|
|
|
|
|
{
|
|
|
|
|
path = fileName.GetPath();
|
|
|
|
|
name = fileName.GetFullName();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2015-09-25 15:38:09 -04:00
|
|
|
path = wxStandardPaths::Get().GetDocumentsDir();
|
2014-08-13 15:28:54 -05:00
|
|
|
// leave name empty
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-04 19:48:08 +01:00
|
|
|
wxFileDialog dlg( aParent,
|
|
|
|
|
aKicadFilesOnly ? _( "Open Board File" ) : _( "Import Non Kicad Board File" ),
|
|
|
|
|
path, name, fileFilters,
|
2014-08-13 15:28:54 -05:00
|
|
|
wxFD_OPEN | wxFD_FILE_MUST_EXIST );
|
|
|
|
|
|
2016-03-04 19:48:08 +01:00
|
|
|
if( dlg.ShowModal() == wxID_OK )
|
2014-08-13 15:28:54 -05:00
|
|
|
{
|
2016-03-04 19:48:08 +01:00
|
|
|
// For import option, if Eagle (*.brd files), tell OpenProjectFiles() to use Eagle plugin.
|
|
|
|
|
// It's the only special case because of the duplicate use of the *.brd file extension.
|
|
|
|
|
// Other cases are clear because of unique file extensions.
|
|
|
|
|
*aCtl = aKicadFilesOnly ? 0 : KICTL_EAGLE_BRD;
|
2014-08-13 15:28:54 -05:00
|
|
|
*aFileName = dlg.GetPath();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Function AskSaveBoardFileName
|
|
|
|
|
* puts up a wxFileDialog asking for a BOARD filename to save.
|
|
|
|
|
*
|
|
|
|
|
* @param aParent is a wxFrame passed to wxFileDialog.
|
2014-11-02 17:25:04 +01:00
|
|
|
* @param aFileName on entry is a probable choice, on return is the
|
2014-08-13 15:28:54 -05:00
|
|
|
* chosen full filename (includes path).
|
|
|
|
|
*
|
|
|
|
|
* @return bool - true if chosen, else false if user aborted.
|
|
|
|
|
*/
|
|
|
|
|
bool AskSaveBoardFileName( wxWindow* aParent, wxString* aFileName )
|
|
|
|
|
{
|
|
|
|
|
wxString wildcard = wxGetTranslation( PcbFileWildcard );
|
|
|
|
|
wxFileName fn = *aFileName;
|
|
|
|
|
|
|
|
|
|
fn.SetExt( KiCadPcbFileExtension );
|
|
|
|
|
|
|
|
|
|
wxFileDialog dlg( aParent,
|
|
|
|
|
_( "Save Board File As" ),
|
|
|
|
|
fn.GetPath(),
|
|
|
|
|
fn.GetFullName(),
|
|
|
|
|
wildcard,
|
2016-03-04 19:48:08 +01:00
|
|
|
wxFD_SAVE | wxFD_OVERWRITE_PROMPT
|
2014-08-13 15:28:54 -05:00
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if( dlg.ShowModal() != wxID_OK )
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
fn = dlg.GetPath();
|
|
|
|
|
|
|
|
|
|
// always enforce filename extension, user may not have entered it.
|
|
|
|
|
fn.SetExt( KiCadPcbFileExtension );
|
|
|
|
|
|
|
|
|
|
*aFileName = fn.GetFullPath();
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2014-03-19 19:42:08 -05:00
|
|
|
|
2010-04-28 10:06:14 -04:00
|
|
|
|
2011-03-01 14:26:17 -05:00
|
|
|
void PCB_EDIT_FRAME::OnFileHistory( wxCommandEvent& event )
|
2009-01-17 20:31:19 +00:00
|
|
|
{
|
2014-03-19 19:42:08 -05:00
|
|
|
wxString fn = GetFileFromHistory( event.GetId(), _( "Printed circuit board" ) );
|
2009-01-17 20:31:19 +00:00
|
|
|
|
2014-03-19 19:42:08 -05:00
|
|
|
if( !!fn )
|
2009-01-17 20:31:19 +00:00
|
|
|
{
|
2014-03-19 19:42:08 -05:00
|
|
|
int open_ctl = 0;
|
|
|
|
|
|
2011-12-22 08:28:11 -05:00
|
|
|
m_canvas->EndMouseCapture( ID_NO_TOOL_SELECTED, m_canvas->GetDefaultCursor() );
|
2014-03-19 19:42:08 -05:00
|
|
|
|
|
|
|
|
if( !wxFileName::IsFileReadable( fn ) )
|
|
|
|
|
{
|
2016-03-04 19:48:08 +01:00
|
|
|
if( !AskLoadBoardFileName( this, &open_ctl, &fn, true ) )
|
2014-03-19 19:42:08 -05:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
OpenProjectFiles( std::vector<wxString>( 1, fn ), open_ctl );
|
2009-01-17 20:31:19 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2007-08-06 02:02:39 +00:00
|
|
|
|
2011-03-01 14:26:17 -05:00
|
|
|
void PCB_EDIT_FRAME::Files_io( wxCommandEvent& event )
|
2007-06-05 12:10:51 +00:00
|
|
|
{
|
2007-08-06 02:02:39 +00:00
|
|
|
int id = event.GetId();
|
2015-03-17 08:34:02 +01:00
|
|
|
Files_io_from_id( id );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PCB_EDIT_FRAME::Files_io_from_id( int id )
|
|
|
|
|
{
|
2007-08-06 02:02:39 +00:00
|
|
|
wxString msg;
|
|
|
|
|
|
2011-02-09 20:41:46 +02:00
|
|
|
// If an edition is in progress, stop it.
|
|
|
|
|
// For something else than save, get rid of current tool.
|
|
|
|
|
if( id == ID_SAVE_BOARD )
|
2011-12-22 08:28:11 -05:00
|
|
|
m_canvas->EndMouseCapture( -1, m_canvas->GetDefaultCursor() );
|
2011-02-09 20:41:46 +02:00
|
|
|
else
|
2011-12-22 08:28:11 -05:00
|
|
|
m_canvas->EndMouseCapture( ID_NO_TOOL_SELECTED, m_canvas->GetDefaultCursor() );
|
2007-08-06 02:02:39 +00:00
|
|
|
|
|
|
|
|
switch( id )
|
|
|
|
|
{
|
|
|
|
|
case ID_LOAD_FILE:
|
2014-03-19 19:42:08 -05:00
|
|
|
{
|
2016-03-04 19:48:08 +01:00
|
|
|
int open_ctl = 0;
|
2014-08-13 15:28:54 -05:00
|
|
|
wxString fileName = Prj().AbsolutePath( GetBoard()->GetFileName() );
|
2014-03-19 19:42:08 -05:00
|
|
|
|
2016-03-04 19:48:08 +01:00
|
|
|
if( !AskLoadBoardFileName( this, &open_ctl, &fileName, true ) )
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
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 ) )
|
2014-03-19 19:42:08 -05:00
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
OpenProjectFiles( std::vector<wxString>( 1, fileName ), open_ctl );
|
|
|
|
|
}
|
2007-08-06 02:02:39 +00:00
|
|
|
break;
|
|
|
|
|
|
2012-12-21 08:58:51 +01:00
|
|
|
case ID_MENU_READ_BOARD_BACKUP_FILE:
|
|
|
|
|
case ID_MENU_RECOVER_BOARD_AUTOSAVE:
|
2009-04-05 20:49:15 +00:00
|
|
|
{
|
2014-08-13 15:28:54 -05:00
|
|
|
wxFileName currfn = Prj().AbsolutePath( GetBoard()->GetFileName() );
|
2012-12-21 08:58:51 +01:00
|
|
|
wxFileName fn = currfn;
|
2014-03-19 19:42:08 -05:00
|
|
|
|
2012-12-21 08:58:51 +01:00
|
|
|
if( id == ID_MENU_RECOVER_BOARD_AUTOSAVE )
|
|
|
|
|
{
|
2014-03-19 19:42:08 -05:00
|
|
|
wxString rec_name = wxString( autosavePrefix ) + fn.GetName();
|
2012-12-21 08:58:51 +01:00
|
|
|
fn.SetName( rec_name );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2014-03-19 19:42:08 -05:00
|
|
|
wxString backup_ext = fn.GetExt()+ backupSuffix;
|
2012-12-21 08:58:51 +01:00
|
|
|
fn.SetExt( backup_ext );
|
|
|
|
|
}
|
2011-08-26 13:01:17 -04:00
|
|
|
|
2012-05-29 16:01:17 -05:00
|
|
|
if( !fn.FileExists() )
|
|
|
|
|
{
|
2014-03-19 19:42:08 -05:00
|
|
|
msg.Printf( _( "Recovery file '%s' not found." ),
|
2012-12-20 21:20:56 +01:00
|
|
|
GetChars( fn.GetFullPath() ) );
|
2012-05-29 16:01:17 -05:00
|
|
|
DisplayInfoMessage( this, msg );
|
2007-08-06 02:02:39 +00:00
|
|
|
break;
|
2012-05-29 16:01:17 -05:00
|
|
|
}
|
2009-04-05 20:49:15 +00:00
|
|
|
|
2014-03-19 19:42:08 -05:00
|
|
|
msg.Printf( _( "OK to load recovery or backup file '%s'" ),
|
2012-12-21 08:58:51 +01:00
|
|
|
GetChars(fn.GetFullPath() ) );
|
|
|
|
|
|
|
|
|
|
if( !IsOK( this, msg ) )
|
|
|
|
|
break;
|
2012-05-29 16:01:17 -05:00
|
|
|
|
2012-12-21 08:58:51 +01:00
|
|
|
GetScreen()->ClrModify(); // do not prompt the user for changes
|
2014-03-19 19:42:08 -05:00
|
|
|
|
|
|
|
|
// LoadOnePcbFile( fn.GetFullPath(), aAppend=false, aForceFileDialog=false );
|
|
|
|
|
OpenProjectFiles( std::vector<wxString>( 1, fn.GetFullPath() ) );
|
2012-08-29 18:59:50 +02:00
|
|
|
|
2012-12-21 08:58:51 +01:00
|
|
|
// Re-set the name since name or extension was changed
|
|
|
|
|
GetBoard()->SetFileName( currfn.GetFullPath() );
|
2012-05-29 16:01:17 -05:00
|
|
|
UpdateTitle();
|
|
|
|
|
}
|
2007-08-06 02:02:39 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ID_APPEND_FILE:
|
2014-03-19 19:42:08 -05:00
|
|
|
{
|
|
|
|
|
int open_ctl;
|
|
|
|
|
wxString fileName;
|
|
|
|
|
|
2014-09-24 18:56:20 +02:00
|
|
|
if( !AskLoadBoardFileName( this, &open_ctl, &fileName, true ) )
|
2014-03-19 19:42:08 -05:00
|
|
|
break;
|
|
|
|
|
|
2014-08-13 15:28:54 -05:00
|
|
|
AppendBoardFile( fileName, open_ctl );
|
2014-09-24 18:56:20 +02:00
|
|
|
|
|
|
|
|
m_canvas->Refresh();
|
2014-03-19 19:42:08 -05:00
|
|
|
}
|
2007-08-06 02:02:39 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ID_NEW_BOARD:
|
2015-09-25 15:38:09 -04:00
|
|
|
{
|
|
|
|
|
if( !Clear_Pcb( true ) )
|
|
|
|
|
break;
|
2013-10-13 12:29:20 -04:00
|
|
|
|
2015-09-25 15:38:09 -04:00
|
|
|
wxFileName fn( wxStandardPaths::Get().GetDocumentsDir(), wxT( "noname" ),
|
|
|
|
|
ProjectFileExtension );
|
2014-03-19 19:42:08 -05:00
|
|
|
|
2015-09-25 15:38:09 -04:00
|
|
|
Prj().SetProjectFullName( fn.GetFullPath() );
|
2014-03-19 19:42:08 -05:00
|
|
|
|
2015-09-25 15:38:09 -04:00
|
|
|
fn.SetExt( PcbFileExtension );
|
2014-03-19 19:42:08 -05:00
|
|
|
|
2015-09-25 15:38:09 -04:00
|
|
|
GetBoard()->SetFileName( fn.GetFullPath() );
|
|
|
|
|
UpdateTitle();
|
|
|
|
|
ReCreateLayerBox();
|
2016-07-19 13:35:25 -04:00
|
|
|
OnModify();
|
2007-08-06 02:02:39 +00:00
|
|
|
break;
|
2015-09-25 15:38:09 -04:00
|
|
|
}
|
2007-08-06 02:02:39 +00:00
|
|
|
|
|
|
|
|
case ID_SAVE_BOARD:
|
2014-09-14 19:12:56 +02:00
|
|
|
if( ! GetBoard()->GetFileName().IsEmpty() )
|
|
|
|
|
{
|
|
|
|
|
SavePcbFile( Prj().AbsolutePath( GetBoard()->GetFileName() ) );
|
|
|
|
|
break;
|
|
|
|
|
}
|
2015-03-17 08:34:02 +01:00
|
|
|
// Fall through
|
|
|
|
|
case ID_COPY_BOARD_AS:
|
|
|
|
|
case ID_SAVE_BOARD_AS:
|
2014-08-13 15:28:54 -05:00
|
|
|
{
|
|
|
|
|
wxString pro_dir = wxPathOnly( Prj().GetProjectFullName() );
|
|
|
|
|
wxFileName fn( pro_dir, _( "noname" ), KiCadPcbFileExtension );
|
|
|
|
|
wxString filename = fn.GetFullPath();
|
|
|
|
|
|
|
|
|
|
if( AskSaveBoardFileName( this, &filename ) )
|
2015-02-14 13:43:11 +01:00
|
|
|
{
|
|
|
|
|
if( id == ID_COPY_BOARD_AS )
|
|
|
|
|
SavePcbCopy( filename );
|
|
|
|
|
else
|
|
|
|
|
SavePcbFile( filename, NO_BACKUP_FILE );
|
|
|
|
|
}
|
2014-08-13 15:28:54 -05:00
|
|
|
}
|
2007-08-06 02:02:39 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
2014-08-13 15:28:54 -05:00
|
|
|
DisplayError( this, wxT( "File_io Internal Error" ) );
|
|
|
|
|
break;
|
2007-08-06 02:02:39 +00:00
|
|
|
}
|
2007-06-05 12:10:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2014-08-13 15:28:54 -05:00
|
|
|
// The KIWAY_PLAYER::OpenProjectFiles() API knows nothing about plugins, so
|
|
|
|
|
// determine how to load the BOARD here, with minor assistance from KICTL_EAGLE_BRD
|
|
|
|
|
// bit flag.
|
2014-09-24 18:56:20 +02:00
|
|
|
IO_MGR::PCB_FILE_T plugin_type( const wxString& aFileName, int aCtl )
|
2007-06-05 12:10:51 +00:00
|
|
|
{
|
2014-08-13 15:28:54 -05:00
|
|
|
IO_MGR::PCB_FILE_T pluginType;
|
2008-04-29 03:18:02 +00:00
|
|
|
|
2014-08-13 15:28:54 -05:00
|
|
|
wxFileName fn = aFileName;
|
2014-03-19 19:42:08 -05:00
|
|
|
|
2016-02-19 15:10:23 +01:00
|
|
|
// Note: file extensions are expected to be in ower case.
|
|
|
|
|
// This is not always true, especially when importing files, so the string
|
|
|
|
|
// comparisons are case insensitive to try to find the suitable plugin.
|
|
|
|
|
|
|
|
|
|
if( fn.GetExt().CmpNoCase( IO_MGR::GetFileExtension( IO_MGR::LEGACY ) ) == 0 )
|
2007-08-06 02:02:39 +00:00
|
|
|
{
|
2014-08-13 15:28:54 -05:00
|
|
|
// both legacy and eagle share a common file extension.
|
|
|
|
|
pluginType = ( aCtl & KICTL_EAGLE_BRD ) ? IO_MGR::EAGLE : IO_MGR::LEGACY;
|
2014-03-19 19:42:08 -05:00
|
|
|
}
|
2016-02-19 15:10:23 +01:00
|
|
|
else if( fn.GetExt().CmpNoCase( IO_MGR::GetFileExtension( IO_MGR::LEGACY ) + backupSuffix ) == 0 )
|
2014-03-19 19:42:08 -05:00
|
|
|
{
|
2014-08-13 15:28:54 -05:00
|
|
|
pluginType = IO_MGR::LEGACY;
|
2014-03-19 19:42:08 -05:00
|
|
|
}
|
2016-02-19 15:10:23 +01:00
|
|
|
else if( fn.GetExt().CmpNoCase( IO_MGR::GetFileExtension( IO_MGR::PCAD ) ) == 0 )
|
2014-03-19 19:42:08 -05:00
|
|
|
{
|
2014-08-13 15:28:54 -05:00
|
|
|
pluginType = IO_MGR::PCAD;
|
2014-03-19 19:42:08 -05:00
|
|
|
}
|
2014-08-13 15:28:54 -05:00
|
|
|
else
|
2016-02-19 15:10:23 +01:00
|
|
|
{
|
2014-08-13 15:28:54 -05:00
|
|
|
pluginType = IO_MGR::KICAD;
|
2016-02-19 15:10:23 +01:00
|
|
|
}
|
2009-09-22 12:27:57 +00:00
|
|
|
|
2014-08-13 15:28:54 -05:00
|
|
|
return pluginType;
|
|
|
|
|
}
|
2009-09-22 12:27:57 +00:00
|
|
|
|
2014-03-19 19:42:08 -05:00
|
|
|
|
|
|
|
|
bool PCB_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, int aCtl )
|
|
|
|
|
{
|
2014-08-13 15:28:54 -05:00
|
|
|
// This is for python:
|
|
|
|
|
if( aFileSet.size() != 1 )
|
|
|
|
|
{
|
|
|
|
|
UTF8 msg = StrPrintf( "Pcbnew:%s() takes only a single filename", __func__ );
|
|
|
|
|
DisplayError( this, msg );
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
wxString fullFileName( aFileSet[0] );
|
2014-03-19 19:42:08 -05:00
|
|
|
|
2014-08-13 15:28:54 -05:00
|
|
|
// We insist on caller sending us an absolute path, if it does not, we say it's a bug.
|
|
|
|
|
wxASSERT_MSG( wxFileName( fullFileName ).IsAbsolute(),
|
|
|
|
|
wxT( "bug in single_top.cpp or project manager." ) );
|
2014-03-19 19:42:08 -05:00
|
|
|
|
2014-09-07 15:01:26 -04:00
|
|
|
if( !LockFile( fullFileName ) )
|
2014-08-13 15:28:54 -05:00
|
|
|
{
|
|
|
|
|
wxString msg = wxString::Format( _(
|
|
|
|
|
"PCB file '%s' is already open." ),
|
|
|
|
|
GetChars( fullFileName )
|
|
|
|
|
);
|
|
|
|
|
DisplayError( this, msg );
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2014-03-19 19:42:08 -05:00
|
|
|
|
2014-08-13 15:28:54 -05:00
|
|
|
if( GetScreen()->IsModify() )
|
2014-03-19 19:42:08 -05:00
|
|
|
{
|
|
|
|
|
int response = YesNoCancelDialog( this, _(
|
2014-08-13 15:28:54 -05:00
|
|
|
"The current board has been modified. Do you wish to save the changes?" ),
|
2014-03-19 19:42:08 -05:00
|
|
|
wxEmptyString,
|
|
|
|
|
_( "Save and Load" ),
|
|
|
|
|
_( "Load Without Saving" )
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if( response == wxID_CANCEL )
|
2009-09-22 12:27:57 +00:00
|
|
|
return false;
|
2014-03-19 19:42:08 -05:00
|
|
|
else if( response == wxID_YES )
|
2015-02-14 13:43:11 +01:00
|
|
|
SavePcbFile( GetBoard()->GetFileName(), CREATE_BACKUP_FILE );
|
2014-08-13 15:28:54 -05:00
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// response == wxID_NO, fall thru
|
|
|
|
|
}
|
2014-03-19 19:42:08 -05:00
|
|
|
}
|
2009-09-22 12:27:57 +00:00
|
|
|
|
2014-08-13 15:28:54 -05:00
|
|
|
wxFileName pro = fullFileName;
|
|
|
|
|
pro.SetExt( ProjectFileExtension );
|
2014-03-19 19:42:08 -05:00
|
|
|
|
2014-08-13 15:28:54 -05:00
|
|
|
bool is_new = !wxFileName::IsFileReadable( fullFileName );
|
2014-03-19 19:42:08 -05:00
|
|
|
|
2014-08-13 15:28:54 -05:00
|
|
|
// If its a non-existent schematic and caller thinks it exists
|
|
|
|
|
if( is_new && !( aCtl & KICTL_CREATE ) )
|
2014-03-19 19:42:08 -05:00
|
|
|
{
|
2014-08-13 15:28:54 -05:00
|
|
|
// notify user that fullFileName does not exist, ask if user wants to create it.
|
|
|
|
|
wxString ask = wxString::Format( _(
|
|
|
|
|
"Board '%s' does not exist. Do you wish to create it?" ),
|
|
|
|
|
GetChars( fullFileName )
|
|
|
|
|
);
|
|
|
|
|
if( !IsOK( this, ask ) )
|
|
|
|
|
return false;
|
2014-03-19 19:42:08 -05:00
|
|
|
}
|
2008-04-29 03:18:02 +00:00
|
|
|
|
2014-08-13 15:28:54 -05:00
|
|
|
Clear_Pcb( false ); // pass false since we prompted above for a modified board
|
|
|
|
|
|
|
|
|
|
IO_MGR::PCB_FILE_T pluginType = plugin_type( fullFileName, aCtl );
|
|
|
|
|
|
|
|
|
|
bool converted = pluginType != IO_MGR::LEGACY && pluginType != IO_MGR::KICAD;
|
2012-05-29 16:01:17 -05:00
|
|
|
|
2014-08-13 15:28:54 -05:00
|
|
|
if( !converted )
|
2013-01-04 18:47:59 +01:00
|
|
|
{
|
2014-08-13 15:28:54 -05:00
|
|
|
// PROJECT::SetProjectFullName() is an impactful function. It should only be
|
|
|
|
|
// called under carefully considered circumstances.
|
2008-04-29 03:18:02 +00:00
|
|
|
|
2014-08-13 15:28:54 -05:00
|
|
|
// The calling code should know not to ask me here to change projects unless
|
|
|
|
|
// it knows what consequences that will have on other KIFACEs running and using
|
|
|
|
|
// this same PROJECT. It can be very harmful if that calling code is stupid.
|
|
|
|
|
Prj().SetProjectFullName( pro.GetFullPath() );
|
2007-08-06 02:02:39 +00:00
|
|
|
|
2014-08-13 15:28:54 -05:00
|
|
|
// load project settings before BOARD
|
|
|
|
|
LoadProjectSettings();
|
|
|
|
|
}
|
2007-08-06 02:02:39 +00:00
|
|
|
|
2014-08-13 15:28:54 -05:00
|
|
|
if( is_new )
|
2011-11-28 21:08:14 -06:00
|
|
|
{
|
2014-08-13 15:28:54 -05:00
|
|
|
OnModify();
|
2011-11-28 21:08:14 -06:00
|
|
|
}
|
2011-12-14 20:24:52 -06:00
|
|
|
else
|
|
|
|
|
{
|
2014-08-13 15:28:54 -05:00
|
|
|
BOARD* loadedBoard = 0; // it will be set to non-NULL if loaded OK
|
2011-12-14 20:24:52 -06:00
|
|
|
|
2014-08-13 15:28:54 -05:00
|
|
|
PLUGIN::RELEASER pi( IO_MGR::PluginFind( pluginType ) );
|
2011-11-28 21:08:14 -06:00
|
|
|
|
2014-08-13 15:28:54 -05:00
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
PROPERTIES props;
|
|
|
|
|
char xbuf[30];
|
|
|
|
|
char ybuf[30];
|
2012-06-01 02:39:32 -05:00
|
|
|
|
2014-08-13 15:28:54 -05:00
|
|
|
// EAGLE_PLUGIN can use this info to center the BOARD, but it does not yet.
|
|
|
|
|
sprintf( xbuf, "%d", GetPageSizeIU().x );
|
|
|
|
|
sprintf( ybuf, "%d", GetPageSizeIU().y );
|
2013-09-24 16:23:13 -05:00
|
|
|
|
2014-08-13 15:28:54 -05:00
|
|
|
props["page_width"] = xbuf;
|
|
|
|
|
props["page_height"] = ybuf;
|
2012-06-01 02:39:32 -05:00
|
|
|
|
2013-07-01 01:47:36 -05:00
|
|
|
#if USE_INSTRUMENTATION
|
2014-08-13 15:28:54 -05:00
|
|
|
// measure the time to load a BOARD.
|
|
|
|
|
unsigned startTime = GetRunningMicroSecs();
|
2013-06-30 20:05:40 -05:00
|
|
|
#endif
|
|
|
|
|
|
2014-08-13 15:28:54 -05:00
|
|
|
loadedBoard = pi->Load( fullFileName, NULL, &props );
|
2012-08-29 18:59:50 +02:00
|
|
|
|
2013-07-01 01:47:36 -05:00
|
|
|
#if USE_INSTRUMENTATION
|
2014-08-13 15:28:54 -05:00
|
|
|
unsigned stopTime = GetRunningMicroSecs();
|
|
|
|
|
printf( "PLUGIN::Load(): %u usecs\n", stopTime - startTime );
|
2013-06-30 20:05:40 -05:00
|
|
|
#endif
|
2014-08-13 15:28:54 -05:00
|
|
|
}
|
|
|
|
|
catch( const IO_ERROR& ioe )
|
2011-12-05 00:15:33 -06:00
|
|
|
{
|
2014-08-13 15:28:54 -05:00
|
|
|
wxString msg = wxString::Format( _(
|
|
|
|
|
"Error loading board.\n%s" ),
|
2016-09-14 17:36:45 -05:00
|
|
|
GetChars( ioe.What() )
|
2014-08-13 15:28:54 -05:00
|
|
|
);
|
|
|
|
|
DisplayError( this, msg );
|
|
|
|
|
return false;
|
2011-12-05 00:15:33 -06:00
|
|
|
}
|
2011-11-28 21:08:14 -06:00
|
|
|
|
2014-08-13 15:28:54 -05:00
|
|
|
SetBoard( loadedBoard );
|
|
|
|
|
|
2011-12-14 20:24:52 -06:00
|
|
|
// we should not ask PLUGINs to do these items:
|
|
|
|
|
loadedBoard->BuildListOfNets();
|
|
|
|
|
loadedBoard->SynchronizeNetsAndNetClasses();
|
|
|
|
|
|
|
|
|
|
SetStatusText( wxEmptyString );
|
|
|
|
|
BestZoom();
|
2014-03-19 19:42:08 -05:00
|
|
|
|
|
|
|
|
// update the layer names in the listbox
|
|
|
|
|
ReCreateLayerBox( false );
|
2007-08-06 02:02:39 +00:00
|
|
|
|
2014-08-13 15:28:54 -05:00
|
|
|
GetScreen()->ClrModify();
|
2011-01-20 11:34:57 -05:00
|
|
|
|
2014-08-13 15:28:54 -05:00
|
|
|
{
|
|
|
|
|
wxFileName fn = fullFileName;
|
|
|
|
|
CheckForAutoSaveFile( fullFileName, fn.GetExt() );
|
|
|
|
|
}
|
2008-07-22 05:29:16 +00:00
|
|
|
|
2014-08-13 15:28:54 -05:00
|
|
|
if( pluginType == IO_MGR::LEGACY &&
|
|
|
|
|
loadedBoard->GetFileFormatVersionAtLoad() < LEGACY_BOARD_FILE_VERSION )
|
|
|
|
|
{
|
|
|
|
|
DisplayInfoMessage( this,
|
|
|
|
|
_( "This file was created by an older version of Pcbnew.\n"
|
|
|
|
|
"It will be stored in the new file format when you save this file again." ) );
|
|
|
|
|
}
|
2007-08-06 02:02:39 +00:00
|
|
|
}
|
|
|
|
|
|
2014-08-13 15:28:54 -05:00
|
|
|
{
|
|
|
|
|
wxFileName fn = fullFileName;
|
2012-12-29 10:54:25 +01:00
|
|
|
|
2014-08-13 15:28:54 -05:00
|
|
|
if( converted )
|
|
|
|
|
fn.SetExt( PcbFileExtension );
|
2012-12-29 10:54:25 +01:00
|
|
|
|
2014-08-13 15:28:54 -05:00
|
|
|
wxString fname = fn.GetFullPath();
|
2012-12-29 10:54:25 +01:00
|
|
|
|
2014-08-13 15:28:54 -05:00
|
|
|
fname.Replace( WIN_STRING_DIR_SEP, UNIX_STRING_DIR_SEP );
|
|
|
|
|
|
|
|
|
|
GetBoard()->SetFileName( fname );
|
|
|
|
|
}
|
2008-07-22 05:29:16 +00:00
|
|
|
|
2011-08-26 13:01:17 -04:00
|
|
|
UpdateTitle();
|
2012-12-29 10:54:25 +01:00
|
|
|
|
|
|
|
|
if( !converted )
|
|
|
|
|
UpdateFileHistory( GetBoard()->GetFileName() );
|
2008-07-22 05:29:16 +00:00
|
|
|
|
2012-02-05 23:44:19 -06:00
|
|
|
// Rebuild the new pad list (for drc and ratsnet control ...)
|
2009-05-24 18:28:36 +00:00
|
|
|
GetBoard()->m_Status_Pcb = 0;
|
2009-06-19 20:13:22 +00:00
|
|
|
|
2016-07-14 09:27:32 +02:00
|
|
|
// Select netclass Default as current netclass (it always exists)
|
2014-09-28 16:44:47 +02:00
|
|
|
SetCurrentNetClass( NETCLASS::Default );
|
2016-07-05 17:01:41 +02:00
|
|
|
|
|
|
|
|
// Rebuild list of nets (full ratsnest rebuild)
|
|
|
|
|
{
|
|
|
|
|
wxBusyCursor dummy; // Displays an Hourglass while building connectivity
|
|
|
|
|
Compile_Ratsnest( NULL, true );
|
|
|
|
|
GetBoard()->GetRatsnest()->ProcessBoard();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Update info shown by the horizontal toolbars
|
2010-01-21 07:41:30 +00:00
|
|
|
ReFillLayerWidget();
|
2013-09-02 17:26:52 +02:00
|
|
|
ReCreateLayerBox();
|
2012-02-05 23:44:19 -06:00
|
|
|
|
2012-03-11 19:40:48 -05:00
|
|
|
// upate the layer widget to match board visibility states, both layers and render columns.
|
|
|
|
|
syncLayerVisibilities();
|
|
|
|
|
syncLayerWidgetLayer();
|
2012-02-05 23:44:19 -06:00
|
|
|
syncRenderStates();
|
2009-12-03 09:33:48 +00:00
|
|
|
|
2015-04-02 13:18:19 +02:00
|
|
|
// Update the tracks / vias available sizes list:
|
|
|
|
|
ReCreateAuxiliaryToolbar();
|
|
|
|
|
|
2012-03-11 19:40:48 -05:00
|
|
|
// Update the RATSNEST items, which were not loaded at the time
|
|
|
|
|
// BOARD::SetVisibleElements() was called from within any PLUGIN.
|
|
|
|
|
// See case RATSNEST_VISIBLE: in BOARD::SetElementVisibility()
|
|
|
|
|
GetBoard()->SetVisibleElements( GetBoard()->GetVisibleElements() );
|
|
|
|
|
|
2009-06-20 19:09:43 +00:00
|
|
|
// Display the loaded board:
|
2009-12-19 19:24:49 +00:00
|
|
|
Zoom_Automatique( false );
|
2009-07-30 11:04:07 +00:00
|
|
|
|
2013-01-12 12:32:24 -05:00
|
|
|
SetMsgPanel( GetBoard() );
|
2007-08-06 02:02:39 +00:00
|
|
|
|
2010-05-01 15:32:25 +02:00
|
|
|
// Refresh the 3D view, if any
|
2016-07-19 13:35:25 -04:00
|
|
|
EDA_3D_VIEWER* draw3DFrame = Get3DViewerFrame();
|
2015-12-21 12:52:00 +01:00
|
|
|
|
|
|
|
|
if( draw3DFrame )
|
|
|
|
|
draw3DFrame->NewDisplay();
|
2008-04-18 13:28:56 +00:00
|
|
|
|
|
|
|
|
#if 0 && defined(DEBUG)
|
2007-10-31 06:40:15 +00:00
|
|
|
// Output the board object tree to stdout, but please run from command prompt:
|
2009-01-05 05:21:35 +00:00
|
|
|
GetBoard()->Show( 0, std::cout );
|
2007-08-06 02:02:39 +00:00
|
|
|
#endif
|
2008-04-18 13:28:56 +00:00
|
|
|
|
2014-03-19 19:42:08 -05:00
|
|
|
// from EDA_APPL which was first loaded BOARD only:
|
|
|
|
|
{
|
|
|
|
|
/* For an obscure reason the focus is lost after loading a board file
|
|
|
|
|
* when starting up the process.
|
|
|
|
|
* (seems due to the recreation of the layer manager after loading the file)
|
|
|
|
|
* Give focus to main window and Drawpanel
|
|
|
|
|
* must be done for these 2 windows (for an obscure reason ...)
|
|
|
|
|
* Linux specific
|
|
|
|
|
* This is more a workaround than a fix.
|
|
|
|
|
*/
|
|
|
|
|
SetFocus();
|
|
|
|
|
GetCanvas()->SetFocus();
|
|
|
|
|
}
|
|
|
|
|
|
2009-09-22 12:27:57 +00:00
|
|
|
return true;
|
2007-06-05 12:10:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2014-08-13 15:28:54 -05:00
|
|
|
static wxString create_backup_file( const wxString& aFileName )
|
2007-06-05 12:10:51 +00:00
|
|
|
{
|
2014-08-13 15:28:54 -05:00
|
|
|
wxFileName fn = aFileName;
|
|
|
|
|
wxFileName backupFileName = aFileName;
|
2007-08-06 02:02:39 +00:00
|
|
|
|
2014-08-13 15:28:54 -05:00
|
|
|
backupFileName.SetExt( fn.GetExt() + backupSuffix );
|
2012-04-07 14:05:56 -04:00
|
|
|
|
2014-08-13 15:28:54 -05:00
|
|
|
// If an old backup file exists, delete it. If an old board file exists,
|
|
|
|
|
// rename it to the backup file name.
|
|
|
|
|
if( fn.FileExists() )
|
2007-08-06 02:02:39 +00:00
|
|
|
{
|
2014-08-13 15:28:54 -05:00
|
|
|
// Remove the old file xxx.000 if it exists.
|
|
|
|
|
if( backupFileName.FileExists() )
|
|
|
|
|
wxRemoveFile( backupFileName.GetFullPath() );
|
2012-12-14 10:54:54 -06:00
|
|
|
|
2014-08-13 15:28:54 -05:00
|
|
|
// Rename the current file from <xxx>.kicad_pcb to <xxx>.kicad_pcb-bak
|
|
|
|
|
if( !wxRenameFile( fn.GetFullPath(), backupFileName.GetFullPath() ) )
|
2013-04-29 12:50:10 -04:00
|
|
|
{
|
2014-08-13 15:28:54 -05:00
|
|
|
wxString msg = wxString::Format( _(
|
|
|
|
|
"Warning: unable to create backup file '%s'" ),
|
|
|
|
|
GetChars( backupFileName.GetFullPath() )
|
|
|
|
|
);
|
|
|
|
|
DisplayError( NULL, msg );
|
2013-04-29 12:50:10 -04:00
|
|
|
}
|
2014-08-13 15:28:54 -05:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
backupFileName.Clear();
|
|
|
|
|
}
|
2013-04-29 12:50:10 -04:00
|
|
|
|
2014-08-13 15:28:54 -05:00
|
|
|
return backupFileName.GetFullPath();
|
|
|
|
|
}
|
2013-10-13 12:29:20 -04:00
|
|
|
|
|
|
|
|
|
2014-08-13 15:28:54 -05:00
|
|
|
bool PCB_EDIT_FRAME::SavePcbFile( const wxString& aFileName, bool aCreateBackupFile )
|
|
|
|
|
{
|
|
|
|
|
// please, keep it simple. prompting goes elsewhere.
|
2014-07-06 23:12:04 -05:00
|
|
|
|
2014-08-13 15:28:54 -05:00
|
|
|
wxFileName pcbFileName = aFileName;
|
2013-10-13 12:29:20 -04:00
|
|
|
|
2014-08-13 15:28:54 -05:00
|
|
|
if( pcbFileName.GetExt() == LegacyPcbFileExtension )
|
|
|
|
|
pcbFileName.SetExt( KiCadPcbFileExtension );
|
2014-07-06 23:12:04 -05:00
|
|
|
|
2014-08-13 15:28:54 -05:00
|
|
|
if( !IsWritable( pcbFileName ) )
|
2011-08-26 13:01:17 -04:00
|
|
|
{
|
2014-08-13 15:28:54 -05:00
|
|
|
wxString msg = wxString::Format( _(
|
|
|
|
|
"No access rights to write to file '%s'" ),
|
|
|
|
|
GetChars( pcbFileName.GetFullPath() )
|
|
|
|
|
);
|
2007-08-06 02:02:39 +00:00
|
|
|
|
2014-08-13 15:28:54 -05:00
|
|
|
DisplayError( this, msg );
|
|
|
|
|
return false;
|
2012-12-14 10:54:54 -06:00
|
|
|
}
|
2012-11-19 10:19:38 -06:00
|
|
|
|
2014-08-13 15:28:54 -05:00
|
|
|
wxString backupFileName;
|
2011-08-26 13:01:17 -04:00
|
|
|
|
2015-02-14 13:43:11 +01:00
|
|
|
// aCreateBackupFile == false is mainly used to write autosave files
|
|
|
|
|
// or new files in save as... command
|
2011-10-13 15:56:32 -04:00
|
|
|
if( aCreateBackupFile )
|
2007-08-06 02:02:39 +00:00
|
|
|
{
|
2014-08-13 15:28:54 -05:00
|
|
|
backupFileName = create_backup_file( aFileName );
|
2007-08-06 02:02:39 +00:00
|
|
|
}
|
|
|
|
|
|
2011-12-14 20:24:52 -06:00
|
|
|
GetBoard()->m_Status_Pcb &= ~CONNEXION_OK;
|
|
|
|
|
|
|
|
|
|
GetBoard()->SynchronizeNetsAndNetClasses();
|
|
|
|
|
|
|
|
|
|
// Select default Netclass before writing file.
|
|
|
|
|
// Useful to save default values in headers
|
2014-09-28 16:44:47 +02:00
|
|
|
SetCurrentNetClass( NETCLASS::Default );
|
2011-12-14 20:24:52 -06:00
|
|
|
|
2014-08-13 15:28:54 -05:00
|
|
|
ClearMsgPanel();
|
|
|
|
|
|
|
|
|
|
wxString upperTxt;
|
|
|
|
|
wxString lowerTxt;
|
|
|
|
|
|
2011-12-14 11:25:42 -06:00
|
|
|
try
|
|
|
|
|
{
|
2014-08-13 15:28:54 -05:00
|
|
|
PLUGIN::RELEASER pi( IO_MGR::PluginFind( IO_MGR::KICAD ) );
|
2012-04-07 14:05:56 -04:00
|
|
|
|
2014-08-13 15:28:54 -05:00
|
|
|
wxASSERT( pcbFileName.IsAbsolute() );
|
2011-12-14 20:24:52 -06:00
|
|
|
|
2012-12-14 12:14:28 -06:00
|
|
|
pi->Save( pcbFileName.GetFullPath(), GetBoard(), NULL );
|
2011-12-14 11:25:42 -06:00
|
|
|
}
|
2014-04-09 08:33:04 -05:00
|
|
|
catch( const IO_ERROR& ioe )
|
2011-12-14 11:25:42 -06:00
|
|
|
{
|
2014-08-13 15:28:54 -05:00
|
|
|
wxString msg = wxString::Format( _(
|
|
|
|
|
"Error saving board file '%s'.\n%s" ),
|
|
|
|
|
GetChars( pcbFileName.GetFullPath() ),
|
2016-09-14 17:36:45 -05:00
|
|
|
GetChars( ioe.What() )
|
2014-08-13 15:28:54 -05:00
|
|
|
);
|
|
|
|
|
DisplayError( this, msg );
|
2011-12-14 11:25:42 -06:00
|
|
|
|
2014-09-24 18:56:20 +02:00
|
|
|
lowerTxt.Printf( _( "Failed to create '%s'" ), GetChars( pcbFileName.GetFullPath() ) );
|
2014-08-13 15:28:54 -05:00
|
|
|
|
|
|
|
|
AppendMsgPanel( upperTxt, lowerTxt, CYAN );
|
2012-12-27 17:42:41 +01:00
|
|
|
|
2014-08-13 15:28:54 -05:00
|
|
|
return false;
|
2011-12-14 20:24:52 -06:00
|
|
|
}
|
|
|
|
|
|
2014-08-13 15:28:54 -05:00
|
|
|
GetBoard()->SetFileName( pcbFileName.GetFullPath() );
|
|
|
|
|
UpdateTitle();
|
2007-08-06 02:02:39 +00:00
|
|
|
|
2014-08-13 15:28:54 -05:00
|
|
|
// Put the saved file in File History, unless aCreateBackupFile
|
|
|
|
|
// is false.
|
|
|
|
|
// aCreateBackupFile == false is mainly used to write autosave files
|
|
|
|
|
// and not need to have an autosave file in file history
|
|
|
|
|
if( aCreateBackupFile )
|
|
|
|
|
UpdateFileHistory( GetBoard()->GetFileName() );
|
2014-03-19 19:42:08 -05:00
|
|
|
|
2014-08-13 15:28:54 -05:00
|
|
|
// Delete auto save file on successful save.
|
|
|
|
|
wxFileName autoSaveFileName = pcbFileName;
|
2011-10-13 15:56:32 -04:00
|
|
|
|
2014-08-13 15:28:54 -05:00
|
|
|
autoSaveFileName.SetName( wxString( autosavePrefix ) + pcbFileName.GetName() );
|
2011-10-13 15:56:32 -04:00
|
|
|
|
2014-08-13 15:28:54 -05:00
|
|
|
if( autoSaveFileName.FileExists() )
|
|
|
|
|
wxRemoveFile( autoSaveFileName.GetFullPath() );
|
2007-08-06 02:02:39 +00:00
|
|
|
|
2014-08-13 15:28:54 -05:00
|
|
|
if( !!backupFileName )
|
2014-09-24 18:56:20 +02:00
|
|
|
upperTxt.Printf( _( "Backup file: '%s'" ), GetChars( backupFileName ) );
|
2011-08-26 13:01:17 -04:00
|
|
|
|
2014-09-24 18:56:20 +02:00
|
|
|
lowerTxt.Printf( _( "Wrote board file: '%s'" ), GetChars( pcbFileName.GetFullPath() ) );
|
2007-08-06 02:02:39 +00:00
|
|
|
|
2010-04-28 10:06:14 -04:00
|
|
|
AppendMsgPanel( upperTxt, lowerTxt, CYAN );
|
2008-04-18 13:28:56 +00:00
|
|
|
|
2007-08-06 02:02:39 +00:00
|
|
|
GetScreen()->ClrModify();
|
2014-08-13 15:28:54 -05:00
|
|
|
GetScreen()->ClrSave();
|
2009-09-22 12:27:57 +00:00
|
|
|
return true;
|
2007-06-05 12:10:51 +00:00
|
|
|
}
|
2011-10-13 15:56:32 -04:00
|
|
|
|
|
|
|
|
|
2015-02-14 13:43:11 +01:00
|
|
|
bool PCB_EDIT_FRAME::SavePcbCopy( const wxString& aFileName )
|
|
|
|
|
{
|
|
|
|
|
wxFileName pcbFileName = aFileName;
|
|
|
|
|
|
|
|
|
|
// Ensure the file ext is the right ext:
|
|
|
|
|
pcbFileName.SetExt( KiCadPcbFileExtension );
|
|
|
|
|
|
|
|
|
|
if( !IsWritable( pcbFileName ) )
|
|
|
|
|
{
|
|
|
|
|
wxString msg = wxString::Format( _(
|
|
|
|
|
"No access rights to write to file '%s'" ),
|
|
|
|
|
GetChars( pcbFileName.GetFullPath() )
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
DisplayError( this, msg );
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GetBoard()->m_Status_Pcb &= ~CONNEXION_OK;
|
|
|
|
|
GetBoard()->SynchronizeNetsAndNetClasses();
|
|
|
|
|
|
|
|
|
|
// Select default Netclass before writing file.
|
|
|
|
|
// Useful to save default values in headers
|
|
|
|
|
SetCurrentNetClass( NETCLASS::Default );
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
PLUGIN::RELEASER pi( IO_MGR::PluginFind( IO_MGR::KICAD ) );
|
|
|
|
|
|
|
|
|
|
wxASSERT( pcbFileName.IsAbsolute() );
|
|
|
|
|
|
|
|
|
|
pi->Save( pcbFileName.GetFullPath(), GetBoard(), NULL );
|
|
|
|
|
}
|
|
|
|
|
catch( const IO_ERROR& ioe )
|
|
|
|
|
{
|
|
|
|
|
wxString msg = wxString::Format( _(
|
|
|
|
|
"Error saving board file '%s'.\n%s" ),
|
|
|
|
|
GetChars( pcbFileName.GetFullPath() ),
|
2016-09-14 17:36:45 -05:00
|
|
|
GetChars( ioe.What() )
|
2015-02-14 13:43:11 +01:00
|
|
|
);
|
|
|
|
|
DisplayError( this, msg );
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DisplayInfoMessage( this, wxString::Format( _( "Board copied to:\n'%s'" ),
|
2016-08-11 15:13:47 -04:00
|
|
|
GetChars( pcbFileName.GetFullPath() ) ) );
|
2015-02-14 13:43:11 +01:00
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2011-10-13 15:56:32 -04:00
|
|
|
bool PCB_EDIT_FRAME::doAutoSave()
|
|
|
|
|
{
|
2016-08-11 15:13:47 -04:00
|
|
|
wxFileName tmpFileName;
|
|
|
|
|
|
|
|
|
|
if( GetBoard()->GetFileName().IsEmpty() )
|
|
|
|
|
{
|
|
|
|
|
tmpFileName = wxFileName( wxStandardPaths::Get().GetDocumentsDir(), wxT( "noname" ),
|
|
|
|
|
KiCadPcbFileExtension );
|
|
|
|
|
GetBoard()->SetFileName( tmpFileName.GetFullPath() );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
tmpFileName = Prj().AbsolutePath( GetBoard()->GetFileName() );
|
|
|
|
|
}
|
2011-10-13 15:56:32 -04:00
|
|
|
|
2016-08-11 15:13:47 -04:00
|
|
|
wxFileName autoSaveFileName = tmpFileName;
|
2011-10-13 15:56:32 -04:00
|
|
|
|
2016-08-11 15:13:47 -04:00
|
|
|
// Auto save file name is the board file name prepended with autosaveFilePrefix string.
|
|
|
|
|
autoSaveFileName.SetName( wxString( autosavePrefix ) + autoSaveFileName.GetName() );
|
2011-10-15 09:25:57 -04:00
|
|
|
|
2016-08-11 15:13:47 -04:00
|
|
|
if( !autoSaveFileName.IsOk() )
|
2015-06-19 09:27:06 -04:00
|
|
|
return false;
|
2016-08-11 15:13:47 -04:00
|
|
|
|
|
|
|
|
// If the board file path is not writable, try writing to a platform specific temp file
|
|
|
|
|
// path. If that path isn't writabe, give up.
|
|
|
|
|
if( !autoSaveFileName.IsDirWritable() )
|
|
|
|
|
{
|
|
|
|
|
autoSaveFileName.SetPath( wxFileName::GetTempDir() );
|
|
|
|
|
|
|
|
|
|
if( !autoSaveFileName.IsOk() || !autoSaveFileName.IsDirWritable() )
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
wxLogTrace( traceAutoSave, "Creating auto save file <" + autoSaveFileName.GetFullPath() + ">" );
|
|
|
|
|
|
|
|
|
|
if( SavePcbFile( autoSaveFileName.GetFullPath(), NO_BACKUP_FILE ) )
|
2011-10-13 15:56:32 -04:00
|
|
|
{
|
2011-10-15 09:25:57 -04:00
|
|
|
GetScreen()->SetModify();
|
2012-08-29 18:59:50 +02:00
|
|
|
GetBoard()->SetFileName( tmpFileName.GetFullPath() );
|
2011-10-13 15:56:32 -04:00
|
|
|
UpdateTitle();
|
2011-10-15 09:25:57 -04:00
|
|
|
m_autoSaveState = false;
|
2011-10-13 15:56:32 -04:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2012-08-29 18:59:50 +02:00
|
|
|
GetBoard()->SetFileName( tmpFileName.GetFullPath() );
|
2011-10-13 15:56:32 -04:00
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|