mirror of
https://gitlab.com/kicad/code/kicad.git
synced 2025-09-15 02:33:15 +02:00
Fix an annoying issue about not named nets: now, these nets are named from the component references and pin names which are connected. therefore, unless the net or the footprint references are modified, the net name is not modified between 2 netlist calculations.
530 lines
14 KiB
C++
530 lines
14 KiB
C++
/*
|
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
|
*
|
|
* Copyright (C) 2013 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
|
* Copyright (C) 2013 Wayne Stambaugh <stambaughw@verizon.net>
|
|
* Copyright (C) 2013 CERN (www.cern.ch)
|
|
* Copyright (C) 1992-2013 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 eeschema/files-io.cpp
|
|
*/
|
|
|
|
#include <fctsys.h>
|
|
#include <class_drawpanel.h>
|
|
#include <confirm.h>
|
|
#include <gestfich.h>
|
|
#include <wxEeschemaStruct.h>
|
|
#include <appl_wxstruct.h>
|
|
|
|
#include <eeschema_id.h>
|
|
#include <class_library.h>
|
|
#include <libeditframe.h>
|
|
#include <sch_sheet.h>
|
|
#include <sch_sheet_path.h>
|
|
#include <sch_component.h>
|
|
#include <wildcards_and_files_ext.h>
|
|
|
|
|
|
bool SCH_EDIT_FRAME::SaveEEFile( SCH_SCREEN* aScreen, bool aSaveUnderNewName, bool aCreateBackupFile )
|
|
{
|
|
wxString msg;
|
|
wxFileName schematicFileName;
|
|
FILE* f;
|
|
bool success;
|
|
|
|
if( aScreen == NULL )
|
|
aScreen = GetScreen();
|
|
|
|
// If no name exists in the window yet - save as new.
|
|
if( aScreen->GetFileName().IsEmpty() )
|
|
aSaveUnderNewName = true;
|
|
|
|
// Construct the name of the file to be saved
|
|
schematicFileName = aScreen->GetFileName();
|
|
|
|
if( aSaveUnderNewName )
|
|
{
|
|
wxFileDialog dlg( this, _( "Schematic Files" ), wxGetCwd(),
|
|
schematicFileName.GetFullName(), SchematicFileWildcard,
|
|
wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
|
|
|
|
if( dlg.ShowModal() == wxID_CANCEL )
|
|
return false;
|
|
|
|
schematicFileName = dlg.GetPath();
|
|
|
|
if( schematicFileName.GetExt() != SchematicFileExtension )
|
|
schematicFileName.SetExt( SchematicFileExtension );
|
|
}
|
|
else
|
|
{
|
|
// Sheet file names are relative to the root sheet path which is the current
|
|
// working directory. The IsWritable function expects the path to be set.
|
|
if( schematicFileName.GetPath().IsEmpty() )
|
|
schematicFileName.Assign( wxFileName::GetCwd(),
|
|
schematicFileName.GetFullName() );
|
|
}
|
|
|
|
if( !IsWritable( schematicFileName ) )
|
|
return false;
|
|
|
|
/* Create backup if requested */
|
|
if( aCreateBackupFile && schematicFileName.FileExists() )
|
|
{
|
|
wxFileName backupFileName = schematicFileName;
|
|
|
|
/* Rename the old file to a '.bak' one: */
|
|
backupFileName.SetExt( SchematicBackupFileExtension );
|
|
if( backupFileName.FileExists() )
|
|
wxRemoveFile( backupFileName.GetFullPath() );
|
|
|
|
if( !wxRenameFile( schematicFileName.GetFullPath(), backupFileName.GetFullPath() ) )
|
|
{
|
|
msg.Printf( _( "Could not save backup of file <%s>" ),
|
|
GetChars( schematicFileName.GetFullPath() ) );
|
|
DisplayError( this, msg );
|
|
}
|
|
}
|
|
|
|
/* Save */
|
|
wxLogTrace( traceAutoSave,
|
|
wxT( "Saving file <" ) + schematicFileName.GetFullPath() + wxT( ">" ) );
|
|
|
|
if( ( f = wxFopen( schematicFileName.GetFullPath(), wxT( "wt" ) ) ) == NULL )
|
|
{
|
|
msg.Printf( _( "Failed to create file <%s>" ),
|
|
GetChars( schematicFileName.GetFullPath() ) );
|
|
DisplayError( this, msg );
|
|
return false;
|
|
}
|
|
|
|
success = aScreen->Save( f );
|
|
|
|
if( success )
|
|
{
|
|
// Delete auto save file.
|
|
wxFileName autoSaveFileName = schematicFileName;
|
|
autoSaveFileName.SetName( wxT( "$" ) + schematicFileName.GetName() );
|
|
|
|
if( autoSaveFileName.FileExists() )
|
|
{
|
|
wxLogTrace( traceAutoSave,
|
|
wxT( "Removing auto save file <" ) + autoSaveFileName.GetFullPath() +
|
|
wxT( ">" ) );
|
|
|
|
wxRemoveFile( autoSaveFileName.GetFullPath() );
|
|
}
|
|
|
|
// Update the screen and frame info.
|
|
if( aSaveUnderNewName )
|
|
aScreen->SetFileName( schematicFileName.GetFullPath() );
|
|
aScreen->ClrSave();
|
|
aScreen->ClrModify();
|
|
|
|
msg.Printf( _( "File %s saved" ), GetChars( aScreen->GetFileName() ) );
|
|
SetStatusText( msg, 0 );
|
|
}
|
|
else
|
|
{
|
|
DisplayError( this, _( "File write operation failed." ) );
|
|
}
|
|
|
|
fclose( f );
|
|
|
|
return success;
|
|
}
|
|
|
|
|
|
void SCH_EDIT_FRAME::Save_File( wxCommandEvent& event )
|
|
{
|
|
int id = event.GetId();
|
|
|
|
switch( id )
|
|
{
|
|
case ID_UPDATE_ONE_SHEET:
|
|
SaveEEFile( NULL );
|
|
break;
|
|
|
|
case ID_SAVE_ONE_SHEET_UNDER_NEW_NAME:
|
|
if( SaveEEFile( NULL, true ) )
|
|
{
|
|
CreateArchiveLibraryCacheFile( true );
|
|
}
|
|
break;
|
|
}
|
|
|
|
UpdateTitle();
|
|
}
|
|
|
|
|
|
bool SCH_EDIT_FRAME::LoadCacheLibrary( const wxString& aFilename )
|
|
{
|
|
wxString msg;
|
|
bool LibCacheExist = false;
|
|
wxFileName fn = aFilename;
|
|
|
|
/* Loading the project library cache
|
|
* until apr 2009 the lib is named <root_name>.cache.lib
|
|
* and after (due to code change): <root_name>-cache.lib
|
|
* so if the <name>-cache.lib is not found, the old way will be tried
|
|
*/
|
|
bool use_oldcachename = false;
|
|
wxString cachename = fn.GetName() + wxT( "-cache" );
|
|
|
|
fn.SetName( cachename );
|
|
fn.SetExt( SchematicLibraryFileExtension );
|
|
|
|
if( ! fn.FileExists() )
|
|
{
|
|
fn = aFilename;
|
|
fn.SetExt( wxT( "cache.lib" ) );
|
|
use_oldcachename = true;
|
|
}
|
|
|
|
if( fn.FileExists() )
|
|
{
|
|
wxString errMsg;
|
|
|
|
wxLogDebug( wxT( "Load schematic cache library file <%s>" ),
|
|
GetChars( fn.GetFullPath() ) );
|
|
msg = wxT( "Load " ) + fn.GetFullPath();
|
|
|
|
CMP_LIBRARY* LibCache = CMP_LIBRARY::LoadLibrary( fn, errMsg );
|
|
|
|
if( LibCache )
|
|
{
|
|
LibCache->SetCache();
|
|
msg += wxT( " OK" );
|
|
|
|
if ( use_oldcachename ) // set the new name
|
|
{
|
|
fn.SetName( cachename );
|
|
fn.SetExt( SchematicLibraryFileExtension );
|
|
LibCache->SetFileName( fn );
|
|
}
|
|
|
|
LibCacheExist = true;
|
|
CMP_LIBRARY::GetLibraryList().push_back( LibCache );
|
|
}
|
|
else
|
|
{
|
|
wxString prompt;
|
|
|
|
prompt.Printf( _( "Component library <%s> failed to load.\nError: %s" ),
|
|
GetChars( fn.GetFullPath() ),
|
|
GetChars( errMsg ) );
|
|
DisplayError( this, prompt );
|
|
msg += _( " ->Error" );
|
|
}
|
|
|
|
PrintMsg( msg );
|
|
}
|
|
|
|
return LibCacheExist;
|
|
}
|
|
|
|
|
|
bool SCH_EDIT_FRAME::LoadOneEEProject( const wxString& aFileName, bool aIsNew )
|
|
{
|
|
SCH_SCREEN* screen;
|
|
wxString FullFileName, msg;
|
|
bool LibCacheExist = false;
|
|
SCH_SCREENS ScreenList;
|
|
|
|
for( screen = ScreenList.GetFirst(); screen != NULL; screen = ScreenList.GetNext() )
|
|
{
|
|
if( screen->IsModify() )
|
|
break;
|
|
}
|
|
|
|
if( screen )
|
|
{
|
|
if( !IsOK( this, _( "Discard changes to the current schematic?" ) ) )
|
|
return false;
|
|
}
|
|
|
|
FullFileName = aFileName;
|
|
|
|
if( ( FullFileName.IsEmpty() ) && !aIsNew )
|
|
{
|
|
wxFileDialog dlg( this, _( "Open Schematic" ), wxGetCwd(),
|
|
wxEmptyString, SchematicFileWildcard,
|
|
wxFD_OPEN | wxFD_FILE_MUST_EXIST );
|
|
|
|
if( dlg.ShowModal() == wxID_CANCEL )
|
|
return false;
|
|
|
|
FullFileName = dlg.GetPath();
|
|
}
|
|
|
|
wxFileName fn = FullFileName;
|
|
|
|
if( fn.IsRelative() )
|
|
{
|
|
fn.MakeAbsolute();
|
|
FullFileName = fn.GetFullPath();
|
|
}
|
|
|
|
if( !wxGetApp().LockFile( FullFileName ) )
|
|
{
|
|
DisplayError( this, _( "This file is already open." ) );
|
|
return false;
|
|
}
|
|
|
|
// Clear the screen before open a new file
|
|
if( g_RootSheet )
|
|
{
|
|
delete g_RootSheet;
|
|
g_RootSheet = NULL;
|
|
}
|
|
|
|
CreateScreens();
|
|
screen = GetScreen();
|
|
|
|
wxLogDebug( wxT( "Loading schematic " ) + FullFileName );
|
|
wxSetWorkingDirectory( fn.GetPath() );
|
|
|
|
screen->SetFileName( FullFileName );
|
|
g_RootSheet->SetFileName( FullFileName );
|
|
SetStatusText( wxEmptyString );
|
|
ClearMsgPanel();
|
|
|
|
screen->ClrModify();
|
|
|
|
if( aIsNew )
|
|
{
|
|
/* SCH_SCREEN constructor does this now
|
|
screen->SetPageSettings( PAGE_INFO( wxT( "A4" ) ) );
|
|
*/
|
|
|
|
screen->SetZoom( 32 );
|
|
screen->SetGrid( ID_POPUP_GRID_LEVEL_1000 + m_LastGridSizeId );
|
|
|
|
TITLE_BLOCK tb;
|
|
wxString title;
|
|
|
|
title += NAMELESS_PROJECT;
|
|
title += wxT( ".sch" );
|
|
tb.SetTitle( title );
|
|
screen->SetTitleBlock( tb );
|
|
|
|
GetScreen()->SetFileName( title );
|
|
|
|
LoadProjectFile( wxEmptyString, true );
|
|
Zoom_Automatique( false );
|
|
SetSheetNumberAndCount();
|
|
m_canvas->Refresh();
|
|
return true;
|
|
}
|
|
|
|
// Reloading configuration.
|
|
msg.Printf( _( "Ready\nWorking dir: <%s>\n" ), GetChars( wxGetCwd() ) );
|
|
PrintMsg( msg );
|
|
|
|
LoadProjectFile( wxEmptyString, false );
|
|
|
|
// Clear (if needed) the current active library in libedit because it could be
|
|
// removed from memory
|
|
LIB_EDIT_FRAME::EnsureActiveLibExists();
|
|
|
|
// Delete old caches.
|
|
CMP_LIBRARY::RemoveCacheLibrary();
|
|
|
|
LibCacheExist = LoadCacheLibrary( g_RootSheet->GetScreen()->GetFileName() );
|
|
|
|
if( !wxFileExists( g_RootSheet->GetScreen()->GetFileName() ) && !LibCacheExist )
|
|
{
|
|
Zoom_Automatique( false );
|
|
msg.Printf( _( "File <%s> not found." ),
|
|
GetChars( g_RootSheet->GetScreen()->GetFileName() ) );
|
|
DisplayInfoMessage( this, msg );
|
|
return false;
|
|
}
|
|
|
|
// load the project.
|
|
g_RootSheet->SetScreen( NULL );
|
|
bool diag = g_RootSheet->Load( this );
|
|
SetScreen( m_CurrentSheet->LastScreen() );
|
|
|
|
UpdateFileHistory( g_RootSheet->GetScreen()->GetFileName() );
|
|
|
|
/* Redraw base screen (ROOT) if necessary. */
|
|
GetScreen()->SetGrid( ID_POPUP_GRID_LEVEL_1000 + m_LastGridSizeId );
|
|
Zoom_Automatique( false );
|
|
SetSheetNumberAndCount();
|
|
m_canvas->Refresh( true );
|
|
return diag;
|
|
}
|
|
|
|
|
|
bool SCH_EDIT_FRAME::AppendOneEEProject()
|
|
{
|
|
SCH_SCREEN* screen;
|
|
wxString FullFileName;
|
|
wxString msg;
|
|
|
|
screen = GetScreen();
|
|
|
|
if( !screen )
|
|
{
|
|
wxLogError( wxT("Document not ready, cannot import") );
|
|
return false;
|
|
}
|
|
|
|
// open file chooser dialog
|
|
wxFileDialog dlg( this, _( "Import Schematic" ), wxGetCwd(),
|
|
wxEmptyString, SchematicFileWildcard,
|
|
wxFD_OPEN | wxFD_FILE_MUST_EXIST );
|
|
|
|
if( dlg.ShowModal() == wxID_CANCEL )
|
|
return false;
|
|
|
|
FullFileName = dlg.GetPath();
|
|
|
|
wxFileName fn = FullFileName;
|
|
|
|
if( fn.IsRelative() )
|
|
{
|
|
fn.MakeAbsolute();
|
|
FullFileName = fn.GetFullPath();
|
|
}
|
|
|
|
LoadCacheLibrary( FullFileName );
|
|
|
|
wxLogDebug( wxT( "Importing schematic " ) + FullFileName );
|
|
|
|
// load the project
|
|
bool success = LoadOneEEFile( screen, FullFileName, true );
|
|
if( success )
|
|
{
|
|
// load sub-sheets
|
|
EDA_ITEM* bs = screen->GetDrawItems();
|
|
while( bs )
|
|
{
|
|
// do not append hierarchical sheets
|
|
if( bs->Type() == SCH_SHEET_T )
|
|
{
|
|
screen->Remove( (SCH_SHEET*) bs );
|
|
}
|
|
// clear annotation and init new time stamp for the new components
|
|
else if( bs->Type() == SCH_COMPONENT_T )
|
|
{
|
|
( (SCH_COMPONENT*) bs )->SetTimeStamp( GetNewTimeStamp() );
|
|
( (SCH_COMPONENT*) bs )->ClearAnnotation( NULL );
|
|
// Clear flags, which are set by these previous modifications:
|
|
bs->ClearFlags();
|
|
}
|
|
|
|
bs = bs->Next();
|
|
}
|
|
}
|
|
|
|
// redraw base screen (ROOT) if necessary
|
|
GetScreen()->SetGrid( ID_POPUP_GRID_LEVEL_1000 + m_LastGridSizeId );
|
|
Zoom_Automatique( false );
|
|
SetSheetNumberAndCount();
|
|
m_canvas->Refresh( true );
|
|
return success;
|
|
}
|
|
|
|
|
|
void SCH_EDIT_FRAME::OnAppendProject( wxCommandEvent& event )
|
|
{
|
|
wxString msg = _( "This operation cannot be undone. "
|
|
"Besides, take into account that hierarchical sheets will not be appended.\n\n"
|
|
"Do you want to save the current document before proceeding?" );
|
|
|
|
if( IsOK( this, msg ) )
|
|
OnSaveProject( event );
|
|
|
|
AppendOneEEProject();
|
|
}
|
|
|
|
|
|
void SCH_EDIT_FRAME::OnSaveProject( wxCommandEvent& aEvent )
|
|
{
|
|
SCH_SCREEN* screen;
|
|
wxFileName fn;
|
|
wxFileName tmp;
|
|
SCH_SCREENS ScreenList;
|
|
|
|
fn = g_RootSheet->GetFileName();
|
|
|
|
// Ensure a path exists. if no path, assume the cwd is used
|
|
// The IsWritable function expects the path to be set
|
|
if( !fn.GetPath().IsEmpty() )
|
|
tmp.AssignDir( fn.GetPath() );
|
|
else
|
|
tmp.AssignDir( wxGetCwd() );
|
|
|
|
if( !IsWritable( tmp ) )
|
|
return;
|
|
|
|
for( screen = ScreenList.GetFirst(); screen != NULL; screen = ScreenList.GetNext() )
|
|
SaveEEFile( screen );
|
|
|
|
CreateArchiveLibraryCacheFile();
|
|
|
|
UpdateTitle();
|
|
}
|
|
|
|
|
|
bool SCH_EDIT_FRAME::doAutoSave()
|
|
{
|
|
wxFileName tmpFileName = g_RootSheet->GetFileName();
|
|
wxFileName fn = tmpFileName;
|
|
wxFileName tmp;
|
|
SCH_SCREENS screens;
|
|
bool autoSaveOk = true;
|
|
|
|
tmp.AssignDir( fn.GetPath() );
|
|
|
|
if( !IsWritable( tmp ) )
|
|
return false;
|
|
|
|
for( SCH_SCREEN* screen = screens.GetFirst(); screen != NULL; screen = screens.GetNext() )
|
|
{
|
|
// Only create auto save files for the schematics that have been modified.
|
|
if( !screen->IsSave() )
|
|
continue;
|
|
|
|
tmpFileName = fn = screen->GetFileName();
|
|
|
|
// Auto save file name is the normal file name prefixed with $.
|
|
fn.SetName( wxT( "$" ) + fn.GetName() );
|
|
|
|
screen->SetFileName( fn.GetFullPath() );
|
|
|
|
if( SaveEEFile( screen, false, NO_BACKUP_FILE ) )
|
|
screen->SetModify();
|
|
else
|
|
autoSaveOk = false;
|
|
|
|
screen->SetFileName( tmpFileName.GetFullPath() );
|
|
}
|
|
|
|
if( autoSaveOk )
|
|
m_autoSaveState = false;
|
|
|
|
return autoSaveOk;
|
|
}
|