KiCad PCB EDA Suite
Loading...
Searching...
No Matches
sch_api_save.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or (at your
9 * option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include <api/sch_api_save.h>
21
22#include <base_screen.h>
23#include <common.h>
24#include <kiplatform/io.h>
25#include <pgm_base.h>
26#include <project.h>
28#include <sch_io/sch_io.h>
29#include <sch_io/sch_io_mgr.h>
30#include <sch_screen.h>
31#include <sch_sheet.h>
32#include <sch_sheet_path.h>
33#include <schematic.h>
36
37#include <wx/filename.h>
38#include <wx/log.h>
39
40
41namespace SCH_API_SAVE
42{
43
44bool SaveSheetToFile( SCH_SHEET* aSheet, SCHEMATIC& aSchematic, const wxString& aPath )
45{
46 wxCHECK( aSheet, false );
47
48 if( aPath.IsEmpty() )
49 return false;
50
51 wxFileName schematicFileName( aPath );
52 schematicFileName.MakeAbsolute();
53
54 if( !schematicFileName.DirExists() && !wxMkdir( schematicFileName.GetPath() ) )
55 return false;
56
57 if( schematicFileName.FileExists() && !schematicFileName.IsFileWritable() )
58 return false;
59
60 if( schematicFileName.FileExists() )
61 KIPLATFORM::IO::MakeWriteable( schematicFileName.GetFullPath() );
62
63 SCH_IO_MGR::SCH_FILE_T pluginType = SCH_IO_MGR::GuessPluginTypeFromSchPath( schematicFileName.GetFullPath() );
64
65 if( pluginType == SCH_IO_MGR::SCH_FILE_UNKNOWN )
66 pluginType = SCH_IO_MGR::SCH_KICAD;
67
68 IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( pluginType ) );
69
70 try
71 {
72 pi->SaveSchematicFile( schematicFileName.GetFullPath(), aSheet, &aSchematic );
73 return true;
74 }
75 catch( const IO_ERROR& ioe )
76 {
77 wxLogTrace( wxS( "KI_TRACE_API" ), wxS( "SaveSheetToFile failed: %s" ), ioe.What() );
78 return false;
79 }
80}
81
82
83void UpdateProjectFile( SCHEMATIC& aSchematic, PROJECT& aProject )
84{
85 SCH_SCREEN* rootScreen = aSchematic.RootScreen();
86
87 if( !rootScreen )
88 return;
89
90 wxFileName projectFile( rootScreen->GetFileName() );
91 projectFile.SetExt( FILEEXT::ProjectFileExtension );
92
93 if( !projectFile.HasName() || !projectFile.IsOk() )
94 return;
95
96 aSchematic.RecordERCExclusions();
97
99
100 if( rootScreen )
101 {
103 }
104
105 const std::vector<SCH_SHEET*>& topLevelSheets = aSchematic.GetTopLevelSheets();
106
107 if( !topLevelSheets.empty() )
108 {
109 std::vector<TOP_LEVEL_SHEET_INFO>& projectSheets = aProject.GetProjectFile().GetTopLevelSheets();
110 projectSheets.clear();
111
112 wxString projectPath = aProject.GetProjectPath();
113
114 for( SCH_SHEET* sheet : topLevelSheets )
115 {
117 info.uuid = sheet->m_Uuid;
118 info.name = sheet->GetName();
119
120 wxString filename;
121
122 if( sheet->GetScreen() )
123 filename = sheet->GetScreen()->GetFileName();
124
125 wxFileName sheetFn( filename );
126
127 if( sheetFn.IsAbsolute() )
128 sheetFn.MakeRelativeTo( projectPath );
129
130 info.filename = sheetFn.GetFullPath();
131 projectSheets.push_back( std::move( info ) );
132 }
133 }
134
135 std::vector<FILE_INFO_PAIR>& sheets = aProject.GetProjectFile().GetSheets();
136 sheets.clear();
137
138 if( !aSchematic.HasHierarchy() )
139 aSchematic.RefreshHierarchy();
140
141 for( SCH_SHEET_PATH& sheetPath : aSchematic.Hierarchy() )
142 {
143 SCH_SHEET* sheet = sheetPath.Last();
144
145 wxCHECK2( sheet, continue );
146
147 if( !sheet->IsVirtualRootSheet() )
148 sheets.emplace_back( std::make_pair( sheet->m_Uuid, sheet->GetName() ) );
149 }
150
151 Pgm().GetSettingsManager().SaveProject( projectFile.GetFullPath() );
152}
153
154
155bool SaveSchematic( SCHEMATIC& aSchematic, PROJECT& aProject )
156{
157 SCH_SCREEN* rootScreen = aSchematic.RootScreen();
158
159 if( !rootScreen || rootScreen->GetFileName().IsEmpty() )
160 return false;
161
162 SCH_SCREENS screens( aSchematic.Root() );
163 screens.BuildClientSheetPathList();
164
165 bool success = true;
166
167 for( size_t i = 0; i < screens.GetCount(); i++ )
168 {
169 SCH_SCREEN* screen = screens.GetScreen( i );
170
171 wxCHECK2( screen, continue );
172
173 wxFileName fileName = screen->GetFileName();
174
175 if( !fileName.IsOk() )
176 continue;
177
178 std::vector<SCH_SHEET_PATH>& sheets = screen->GetClientSheetPaths();
179
180 if( sheets.size() == 1 )
181 screen->SetVirtualPageNumber( 1 );
182 else
183 screen->SetVirtualPageNumber( 0 );
184
185 success &= SaveSheetToFile( screens.GetSheet( i ), aSchematic, fileName.GetFullPath() );
186
187 if( success )
188 screen->SetContentModified( false );
189 }
190
191 if( success )
192 UpdateProjectFile( aSchematic, aProject );
193
194 return success;
195}
196
197
198bool SaveSchematicCopy( SCHEMATIC& aSchematic, PROJECT& aProject, const wxString& aFileName, bool aCreateProject )
199{
200 wxFileName schematicFileName( aFileName );
201 schematicFileName.MakeAbsolute();
202
203 if( !schematicFileName.IsOk() || !schematicFileName.IsDirWritable() )
204 return false;
205
206 // Root() is the virtual root, whose screen only holds the top-level sheets
207 SCH_SHEET* rootSheet = aSchematic.GetTopLevelSheet();
208 SCH_SCREEN* rootScreen = aSchematic.RootScreen();
209
210 if( !rootSheet || !rootScreen )
211 return false;
212
213 if( schematicFileName.GetFullPath() == rootScreen->GetFileName() )
214 return SaveSchematic( aSchematic, aProject );
215
216 if( !SaveSheetToFile( rootSheet, aSchematic, schematicFileName.GetFullPath() ) )
217 return false;
218
219 if( aCreateProject )
220 {
221 wxFileName projectFile( schematicFileName );
222 projectFile.SetExt( FILEEXT::ProjectFileExtension );
223
224 if( !projectFile.FileExists() )
225 {
226 if( !Pgm().GetSettingsManager().SaveProjectCopy( projectFile.GetFullPath() ) )
227 return false;
228 }
229 }
230
231 return true;
232}
233
234
235bool SaveSchematicAs( SCHEMATIC& aSchematic, PROJECT& aProject, const wxString& aFileName )
236{
237 wxFileName schematicFileName( EnsureFileExtension( aFileName, FILEEXT::KiCadSchematicFileExtension ) );
238 schematicFileName.MakeAbsolute();
239
240 if( !schematicFileName.IsOk() || schematicFileName.GetName().IsEmpty() )
241 return false;
242
243 if( ( !schematicFileName.DirExists() && !schematicFileName.Mkdir() ) || !schematicFileName.IsDirWritable() )
244 return false;
245
246 aSchematic.Root().SetFileName( schematicFileName.GetFullName() );
247 aSchematic.RootScreen()->SetFileName( schematicFileName.GetFullPath() );
248
249 if( !SaveSchematic( aSchematic, aProject ) )
250 return false;
251
252 aProject.SetReadOnly( false );
253
254 wxFileName projectFile( schematicFileName );
255 projectFile.SetExt( FILEEXT::ProjectFileExtension );
256
257 Pgm().GetSettingsManager().SaveProjectAs( projectFile.GetFullPath(), &aProject );
258
259 return true;
260}
261
262} // namespace SCH_API_SAVE
BASE_SCREEN class implementation.
void SetVirtualPageNumber(int aPageNumber)
Definition base_screen.h:72
static wxString m_DrawingSheetFileName
the name of the drawing sheet file, or empty to use the default drawing sheet
Definition base_screen.h:81
void SetContentModified(bool aModified=true)
Definition base_screen.h:55
const KIID m_Uuid
Definition eda_item.h:599
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
virtual const wxString What() const
A composite of Problem() and Where()
virtual SETTINGS_MANAGER & GetSettingsManager() const
Definition pgm_base.h:123
std::vector< FILE_INFO_PAIR > & GetSheets()
SCHEMATIC_SETTINGS * m_SchematicSettings
struct IP2581_BOM m_IP2581Bom
Layer pair list for the board.
std::vector< TOP_LEVEL_SHEET_INFO > & GetTopLevelSheets()
Container for project specific data.
Definition project.h:63
virtual void SetReadOnly(bool aReadOnly=true)
Definition project.h:161
virtual const wxString GetProjectPath() const
Return the full path of the project.
Definition project.cpp:183
virtual PROJECT_FILE & GetProjectFile() const
Definition project.h:201
Holds all the data relating to one schematic.
Definition schematic.h:149
void RecordERCExclusions()
Scan existing markers and record data from any that are Excluded.
SCH_SHEET_LIST Hierarchy() const
Return the full schematic flattened hierarchical sheet list.
bool HasHierarchy() const
Check if the hierarchy has been built.
Definition schematic.h:190
SCH_SHEET * GetTopLevelSheet(int aIndex=0) const
SCH_SCREEN * RootScreen() const
Helper to retrieve the screen of the root sheet.
SCH_SHEET & Root() const
Definition schematic.h:200
std::vector< SCH_SHEET * > GetTopLevelSheets() const
Get the list of top-level sheets.
void RefreshHierarchy()
static SCH_FILE_T GuessPluginTypeFromSchPath(const wxString &aSchematicPath, int aCtl=0)
Return a plugin type given a schematic using the file extension of aSchematicPath.
Container class that holds multiple SCH_SCREEN objects in a hierarchy.
Definition sch_screen.h:818
SCH_SCREEN * GetScreen(unsigned int aIndex) const
void BuildClientSheetPathList()
Build the list of sheet paths sharing a screen for each screen in use.
size_t GetCount() const
Definition sch_screen.h:823
SCH_SHEET * GetSheet(unsigned int aIndex) const
std::vector< SCH_SHEET_PATH > & GetClientSheetPaths()
Return the number of times this screen is used.
Definition sch_screen.h:226
const wxString & GetFileName() const
Definition sch_screen.h:157
void SetFileName(const wxString &aFileName)
Set the file name for this screen to aFileName.
TITLE_BLOCK & GetTitleBlock()
Definition sch_screen.h:168
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition sch_sheet.h:48
void SetFileName(const wxString &aFilename)
Definition sch_sheet.h:392
wxString GetName() const
Definition sch_sheet.h:142
bool IsVirtualRootSheet() const
void SaveProjectAs(const wxString &aFullPath, PROJECT *aProject=nullptr)
Set the currently loaded project path and saves it (pointers remain valid).
bool SaveProject(const wxString &aFullPath=wxEmptyString, PROJECT *aProject=nullptr)
Save a loaded project.
const wxString & GetRevision() const
Definition title_block.h:83
wxString EnsureFileExtension(const wxString &aFilename, const wxString &aExtension)
It's annoying to throw up nag dialogs when the extension isn't right.
Definition common.cpp:848
static const std::string ProjectFileExtension
static const std::string KiCadSchematicFileExtension
std::unique_ptr< T > IO_RELEASER
Helper to hold and release an IO_BASE object when exceptions are thrown.
Definition io_mgr.h:33
bool MakeWriteable(const wxString &aFilePath)
Ensures that a file has write permissions.
Definition unix/io.cpp:78
bool SaveSheetToFile(SCH_SHEET *aSheet, SCHEMATIC &aSchematic, const wxString &aPath)
Write a single sheet to disk via SCH_IO.
bool SaveSchematic(SCHEMATIC &aSchematic, PROJECT &aProject)
Save every screen in the hierarchy to its current path, then update the project file.
void UpdateProjectFile(SCHEMATIC &aSchematic, PROJECT &aProject)
Sync schematic metadata into the project file (.kicad_pro) and save it.
bool SaveSchematicCopy(SCHEMATIC &aSchematic, PROJECT &aProject, const wxString &aFileName, bool aCreateProject)
Save the root schematic to aFileName without changing the open document.
bool SaveSchematicAs(SCHEMATIC &aSchematic, PROJECT &aProject, const wxString &aFileName)
Save the schematic to aFileName and adopt it: the root sheet and screen are re-homed to the new path,...
PGM_BASE & Pgm()
The global program "get" accessor.
see class PGM_BASE
Definition of the SCH_SHEET_PATH and SCH_SHEET_LIST classes for Eeschema.
wxString schRevision
Auto-propagated schematic title block revision.
Information about a top-level schematic sheet.
Definition of file extensions used in Kicad.