KiCad PCB EDA Suite
Loading...
Searching...
No Matches
eeschema/files-io.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 (C) 2013 Jean-Pierre Charras, jp.charras at wanadoo.fr
5 * Copyright (C) 2013 Wayne Stambaugh <[email protected]>
6 * Copyright (C) 2013-2023 CERN (www.cern.ch)
7 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, you may find one here:
21 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
22 * or you may search the http://www.gnu.org website for the version 2 license,
23 * or you may write to the Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
25 */
26
27
28#include <confirm.h>
29#include <common.h>
30#include <connection_graph.h>
32#include <dialog_symbol_remap.h>
34#include <eeschema_settings.h>
35#include <id.h>
36#include <kiface_base.h>
37#include <kiplatform/app.h>
39#include <local_history.h>
40#include <lockfile.h>
41#include <pgm_base.h>
42#include <core/profile.h>
44#include <project_rescue.h>
45#include <project_sch.h>
48#include <reporter.h>
49#include <richio.h>
50#include <sch_bus_entry.h>
51#include <sch_commit.h>
52#include <sch_edit_frame.h>
54#include <sch_file_versions.h>
55#include <sch_line.h>
56#include <sch_sheet.h>
57#include <sch_sheet_path.h>
58#include <schematic.h>
60#include <sim/simulator_frame.h>
61#include <tool/actions.h>
62#include <tool/tool_manager.h>
65#include <trace_helpers.h>
67#include <widgets/wx_infobar.h>
69#include <local_history.h>
71#include <wx/app.h>
72#include <wx/ffile.h>
73#include <wx/filedlg.h>
74#include <wx/log.h>
75#include <wx/richmsgdlg.h>
76#include <wx/stdpaths.h>
79#include <paths.h>
80#include <wx_filename.h> // For ::ResolvePossibleSymlinks
83
84#include <kiplatform/io.h>
85
88#include "save_project_utils.h"
89
90bool SCH_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, int aCtl )
91{
92 // ensure the splash screen does not obscure any dialog at startup
93 Pgm().HideSplash();
94
95 // implement the pseudo code from KIWAY_PLAYER.h:
96 wxString msg;
97
98 EESCHEMA_SETTINGS* cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
99
100 // This is for python:
101 if( aFileSet.size() != 1 )
102 {
103 msg.Printf( "Eeschema:%s() takes only a single filename.", __WXFUNCTION__ );
104 DisplayError( this, msg );
105 return false;
106 }
107
108 wxString fullFileName( aFileSet[0] );
109 wxFileName wx_filename( fullFileName );
110 Kiway().LocalHistory().Init( wx_filename.GetPath() );
111
112 // We insist on caller sending us an absolute path, if it does not, we say it's a bug.
113 wxASSERT_MSG( wx_filename.IsAbsolute(), wxS( "Path is not absolute!" ) );
114
115 if( !LockFile( fullFileName ) )
116 {
117 msg.Printf( _( "Schematic '%s' is already open by '%s' at '%s'." ), fullFileName,
118 m_file_checker->GetUsername(), m_file_checker->GetHostname() );
119
120 if( !AskOverrideLock( this, msg ) )
121 return false;
122
123 m_file_checker->OverrideLock();
124 }
125
126 if( !AskToSaveChanges() )
127 return false;
128
129#ifdef PROFILE
130 PROF_TIMER openFiles( "OpenProjectFile" );
131#endif
132
133 wxFileName pro = fullFileName;
134 pro.SetExt( FILEEXT::ProjectFileExtension );
135
136 bool is_new = !wxFileName::IsFileReadable( fullFileName );
137
138 // If its a non-existent schematic and caller thinks it exists
139 if( is_new && !( aCtl & KICTL_CREATE ) )
140 {
141 // notify user that fullFileName does not exist, ask if user wants to create it.
142 msg.Printf( _( "Schematic '%s' does not exist. Do you wish to create it?" ),
143 fullFileName );
144
145 if( !IsOK( this, msg ) )
146 return false;
147 }
148
149 wxCommandEvent e( EDA_EVT_SCHEMATIC_CHANGING );
150 ProcessEventLocally( e );
151
152 // unload current project file before loading new
153 {
156 SetScreen( nullptr );
158 }
159
160 SetStatusText( wxEmptyString );
161 m_infoBar->Dismiss();
162
163 WX_PROGRESS_REPORTER progressReporter( this, is_new ? _( "Create Schematic" )
164 : _( "Load Schematic" ), 1,
165 PR_CAN_ABORT );
166
167 bool differentProject = pro.GetFullPath() != Prj().GetProjectFullName();
168
169 // This is for handling standalone mode schematic changes
170 if( differentProject )
171 {
172 if( !Prj().IsNullProject() )
173 {
176 }
177
178 // disconnect existing project from schematic before we unload the project
179 Schematic().SetProject( nullptr );
180 GetSettingsManager()->UnloadProject( &Prj(), false );
181
182 GetSettingsManager()->LoadProject( pro.GetFullPath() );
183
184 wxFileName legacyPro( pro );
185 legacyPro.SetExt( FILEEXT::LegacyProjectFileExtension );
186
187 // Do not allow saving a project if one doesn't exist. This normally happens if we are
188 // standalone and opening a schematic that has been moved from its project folder.
189 if( !pro.Exists() && !legacyPro.Exists() && !( aCtl & KICTL_CREATE ) )
190 Prj().SetReadOnly();
191 }
192
193 // Start a new schematic object now that we sorted out our project
194 std::unique_ptr<SCHEMATIC> newSchematic = std::make_unique<SCHEMATIC>( &Prj() );
195
196 SCH_IO_MGR::SCH_FILE_T schFileType = SCH_IO_MGR::GuessPluginTypeFromSchPath( fullFileName,
198
199 if( schFileType == SCH_IO_MGR::SCH_LEGACY )
200 {
201 // Don't reload the symbol libraries if we are just launching Eeschema from KiCad again.
202 // They are already saved in the kiface project object.
203 if( differentProject || !Prj().GetElem( PROJECT::ELEM::LEGACY_SYMBOL_LIBS ) )
204 {
205 // load the libraries here, not in SCH_SCREEN::Draw() which is a context
206 // that will not tolerate DisplayError() dialog since we're already in an
207 // event handler in there.
208 // And when a schematic file is loaded, we need these libs to initialize
209 // some parameters (links to PART LIB, dangling ends ...)
212 }
213 }
214 else
215 {
216 // No legacy symbol libraries including the cache are loaded with the new file format.
218 }
219
220 wxFileName rfn( GetCurrentFileName() );
221 rfn.MakeRelativeTo( Prj().GetProjectPath() );
222 LoadWindowState( rfn.GetFullPath() );
223
224 KIPLATFORM::APP::SetShutdownBlockReason( this, _( "Schematic file changes are unsaved" ) );
225
226 if( Kiface().IsSingle() )
227 {
229 }
230
231 if( is_new || schFileType == SCH_IO_MGR::SCH_FILE_T::SCH_FILE_UNKNOWN )
232 {
233 newSchematic->CreateDefaultScreens();
234 SetSchematic( newSchematic.release() );
235
236 // mark new, unsaved file as modified.
238 GetScreen()->SetFileName( fullFileName );
239
240 if( schFileType == SCH_IO_MGR::SCH_FILE_T::SCH_FILE_UNKNOWN )
241 {
242 msg.Printf( _( "'%s' is not a KiCad schematic file.\nUse File -> Import for "
243 "non-KiCad schematic files." ),
244 fullFileName );
245
246 progressReporter.Hide();
247 DisplayErrorMessage( this, msg );
248 }
249 }
250 else
251 {
252 SetScreen( nullptr );
253
254 IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( schFileType ) );
255
256 pi->SetProgressReporter( &progressReporter );
257
258 bool failedLoad = false;
259
260 try
261 {
262 {
263 wxBusyCursor busy;
264 WINDOW_DISABLER raii( this );
265
266 // Check if project file has top-level sheets defined
267 PROJECT_FILE& projectFile = Prj().GetProjectFile();
268 const std::vector<TOP_LEVEL_SHEET_INFO>& topLevelSheets = projectFile.GetTopLevelSheets();
269
270 if( !topLevelSheets.empty() )
271 {
272 // New multi-root format: Load all top-level sheets
273 // Note: AddTopLevelSheet will create the virtual root as needed
274
275 // Load each top-level sheet
276 for( const TOP_LEVEL_SHEET_INFO& sheetInfo : topLevelSheets )
277 {
278 wxFileName sheetFileName( Prj().GetProjectPath(), sheetInfo.filename );
279
280 // When loading legacy schematic files, ensure we are referencing the correct extension
281 if( schFileType == SCH_IO_MGR::SCH_LEGACY )
282 sheetFileName.SetExt( FILEEXT::LegacySchematicFileExtension );
283
284 wxString sheetPath = sheetFileName.GetFullPath();
285
286 if( !wxFileName::FileExists( sheetPath ) )
287 {
288 wxLogWarning( wxT( "Top-level sheet file not found: %s" ), sheetPath );
289 continue;
290 }
291
292 SCH_SHEET* sheet = pi->LoadSchematicFile( sheetPath, newSchematic.get() );
293
294 if( sheet )
295 {
296 // Preserve the UUID from the project file, unless it's niluuid which is
297 // just a placeholder meaning "use the UUID from the file"
298 if( sheetInfo.uuid != niluuid )
299 {
300 const_cast<KIID&>( sheet->m_Uuid ) = sheetInfo.uuid;
301 }
302
303 sheet->SetName( sheetInfo.name );
304
305 // Regular top-level sheet, add it normally
306 newSchematic->AddTopLevelSheet( sheet );
307
308 wxLogTrace( tracePathsAndFiles,
309 wxS( "Loaded top-level sheet '%s' (UUID %s) from %s" ),
310 sheet->GetName(),
311 sheet->m_Uuid.AsString(),
312 sheetPath );
313 }
314 }
315
316 // Virtual root was already created by AddTopLevelSheet, no need to call SetRoot
317 // Set current sheet to the first top-level sheet
318 if( !newSchematic->GetTopLevelSheets().empty() )
319 {
320 newSchematic->CurrentSheet().clear();
321 newSchematic->CurrentSheet().push_back( newSchematic->GetTopLevelSheets()[0] );
322
323 wxLogTrace( tracePathsAndFiles,
324 wxS( "Loaded multi-root schematic with %zu top-level sheets, current sheet set to '%s'" ),
325 newSchematic->GetTopLevelSheets().size(),
326 newSchematic->GetTopLevelSheets()[0]->GetName() );
327 }
328 else
329 {
330 wxLogTrace( tracePathsAndFiles,
331 wxS( "Loaded multi-root schematic with no top-level sheets!" ) );
332 newSchematic->CreateDefaultScreens();
333 }
334 }
335 else
336 {
337 // Legacy single-root format: Load the single root sheet
338 newSchematic->SetRoot( pi->LoadSchematicFile( fullFileName, newSchematic.get() ) );
339
340 // Make ${SHEETNAME} work on the root sheet until we properly support
341 // naming the root sheet
342 newSchematic->Root().SetName( _( "Root" ) );
343
344 wxLogTrace( tracePathsAndFiles,
345 wxS( "Loaded schematic with root sheet UUID %s" ),
346 newSchematic->Root().m_Uuid.AsString() );
347 wxLogTrace( traceSchCurrentSheet,
348 "After loading: Current sheet path='%s', size=%zu, empty=%d",
349 newSchematic->CurrentSheet().Path().AsString(),
350 newSchematic->CurrentSheet().size(),
351 newSchematic->CurrentSheet().empty() ? 1 : 0 );
352 }
353 }
354
355 if( !pi->GetError().IsEmpty() )
356 {
357 DisplayErrorMessage( this, _( "The entire schematic could not be loaded. Errors "
358 "occurred attempting to load hierarchical sheets." ),
359 pi->GetError() );
360 }
361 }
362 catch( const FUTURE_FORMAT_ERROR& ffe )
363 {
364 newSchematic->CreateDefaultScreens();
365 msg.Printf( _( "Error loading schematic '%s'." ), fullFileName );
366 progressReporter.Hide();
367 DisplayErrorMessage( this, msg, ffe.Problem() );
368
369 failedLoad = true;
370 }
371 catch( const IO_ERROR& ioe )
372 {
373 newSchematic->CreateDefaultScreens();
374 msg.Printf( _( "Error loading schematic '%s'." ), fullFileName );
375 progressReporter.Hide();
376 DisplayErrorMessage( this, msg, ioe.What() );
377
378 failedLoad = true;
379 }
380 catch( const std::bad_alloc& )
381 {
382 newSchematic->CreateDefaultScreens();
383 msg.Printf( _( "Memory exhausted loading schematic '%s'." ), fullFileName );
384 progressReporter.Hide();
385 DisplayErrorMessage( this, msg, wxEmptyString );
386
387 failedLoad = true;
388 }
389
390 SetSchematic( newSchematic.release() );
391
392 // This fixes a focus issue after the progress reporter is done on GTK. It shouldn't
393 // cause any issues on macOS and Windows. If it does, it will have to be conditionally
394 // compiled.
395 Raise();
396
397 if( failedLoad )
398 {
399 // Do not leave g_RootSheet == NULL because it is expected to be
400 // a valid sheet. Therefore create a dummy empty root sheet and screen.
403
404 msg.Printf( _( "Failed to load '%s'." ), fullFileName );
405 SetMsgPanel( wxEmptyString, msg );
406
407 return false;
408 }
409
410 // Load project settings after schematic has been set up with the project link, since this will
411 // update some of the needed schematic settings such as drawing defaults
413
414 // It's possible the schematic parser fixed errors due to bugs so warn the user
415 // that the schematic has been fixed (modified).
416 SCH_SHEET_LIST sheetList = Schematic().Hierarchy();
417
418 if( sheetList.IsModified() )
419 {
420 DisplayInfoMessage( this,
421 _( "An error was found when loading the schematic that has "
422 "been automatically fixed. Please save the schematic to "
423 "repair the broken file or it may not be usable with other "
424 "versions of KiCad." ) );
425 }
426
427 if( sheetList.AllSheetPageNumbersEmpty() )
428 sheetList.SetInitialPageNumbers();
429
430 UpdateFileHistory( fullFileName );
431
432 SCH_SCREENS schematic( Schematic().Root() );
433
434 // LIB_ID checks and symbol rescue only apply to the legacy file formats.
435 if( schFileType == SCH_IO_MGR::SCH_LEGACY )
436 {
437 // Convert any legacy bus-bus entries to just be bus wires
438 for( SCH_SCREEN* screen = schematic.GetFirst(); screen; screen = schematic.GetNext() )
439 {
440 std::vector<SCH_ITEM*> deleted;
441
442 for( SCH_ITEM* item : screen->Items() )
443 {
444 if( item->Type() == SCH_BUS_BUS_ENTRY_T )
445 {
446 SCH_BUS_BUS_ENTRY* entry = static_cast<SCH_BUS_BUS_ENTRY*>( item );
447 std::unique_ptr<SCH_LINE> wire = std::make_unique<SCH_LINE>();
448
449 wire->SetLayer( LAYER_BUS );
450 wire->SetStartPoint( entry->GetPosition() );
451 wire->SetEndPoint( entry->GetEnd() );
452
453 screen->Append( wire.release() );
454 deleted.push_back( item );
455 }
456 }
457
458 for( SCH_ITEM* item : deleted )
459 screen->Remove( item );
460 }
461
462
463 // Convert old projects over to use symbol library table.
464 if( schematic.HasNoFullyDefinedLibIds() )
465 {
466 DIALOG_SYMBOL_REMAP dlgRemap( this );
467
468 dlgRemap.ShowQuasiModal();
469 }
470 else
471 {
472 // Double check to ensure no legacy library list entries have been
473 // added to the project file symbol library list.
474 wxString paths;
475 wxArrayString libNames;
476
477 LEGACY_SYMBOL_LIBS::GetLibNamesAndPaths( &Prj(), &paths, &libNames );
478
479 if( !libNames.IsEmpty() )
480 {
481 if( eeconfig()->m_Appearance.show_illegal_symbol_lib_dialog )
482 {
483 wxRichMessageDialog invalidLibDlg(
484 this,
485 _( "Illegal entry found in project file symbol library list." ),
486 _( "Project Load Warning" ),
487 wxOK | wxCENTER | wxICON_EXCLAMATION );
488 invalidLibDlg.ShowDetailedText(
489 _( "Symbol libraries defined in the project file symbol library "
490 "list are no longer supported and will be removed.\n\n"
491 "This may cause broken symbol library links under certain "
492 "conditions." ) );
493 invalidLibDlg.ShowCheckBox( _( "Do not show this dialog again." ) );
494 invalidLibDlg.ShowModal();
496 !invalidLibDlg.IsCheckBoxChecked();
497 }
498
499 libNames.Clear();
500 paths.Clear();
501 LEGACY_SYMBOL_LIBS::SetLibNamesAndPaths( &Prj(), paths, libNames );
502 }
503
504 if( !cfg || !cfg->m_RescueNeverShow )
505 {
507 editor->RescueSymbolLibTableProject( false );
508 }
509 }
510
511 // Ensure there is only one legacy library loaded and that it is the cache library.
512 LEGACY_SYMBOL_LIBS* legacyLibs = PROJECT_SCH::LegacySchLibs( &Schematic().Project() );
513
514 if( legacyLibs->GetLibraryCount() == 0 )
515 {
516 wxString extMsg;
517 wxFileName cacheFn = pro;
518
519 wxLogTrace( traceAutoSave, "[SetName dbg] cacheFn BEFORE path='%s' name='%s' full='%s' arg='%s'",
520 cacheFn.GetPath(), cacheFn.GetName(), cacheFn.GetFullPath(), cacheFn.GetName() + "-cache" );
521 cacheFn.SetName( cacheFn.GetName() + "-cache" );
522 wxLogTrace( traceAutoSave, "[SetName dbg] cacheFn AFTER path='%s' name='%s' full='%s'",
523 cacheFn.GetPath(), cacheFn.GetName(), cacheFn.GetFullPath() );
525
526 msg.Printf( _( "The project symbol library cache file '%s' was not found." ),
527 cacheFn.GetFullName() );
528 extMsg = _( "This can result in a broken schematic under certain conditions. "
529 "If the schematic does not have any missing symbols upon opening, "
530 "save it immediately before making any changes to prevent data "
531 "loss. If there are missing symbols, either manual recovery of "
532 "the schematic or recovery of the symbol cache library file and "
533 "reloading the schematic is required." );
534
535 wxMessageDialog dlgMissingCache( this, msg, _( "Warning" ),
536 wxOK | wxCANCEL | wxICON_EXCLAMATION | wxCENTER );
537 dlgMissingCache.SetExtendedMessage( extMsg );
538 dlgMissingCache.SetOKCancelLabels(
539 wxMessageDialog::ButtonLabel( _( "Load Without Cache File" ) ),
540 wxMessageDialog::ButtonLabel( _( "Abort" ) ) );
541
542 if( dlgMissingCache.ShowModal() == wxID_CANCEL )
543 {
544 Schematic().Reset();
546 return false;
547 }
548 }
549
550 // Update all symbol library links for all sheets.
551 schematic.UpdateSymbolLinks();
552
553 m_infoBar->RemoveAllButtons();
554 m_infoBar->AddCloseButton();
555 m_infoBar->ShowMessage( _( "This file was created by an older version of KiCad. "
556 "It will be converted to the new format when saved." ),
558
559 // Legacy schematic can have duplicate time stamps so fix that before converting
560 // to the s-expression format.
561 schematic.ReplaceDuplicateTimeStamps();
562
563 for( SCH_SCREEN* screen = schematic.GetFirst(); screen; screen = schematic.GetNext() )
564 screen->FixLegacyPowerSymbolMismatches();
565
566 // Allow the schematic to be saved to new file format without making any edits.
567 OnModify();
568 }
569 else // S-expression schematic.
570 {
571 SCH_SCREEN* first_screen = schematic.GetFirst();
572
573 // Skip the first screen as it is a virtual root with no version info.
574 if( first_screen->GetFileFormatVersionAtLoad() == 0 )
575 first_screen = schematic.GetNext();
576
577 if( first_screen && first_screen->GetFileFormatVersionAtLoad() < SEXPR_SCHEMATIC_FILE_VERSION )
578 {
579 m_infoBar->RemoveAllButtons();
580 m_infoBar->AddCloseButton();
581 m_infoBar->ShowMessage( _( "This file was created by an older version of KiCad. "
582 "It will be converted to the new format when saved." ),
584 }
585
586 for( SCH_SCREEN* screen = schematic.GetFirst(); screen; screen = schematic.GetNext() )
588
589 // Restore all of the loaded symbol and sheet instances from the root sheet.
590 if( Schematic().RootScreen()->GetFileFormatVersionAtLoad() < 20221002 )
591 sheetList.UpdateSymbolInstanceData( Schematic().RootScreen()->GetSymbolInstances() );
592
593 if( Schematic().RootScreen()->GetFileFormatVersionAtLoad() < 20221110 )
594 sheetList.UpdateSheetInstanceData( Schematic().RootScreen()->GetSheetInstances());
595
596 if( Schematic().RootScreen()->GetFileFormatVersionAtLoad() < 20230221 )
597 for( SCH_SCREEN* screen = schematic.GetFirst(); screen;
598 screen = schematic.GetNext() )
599 screen->FixLegacyPowerSymbolMismatches();
600
601 for( SCH_SCREEN* screen = schematic.GetFirst(); screen; screen = schematic.GetNext() )
602 screen->MigrateSimModels();
603 }
604
605 // After the schematic is successfully loaded, we load the drawing sheet.
606 // This allows us to use the drawing sheet embedded in the schematic (if any)
607 // instead of the default one.
609
610 schematic.PruneOrphanedSymbolInstances( Prj().GetProjectName(), sheetList );
611 schematic.PruneOrphanedSheetInstances( Prj().GetProjectName(), sheetList );
612
613 wxLogTrace( traceSchCurrentSheet,
614 "Before CheckForMissingSymbolInstances: Current sheet path='%s', size=%zu",
615 GetCurrentSheet().Path().AsString(),
616 GetCurrentSheet().size() );
617 sheetList.CheckForMissingSymbolInstances( Prj().GetProjectName() );
618
620
621 SetScreen( GetCurrentSheet().LastScreen() );
622
623 wxLogTrace( traceSchCurrentSheet,
624 "After SetScreen: Current sheet path='%s', size=%zu",
625 GetCurrentSheet().Path().AsString(),
626 GetCurrentSheet().size() );
627
628 // Migrate conflicting bus definitions
629 // TODO(JE) This should only run once based on schematic file version
630 if( Schematic().ConnectionGraph()->GetBusesNeedingMigration().size() > 0 )
631 {
632 DIALOG_MIGRATE_BUSES dlg( this );
633 dlg.ShowQuasiModal();
634 OnModify();
635 }
636
637 SCH_COMMIT dummy( this );
638
639 progressReporter.Report( _( "Updating connections..." ) );
640 progressReporter.KeepRefreshing();
641
642 RecalculateConnections( &dummy, GLOBAL_CLEANUP, &progressReporter );
643
644 if( schematic.HasSymbolFieldNamesWithWhiteSpace() )
645 {
646 m_infoBar->QueueShowMessage( _( "This schematic contains symbols that have leading "
647 "and/or trailing white space field names." ),
648 wxICON_WARNING );
649 }
650 }
651
652 // Load any exclusions from the project file
654
657
660
661 // Re-create junctions if needed. Eeschema optimizes wires by merging
662 // colinear segments. If a schematic is saved without a valid
663 // cache library or missing installed libraries, this can cause connectivity errors
664 // unless junctions are added.
665 //
666 // TODO: (RFB) This really needs to be put inside the Load() function of the SCH_IO_KICAD_LEGACY
667 // I can't put it right now because of the extra code that is above to convert legacy bus-bus
668 // entries to bus wires
669 if( schFileType == SCH_IO_MGR::SCH_LEGACY )
671
672 SyncView();
674
676
677 UpdateHierarchyNavigator( false, true );
678
679 wxCommandEvent changedEvt( EDA_EVT_SCHEMATIC_CHANGED );
680 ProcessEventLocally( changedEvt );
681
682 if( !differentProject && Kiface().IsSingle() )
683 {
684 // If we didn't reload the project, we still want to send the notification so that
685 // things that are supposed to happen on project load can happen again on reload
687 }
688
689 for( wxEvtHandler* listener : m_schematicChangeListeners )
690 {
691 wxCHECK2( listener, continue );
692
693 // Use the windows variant when handling event messages in case there is any special
694 // event handler pre and/or post processing specific to windows.
695 wxWindow* win = dynamic_cast<wxWindow*>( listener );
696
697 if( win )
698 win->HandleWindowEvent( e );
699 else
700 listener->SafelyProcessEvent( e );
701 }
702
703 updateTitle();
704 m_toolManager->GetTool<SCH_NAVIGATE_TOOL>()->ResetHistory();
705
706 wxFileName fn = Prj().AbsolutePath( GetScreen()->GetFileName() );
707
708 if( fn.FileExists() && !fn.IsFileWritable() )
709 {
710 m_infoBar->RemoveAllButtons();
711 m_infoBar->AddCloseButton();
712 m_infoBar->ShowMessage( _( "Schematic is read only." ),
714 }
715
716#ifdef PROFILE
717 openFiles.Show();
718#endif
719 // Ensure all items are redrawn (especially the drawing-sheet items):
720 if( GetCanvas() )
721 GetCanvas()->DisplaySheet( GetCurrentSheet().LastScreen() );
722
723 // Trigger a library load to handle any project-specific libraries
724 CallAfter( [&]()
725 {
726 KIFACE *schface = Kiway().KiFACE( KIWAY::FACE_SCH );
727 schface->PreloadLibraries( &Kiway() );
728
730 } );
731
732 m_remoteSymbolPane->BindWebViewLoaded();
733
734 return true;
735}
736
737
738void SCH_EDIT_FRAME::OnImportProject( wxCommandEvent& aEvent )
739{
740 if( Schematic().RootScreen() && !Schematic().RootScreen()->Items().empty() )
741 {
742 wxString msg = _( "This operation replaces the contents of the current schematic, "
743 "which will be permanently lost.\n\n"
744 "Do you want to proceed?" );
745
746 if( !IsOK( this, msg ) )
747 return;
748 }
749
750 // Set the project location if none is set or if we are running in standalone mode
751 bool setProject = Prj().GetProjectFullName().IsEmpty() || Kiface().IsSingle();
752 wxString path = wxPathOnly( Prj().GetProjectFullName() );
753
754 wxString fileFiltersStr;
755 wxString allWildcardsStr;
756
757 for( const SCH_IO_MGR::SCH_FILE_T& fileType : SCH_IO_MGR::SCH_FILE_T_vector )
758 {
759 if( fileType == SCH_IO_MGR::SCH_KICAD || fileType == SCH_IO_MGR::SCH_LEGACY )
760 continue; // this is "Import non-KiCad schematic"
761
762 IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( fileType ) );
763
764 if( !pi )
765 continue;
766
767 const IO_BASE::IO_FILE_DESC& desc = pi->GetSchematicFileDesc();
768
769 if( desc.m_FileExtensions.empty() || !desc.m_CanRead )
770 continue;
771
772 if( !fileFiltersStr.IsEmpty() )
773 fileFiltersStr += wxChar( '|' );
774
775 fileFiltersStr += desc.FileFilter();
776
777 for( const std::string& ext : desc.m_FileExtensions )
778 allWildcardsStr << wxS( "*." ) << formatWildcardExt( ext ) << wxS( ";" );
779 }
780
781 fileFiltersStr = _( "All supported formats" ) + wxS( "|" ) + allWildcardsStr + wxS( "|" )
782 + fileFiltersStr;
783
784 wxFileDialog dlg( this, _( "Import Schematic" ), path, wxEmptyString, fileFiltersStr,
785 wxFD_OPEN | wxFD_FILE_MUST_EXIST ); // TODO
786
787 FILEDLG_IMPORT_NON_KICAD importOptions( eeconfig()->m_System.show_import_issues );
788 dlg.SetCustomizeHook( importOptions );
789
790 if( dlg.ShowModal() == wxID_CANCEL )
791 return;
792
794
795 // Don't leave dangling pointers to previously-opened document.
796 m_toolManager->GetTool<SCH_SELECTION_TOOL>()->ClearSelection();
799
800 if( setProject )
801 {
802 Schematic().SetProject( nullptr );
803 GetSettingsManager()->UnloadProject( &Prj(), false );
804
805 // Clear view before destroying schematic as repaints depend on schematic being valid
806 SetScreen( nullptr );
807
808 Schematic().Reset();
809
810 wxFileName projectFn( dlg.GetPath() );
811 projectFn.SetExt( FILEEXT::ProjectFileExtension );
812 GetSettingsManager()->LoadProject( projectFn.GetFullPath() );
813 }
814
815 wxFileName fn = dlg.GetPath();
816
817 if( !fn.IsFileReadable() )
818 {
819 wxLogError( _( "Insufficient permissions to read file '%s'." ), fn.GetFullPath() );
820 return;
821 }
822
823 SCH_IO_MGR::SCH_FILE_T pluginType = SCH_IO_MGR::SCH_FILE_T::SCH_FILE_UNKNOWN;
824
825 for( const SCH_IO_MGR::SCH_FILE_T& fileType : SCH_IO_MGR::SCH_FILE_T_vector )
826 {
827 IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( fileType ) );
828
829 if( !pi )
830 continue;
831
832 if( pi->CanReadSchematicFile( fn.GetFullPath() ) )
833 {
834 pluginType = fileType;
835 break;
836 }
837 }
838
839 if( pluginType == SCH_IO_MGR::SCH_FILE_T::SCH_FILE_UNKNOWN )
840 {
841 wxLogError( _( "No loader can read the specified file: '%s'." ), fn.GetFullPath() );
843 SetScreen( Schematic().RootScreen() );
844 return;
845 }
846
847 importFile( dlg.GetPath(), pluginType );
848
850}
851
852
853bool SCH_EDIT_FRAME::saveSchematicFile( SCH_SHEET* aSheet, const wxString& aSavePath )
854{
855 wxString msg;
856 wxFileName schematicFileName;
857 wxFileName oldFileName;
858 bool success;
859
860 SCH_SCREEN* screen = aSheet->GetScreen();
861
862 wxCHECK( screen, false );
863
864 // Cannot save to nowhere
865 if( aSavePath.IsEmpty() )
866 return false;
867
868 // Construct the name of the file to be saved
869 schematicFileName = Prj().AbsolutePath( aSavePath );
870 oldFileName = schematicFileName;
871
872 // Write through symlinks, don't replace them
873 WX_FILENAME::ResolvePossibleSymlinks( schematicFileName );
874
875 if( !schematicFileName.DirExists() )
876 {
877 if( !wxMkdir( schematicFileName.GetPath() ) )
878 {
879 msg.Printf( _( "Error saving schematic file '%s'.\n%s" ),
880 schematicFileName.GetFullPath(),
881 "Could not create directory: %s" + schematicFileName.GetPath() );
882 DisplayError( this, msg );
883
884 return false;
885 }
886 }
887
888 if( !IsWritable( schematicFileName ) )
889 return false;
890
891 wxFileName projectFile( schematicFileName );
892
893 projectFile.SetExt( FILEEXT::ProjectFileExtension );
894
895 if( projectFile.FileExists() )
896 {
897 // Save various ERC settings, such as violation severities (which may have been edited
898 // via the ERC dialog as well as the Schematic Setup dialog), ERC exclusions, etc.
900 }
901
902 // Save
903 wxLogTrace( traceAutoSave, wxS( "Saving file " ) + schematicFileName.GetFullPath() );
904
905 if( m_infoBar->GetMessageType() == WX_INFOBAR::MESSAGE_TYPE::OUTDATED_SAVE )
906 m_infoBar->Dismiss();
907
908 SCH_IO_MGR::SCH_FILE_T pluginType = SCH_IO_MGR::GuessPluginTypeFromSchPath(
909 schematicFileName.GetFullPath() );
910
911 if( pluginType == SCH_IO_MGR::SCH_FILE_UNKNOWN )
912 pluginType = SCH_IO_MGR::SCH_KICAD;
913
914 IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( pluginType ) );
915
916 try
917 {
918 pi->SaveSchematicFile( schematicFileName.GetFullPath(), aSheet, &Schematic() );
919 success = true;
920 }
921 catch( const IO_ERROR& ioe )
922 {
923 msg.Printf( _( "Error saving schematic file '%s'.\n%s" ),
924 schematicFileName.GetFullPath(),
925 ioe.What() );
926 DisplayError( this, msg );
927
928 success = false;
929 }
930
931 if( success )
932 {
933 screen->SetContentModified( false );
934
935 msg.Printf( _( "File '%s' saved." ), screen->GetFileName() );
936 SetStatusText( msg, 0 );
937
938 // Record a full project snapshot so related files (symbols, libs, sheets) are captured.
939 Kiway().LocalHistory().CommitFullProjectSnapshot( schematicFileName.GetPath(), wxS( "SCH Save" ) );
940 Kiway().LocalHistory().TagSave( schematicFileName.GetPath(), wxS( "sch" ) );
941
942 if( m_autoSaveTimer )
943 m_autoSaveTimer->Stop();
944
945 m_autoSavePending = false;
946 m_autoSaveRequired = false;
947 }
948
949 return success;
950}
951
952
953bool PrepareSaveAsFiles( SCHEMATIC& aSchematic, SCH_SCREENS& aScreens,
954 const wxFileName& aOldRoot, const wxFileName& aNewRoot,
955 bool aSaveCopy, bool aCopySubsheets, bool aIncludeExternSheets,
956 std::unordered_map<SCH_SCREEN*, wxString>& aFilenameMap,
957 wxString& aErrorMsg )
958{
959 SCH_SCREEN* screen;
960
961 for( size_t i = 0; i < aScreens.GetCount(); i++ )
962 {
963 screen = aScreens.GetScreen( i );
964
965 wxCHECK2( screen, continue );
966
967 if( screen == aSchematic.RootScreen() )
968 continue;
969
970 wxFileName src = screen->GetFileName();
971
972 if( !src.IsAbsolute() )
973 src.MakeAbsolute( aOldRoot.GetPath() );
974
975 bool internalSheet = src.GetPath().StartsWith( aOldRoot.GetPath() );
976
977 if( aCopySubsheets && ( internalSheet || aIncludeExternSheets ) )
978 {
979 wxFileName dest = src;
980
981 if( internalSheet && dest.MakeRelativeTo( aOldRoot.GetPath() ) )
982 dest.MakeAbsolute( aNewRoot.GetPath() );
983 else
984 dest.Assign( aNewRoot.GetPath(), dest.GetFullName() );
985
986 wxLogTrace( tracePathsAndFiles,
987 wxS( "Moving schematic from '%s' to '%s'." ),
988 screen->GetFileName(),
989 dest.GetFullPath() );
990
991 if( !dest.DirExists() && !dest.Mkdir() )
992 {
993 aErrorMsg.Printf( _( "Folder '%s' could not be created.\n\n"
994 "Make sure you have write permissions and try again." ),
995 dest.GetPath() );
996 return false;
997 }
998
999 if( aSaveCopy )
1000 aFilenameMap[screen] = dest.GetFullPath();
1001 else
1002 screen->SetFileName( dest.GetFullPath() );
1003 }
1004 else
1005 {
1006 if( aSaveCopy )
1007 aFilenameMap[screen] = wxString();
1008
1009 screen->SetFileName( src.GetFullPath() );
1010 }
1011 }
1012
1013 for( SCH_SHEET_PATH& sheet : aSchematic.Hierarchy() )
1014 {
1015 if( !sheet.Last()->IsTopLevelSheet() )
1016 sheet.MakeFilePathRelativeToParentSheet();
1017 }
1018
1019 return true;
1020}
1021
1023{
1024 wxString msg;
1025 SCH_SCREEN* screen;
1026 SCH_SCREENS screens( Schematic().Root() );
1027 bool saveCopy = aSaveAs && !Kiface().IsSingle();
1028 bool success = true;
1029 bool updateFileHistory = false;
1030 bool createNewProject = false;
1031 bool copySubsheets = false;
1032 bool includeExternSheets = false;
1033
1034 // I want to see it in the debugger, show me the string! Can't do that with wxFileName.
1035 wxString fileName = Prj().AbsolutePath( Schematic().Root().GetFileName() );
1036 wxFileName fn = fileName;
1037
1038 // Path to save each screen to: will be the stored filename by default, but is overwritten by
1039 // a Save As Copy operation.
1040 std::unordered_map<SCH_SCREEN*, wxString> filenameMap;
1041
1042 // Handle "Save As" and saving a new project/schematic for the first time in standalone
1043 if( Prj().IsNullProject() || aSaveAs )
1044 {
1045 // Null project should only be possible in standalone mode.
1046 wxCHECK( Kiface().IsSingle() || aSaveAs, false );
1047
1048 wxFileName newFileName;
1049 wxFileName savePath( Prj().GetProjectFullName() );
1050
1051 if( !savePath.IsOk() || !savePath.IsDirWritable() )
1052 {
1053 savePath = GetMruPath();
1054
1055 if( !savePath.IsOk() || !savePath.IsDirWritable() )
1057 }
1058
1059 if( savePath.HasExt() )
1060 savePath.SetExt( FILEEXT::KiCadSchematicFileExtension );
1061 else
1062 savePath.SetName( wxEmptyString );
1063
1064 wxFileDialog dlg( this, _( "Schematic Files" ), savePath.GetPath(), savePath.GetFullName(),
1066 wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
1067
1068 FILEDLG_HOOK_SAVE_PROJECT newProjectHook;
1069
1070 // Add a "Create a project" checkbox in standalone mode and one isn't loaded
1071 if( Kiface().IsSingle() || aSaveAs )
1072 {
1073 dlg.SetCustomizeHook( newProjectHook );
1074 }
1075
1076 if( dlg.ShowModal() == wxID_CANCEL )
1077 return false;
1078
1079 newFileName = EnsureFileExtension( dlg.GetPath(), FILEEXT::KiCadSchematicFileExtension );
1080
1081 if( ( !newFileName.DirExists() && !newFileName.Mkdir() ) ||
1082 !newFileName.IsDirWritable() )
1083 {
1084 msg.Printf( _( "Folder '%s' could not be created.\n\n"
1085 "Make sure you have write permissions and try again." ),
1086 newFileName.GetPath() );
1087
1088 wxMessageDialog dlgBadPath( this, msg, _( "Error" ),
1089 wxOK | wxICON_EXCLAMATION | wxCENTER );
1090
1091 dlgBadPath.ShowModal();
1092 return false;
1093 }
1094
1095 if( newProjectHook.IsAttachedToDialog() )
1096 {
1097 createNewProject = newProjectHook.GetCreateNewProject();
1098 copySubsheets = newProjectHook.GetCopySubsheets();
1099 includeExternSheets = newProjectHook.GetIncludeExternSheets();
1100 }
1101
1102 if( !saveCopy )
1103 {
1104 Schematic().Root().SetFileName( newFileName.GetFullName() );
1105 Schematic().RootScreen()->SetFileName( newFileName.GetFullPath() );
1106 updateFileHistory = true;
1107 }
1108 else
1109 {
1110 filenameMap[Schematic().RootScreen()] = newFileName.GetFullPath();
1111 }
1112
1113 if( !PrepareSaveAsFiles( Schematic(), screens, fn, newFileName, saveCopy,
1114 copySubsheets, includeExternSheets, filenameMap, msg ) )
1115 {
1116 wxMessageDialog dlgBadFilePath( this, msg, _( "Error" ),
1117 wxOK | wxICON_EXCLAMATION | wxCENTER );
1118
1119 dlgBadFilePath.ShowModal();
1120 return false;
1121 }
1122 }
1123 else if( !fn.FileExists() )
1124 {
1125 // File doesn't exist yet; true if we just imported something
1126 updateFileHistory = true;
1127 }
1128 else if( screens.GetFirst() && screens.GetFirst()->GetFileFormatVersionAtLoad() < SEXPR_SCHEMATIC_FILE_VERSION )
1129 {
1130 // Allow the user to save un-edited files in new format
1131 }
1132 else if( !IsContentModified() )
1133 {
1134 return true;
1135 }
1136
1137 if( filenameMap.empty() || !saveCopy )
1138 {
1139 for( size_t i = 0; i < screens.GetCount(); i++ )
1140 filenameMap[screens.GetScreen( i )] = screens.GetScreen( i )->GetFileName();
1141 }
1142
1143 // Warn user on potential file overwrite. This can happen on shared sheets.
1144 wxArrayString overwrittenFiles;
1145 wxArrayString lockedFiles;
1146
1147 for( size_t i = 0; i < screens.GetCount(); i++ )
1148 {
1149 screen = screens.GetScreen( i );
1150
1151 wxCHECK2( screen, continue );
1152
1153 // Convert legacy schematics file name extensions for the new format.
1154 wxFileName tmpFn = filenameMap[screen];
1155
1156 if( !tmpFn.IsOk() )
1157 continue;
1158
1159 if( tmpFn.FileExists() && !tmpFn.IsFileWritable() )
1160 lockedFiles.Add( tmpFn.GetFullPath() );
1161
1162 if( tmpFn.GetExt() == FILEEXT::KiCadSchematicFileExtension )
1163 continue;
1164
1166
1167 if( tmpFn.FileExists() )
1168 overwrittenFiles.Add( tmpFn.GetFullPath() );
1169 }
1170
1171 if( !lockedFiles.IsEmpty() )
1172 {
1173 for( const wxString& lockedFile : lockedFiles )
1174 {
1175 if( msg.IsEmpty() )
1176 msg = lockedFile;
1177 else
1178 msg += "\n" + lockedFile;
1179 }
1180
1181 wxRichMessageDialog dlg( this, wxString::Format( _( "Failed to save %s." ),
1182 Schematic().Root().GetFileName() ),
1183 _( "Locked File Warning" ),
1184 wxOK | wxICON_WARNING | wxCENTER );
1185 dlg.SetExtendedMessage( _( "You do not have write permissions to:\n\n" ) + msg );
1186
1187 dlg.ShowModal();
1188 return false;
1189 }
1190
1191 if( !overwrittenFiles.IsEmpty() )
1192 {
1193 for( const wxString& overwrittenFile : overwrittenFiles )
1194 {
1195 if( msg.IsEmpty() )
1196 msg = overwrittenFile;
1197 else
1198 msg += "\n" + overwrittenFile;
1199 }
1200
1201 wxRichMessageDialog dlg( this, _( "Saving will overwrite existing files." ),
1202 _( "Save Warning" ),
1203 wxOK | wxCANCEL | wxCANCEL_DEFAULT | wxCENTER |
1204 wxICON_EXCLAMATION );
1205 dlg.ShowDetailedText( _( "The following files will be overwritten:\n\n" ) + msg );
1206 dlg.SetOKCancelLabels( wxMessageDialog::ButtonLabel( _( "Overwrite Files" ) ),
1207 wxMessageDialog::ButtonLabel( _( "Abort Project Save" ) ) );
1208
1209 if( dlg.ShowModal() == wxID_CANCEL )
1210 return false;
1211 }
1212
1213 screens.BuildClientSheetPathList();
1214
1215 for( size_t i = 0; i < screens.GetCount(); i++ )
1216 {
1217 screen = screens.GetScreen( i );
1218
1219 wxCHECK2( screen, continue );
1220
1221 // Convert legacy schematics file name extensions for the new format.
1222 wxFileName tmpFn = filenameMap[screen];
1223
1224 if( tmpFn.IsOk() && tmpFn.GetExt() != FILEEXT::KiCadSchematicFileExtension )
1225 {
1226 updateFileHistory = true;
1228
1229 for( EDA_ITEM* item : screen->Items().OfType( SCH_SHEET_T ) )
1230 {
1231 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
1232 wxFileName sheetFileName = sheet->GetFileName();
1233
1234 if( !sheetFileName.IsOk()
1235 || sheetFileName.GetExt() == FILEEXT::KiCadSchematicFileExtension )
1236 continue;
1237
1238 sheetFileName.SetExt( FILEEXT::KiCadSchematicFileExtension );
1239 sheet->SetFileName( sheetFileName.GetFullPath() );
1240 UpdateItem( sheet );
1241 }
1242
1243 filenameMap[screen] = tmpFn.GetFullPath();
1244
1245 if( !saveCopy )
1246 screen->SetFileName( tmpFn.GetFullPath() );
1247 }
1248
1249 // Do not save sheet symbols with no valid filename set
1250 if( !tmpFn.IsOk() )
1251 continue;
1252
1253 std::vector<SCH_SHEET_PATH>& sheets = screen->GetClientSheetPaths();
1254
1255 if( sheets.size() == 1 )
1256 screen->SetVirtualPageNumber( 1 );
1257 else
1258 screen->SetVirtualPageNumber( 0 ); // multiple uses; no way to store the real sheet #
1259
1260 // This is a new schematic file so make sure it has a unique ID.
1261 if( !saveCopy && tmpFn.GetFullPath() != screen->GetFileName() )
1262 screen->AssignNewUuid();
1263
1264 success &= saveSchematicFile( screens.GetSheet( i ), tmpFn.GetFullPath() );
1265 }
1266
1267 if( success )
1268 m_autoSaveRequired = false;
1269
1270 if( aSaveAs && success )
1271 LockFile( Schematic().RootScreen()->GetFileName() );
1272
1273 if( updateFileHistory )
1274 UpdateFileHistory( Schematic().RootScreen()->GetFileName() );
1275
1276 // Save the sheet name map to the project file
1277 std::vector<FILE_INFO_PAIR>& sheets = Prj().GetProjectFile().GetSheets();
1278 sheets.clear();
1279
1280 for( SCH_SHEET_PATH& sheetPath : Schematic().Hierarchy() )
1281 {
1282 SCH_SHEET* sheet = sheetPath.Last();
1283
1284 wxCHECK2( sheet, continue );
1285
1286 // Do not save the virtual root sheet
1287 if( !sheet->IsVirtualRootSheet() )
1288 {
1289 sheets.emplace_back( std::make_pair( sheet->m_Uuid, sheet->GetName() ) );
1290 }
1291 }
1292
1293 wxASSERT( filenameMap.count( Schematic().RootScreen() ) );
1294 wxFileName projectPath( filenameMap.at( Schematic().RootScreen() ) );
1295 projectPath.SetExt( FILEEXT::ProjectFileExtension );
1296
1297 if( Prj().IsNullProject() || ( aSaveAs && !saveCopy ) )
1298 {
1299 Prj().SetReadOnly( !createNewProject );
1300 GetSettingsManager()->SaveProjectAs( projectPath.GetFullPath() );
1301 }
1302 else if( saveCopy && createNewProject )
1303 {
1304 GetSettingsManager()->SaveProjectCopy( projectPath.GetFullPath() );
1305 }
1306 else
1307 {
1310 }
1311
1312 if( !Kiface().IsSingle() )
1313 {
1314 WX_STRING_REPORTER backupReporter;
1315
1316 if( !GetSettingsManager()->TriggerBackupIfNeeded( backupReporter ) )
1317 SetStatusText( backupReporter.GetMessages(), 0 );
1318 }
1319
1320 updateTitle();
1321
1322 if( m_infoBar->GetMessageType() == WX_INFOBAR::MESSAGE_TYPE::OUTDATED_SAVE )
1323 m_infoBar->Dismiss();
1324
1325 return success;
1326}
1327
1328
1329bool SCH_EDIT_FRAME::importFile( const wxString& aFileName, int aFileType,
1330 const std::map<std::string, UTF8>* aProperties )
1331{
1332 wxFileName filename( aFileName );
1333 wxFileName newfilename;
1334 SCH_IO_MGR::SCH_FILE_T fileType = (SCH_IO_MGR::SCH_FILE_T) aFileType;
1335
1336 wxCommandEvent changingEvt( EDA_EVT_SCHEMATIC_CHANGING );
1337 ProcessEventLocally( changingEvt );
1338
1339 std::unique_ptr<SCHEMATIC> newSchematic = std::make_unique<SCHEMATIC>( &Prj() );
1340
1341 switch( fileType )
1342 {
1343 case SCH_IO_MGR::SCH_ALTIUM:
1344 case SCH_IO_MGR::SCH_CADSTAR_ARCHIVE:
1345 case SCH_IO_MGR::SCH_EAGLE:
1346 case SCH_IO_MGR::SCH_LTSPICE:
1347 case SCH_IO_MGR::SCH_EASYEDA:
1348 case SCH_IO_MGR::SCH_EASYEDAPRO:
1349 {
1350 // We insist on caller sending us an absolute path, if it does not, we say it's a bug.
1351 // Unless we are passing the files in aproperties, in which case aFileName can be empty.
1352 wxCHECK_MSG( aFileName.IsEmpty() || filename.IsAbsolute(), false,
1353 wxS( "Import schematic: path is not absolute!" ) );
1354
1355 try
1356 {
1357 IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( fileType ) );
1358 DIALOG_HTML_REPORTER errorReporter( this );
1359 WX_PROGRESS_REPORTER progressReporter( this, _( "Import Schematic" ), 1, PR_CAN_ABORT );
1360
1361 if( PROJECT_CHOOSER_PLUGIN* c_pi = dynamic_cast<PROJECT_CHOOSER_PLUGIN*>( pi.get() ) )
1362 {
1363 c_pi->RegisterCallback( std::bind( DIALOG_IMPORT_CHOOSE_PROJECT::RunModal,
1364 this, std::placeholders::_1 ) );
1365 }
1366
1367 if( eeconfig()->m_System.show_import_issues )
1368 pi->SetReporter( errorReporter.m_Reporter );
1369 else
1370 pi->SetReporter( &NULL_REPORTER::GetInstance() );
1371
1372 pi->SetProgressReporter( &progressReporter );
1373
1374 SCH_SHEET* loadedSheet = pi->LoadSchematicFile( aFileName, newSchematic.get(), nullptr,
1375 aProperties );
1376
1377 SetSchematic( newSchematic.release() );
1378
1379 if( loadedSheet )
1380 {
1381 Schematic().SetRoot( loadedSheet );
1382
1383 if( errorReporter.m_Reporter->HasMessage() )
1384 {
1385 errorReporter.m_Reporter->Flush(); // Build HTML messages
1386 errorReporter.ShowModal();
1387 }
1388
1389 // Non-KiCad schematics do not use a drawing-sheet (or if they do, it works
1390 // differently to KiCad), so set it to an empty one.
1392 drawingSheet.SetEmptyLayout();
1393 BASE_SCREEN::m_DrawingSheetFileName = "empty.kicad_wks";
1394
1395 newfilename.SetPath( Prj().GetProjectPath() );
1396 newfilename.SetName( Prj().GetProjectName() );
1397 newfilename.SetExt( FILEEXT::KiCadSchematicFileExtension );
1398
1399 SetScreen( Schematic().RootScreen() );
1400
1401 Schematic().Root().SetFileName( newfilename.GetFullName() );
1402 GetScreen()->SetFileName( newfilename.GetFullPath() );
1404
1405 progressReporter.Report( _( "Updating connections..." ) );
1406
1407 if( !progressReporter.KeepRefreshing() )
1408 THROW_IO_ERROR( _( "File import canceled by user." ) );
1409
1410 RecalculateConnections( nullptr, GLOBAL_CLEANUP, &progressReporter );
1411
1412 // Only perform the dangling end test on root sheet.
1414 }
1415 else
1416 {
1418 }
1419 }
1420 catch( const IO_ERROR& ioe )
1421 {
1422 // Do not leave g_RootSheet == NULL because it is expected to be
1423 // a valid sheet. Therefore create a dummy empty root sheet and screen.
1426
1427 wxString msg = wxString::Format( _( "Error loading schematic '%s'." ), aFileName );
1428 DisplayErrorMessage( this, msg, ioe.What() );
1429
1430 msg.Printf( _( "Failed to load '%s'." ), aFileName );
1431 SetMsgPanel( wxEmptyString, msg );
1432 }
1433 catch( const std::exception& exc )
1434 {
1437
1438 wxString msg = wxString::Format( _( "Unhandled exception occurred loading schematic "
1439 "'%s'." ), aFileName );
1440 DisplayErrorMessage( this, msg, exc.what() );
1441
1442 msg.Printf( _( "Failed to load '%s'." ), aFileName );
1443 SetMsgPanel( wxEmptyString, msg );
1444 }
1445
1448
1451 SyncView();
1452
1453 UpdateHierarchyNavigator( false, true );
1454
1455 wxCommandEvent e( EDA_EVT_SCHEMATIC_CHANGED );
1456 ProcessEventLocally( e );
1457
1458 for( wxEvtHandler* listener : m_schematicChangeListeners )
1459 {
1460 wxCHECK2( listener, continue );
1461
1462 // Use the windows variant when handling event messages in case there is any
1463 // special event handler pre and/or post processing specific to windows.
1464 wxWindow* win = dynamic_cast<wxWindow*>( listener );
1465
1466 if( win )
1467 win->HandleWindowEvent( e );
1468 else
1469 listener->SafelyProcessEvent( e );
1470 }
1471
1472 updateTitle();
1473 break;
1474 }
1475
1476 default:
1477 break;
1478 }
1479
1480 return true;
1481}
1482
1483
1485{
1486 SCH_SCREENS screenList( Schematic().Root() );
1487
1488 // Save any currently open and modified project files.
1489 for( SCH_SCREEN* screen = screenList.GetFirst(); screen; screen = screenList.GetNext() )
1490 {
1491 SIMULATOR_FRAME* simFrame = (SIMULATOR_FRAME*) Kiway().Player( FRAME_SIMULATOR, false );
1492
1493 // Simulator must be closed before loading another schematic, otherwise it may crash.
1494 // If there are any changes in the simulator the user will be prompted to save them.
1495 if( simFrame && !simFrame->Close() )
1496 return false;
1497
1498 if( screen->IsContentModified() )
1499 {
1500 if( !HandleUnsavedChanges( this, _( "The current schematic has been modified. "
1501 "Save changes?" ),
1502 [&]() -> bool
1503 {
1504 return SaveProject();
1505 } ) )
1506 {
1507 return false;
1508 }
1509 }
1510 }
1511
1512 return true;
1513}
KIFACE_BASE & Kiface()
Global KIFACE_BASE "get" accessor.
static TOOL_ACTION zoomFitScreen
Definition actions.h:142
void SetVirtualPageNumber(int aPageNumber)
Definition base_screen.h:76
static wxString m_DrawingSheetFileName
the name of the drawing sheet file, or empty to use the default drawing sheet
Definition base_screen.h:85
void SetContentModified(bool aModified=true)
Definition base_screen.h:59
Class DIALOG_HTML_REPORTER.
WX_HTML_REPORT_BOX * m_Reporter
static std::vector< IMPORT_PROJECT_DESC > RunModal(wxWindow *aParent, const std::vector< IMPORT_PROJECT_DESC > &aProjectDesc)
Create and show a dialog (modal) and returns the data from it after completion.
int ShowModal() override
Handle the graphic items list to draw/plot the frame and title block.
static DS_DATA_MODEL & GetTheInstance()
Return the instance of DS_DATA_MODEL used in the application.
void LoadWindowState(const wxString &aFileName)
virtual void ClearUndoRedoList()
Clear the undo and redo list using ClearUndoORRedoList()
SETTINGS_MANAGER * GetSettingsManager() const
WX_INFOBAR * m_infoBar
wxTimer * m_autoSaveTimer
void UpdateFileHistory(const wxString &FullFileName, FILE_HISTORY *aFileHistory=nullptr)
Update the list of recently opened files.
wxString GetMruPath() const
bool IsWritable(const wxFileName &aFileName, bool aVerbose=true)
Check if aFileName can be written.
std::unique_ptr< LOCKFILE > m_file_checker
void SetMsgPanel(const std::vector< MSG_PANEL_ITEM > &aList)
Clear the message panel and populates it with the contents of aList.
void RefreshCanvas() override
bool LockFile(const wxString &aFileName)
Mark a schematic file as being in use.
A base class for most all the KiCad significant classes used in schematics and boards.
Definition eda_item.h:98
const KIID m_Uuid
Definition eda_item.h:516
EE_TYPE OfType(KICAD_T aType) const
Definition sch_rtree.h:241
bool GetCreateNewProject() const
Gets the selected state of the copy subsheets option.
bool GetCopySubsheets() const
Gets the selected state of the include external sheets option.
bool GetIncludeExternSheets() const
Gets if this hook has attached controls to a dialog box.
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 const wxString Problem() const
what was the problem?
APP_SETTINGS_BASE * KifaceSettings() const
Definition kiface_base.h:95
bool IsSingle() const
Is this KIFACE running under single_top?
Definition kiid.h:49
wxString AsString() const
Definition kiid.cpp:246
virtual KIWAY_PLAYER * Player(FRAME_T aFrameType, bool doCreate=true, wxTopLevelWindow *aParent=nullptr)
Return the KIWAY_PLAYER* given a FRAME_T.
Definition kiway.cpp:403
virtual KIFACE * KiFACE(FACE_T aFaceId, bool doLoad=true)
Return the KIFACE* given a FACE_T.
Definition kiway.cpp:206
@ FACE_SCH
eeschema DSO
Definition kiway.h:299
LOCAL_HISTORY & LocalHistory()
Return the LOCAL_HISTORY associated with this KIWAY.
Definition kiway.h:404
A collection of #SYMBOL_LIB objects.
static void GetLibNamesAndPaths(PROJECT *aProject, wxString *aPaths, wxArrayString *aNames=nullptr)
static void SetLibNamesAndPaths(PROJECT *aProject, const wxString &aPaths, const wxArrayString &aNames)
bool TagSave(const wxString &aProjectPath, const wxString &aFileType)
Tag a manual save in the local history repository.
bool Init(const wxString &aProjectPath)
Initialize the local history repository for the given project path.
bool CommitFullProjectSnapshot(const wxString &aProjectPath, const wxString &aTitle)
Commit a snapshot of the entire project directory (excluding the .history directory and ignored trans...
static REPORTER & GetInstance()
Definition reporter.cpp:96
static wxString GetDefaultUserProjectsPath()
Gets the default path we point users to create projects.
Definition paths.cpp:137
void PreloadDesignBlockLibraries(KIWAY *aKiway)
Starts a background job to preload the global and project design block libraries.
Definition pgm_base.cpp:871
void HideSplash()
Definition pgm_base.cpp:297
A small class to help profiling.
Definition profile.h:49
void Show(std::ostream &aStream=std::cerr)
Print the elapsed time (in a suitable unit) to a stream.
Definition profile.h:105
virtual void Report(const wxString &aMessage) override
Display aMessage in the progress bar dialog.
bool KeepRefreshing(bool aWait=false) override
Update the UI dialog.
Plugin class for import plugins that support choosing a project.
The backing store for a PROJECT, in JSON format.
std::vector< FILE_INFO_PAIR > & GetSheets()
std::vector< TOP_LEVEL_SHEET_INFO > & GetTopLevelSheets()
static LEGACY_SYMBOL_LIBS * LegacySchLibs(PROJECT *aProject)
Returns the list of symbol libraries from a legacy (pre-5.x) design This is only used from the remapp...
virtual void SetReadOnly(bool aReadOnly=true)
Definition project.h:168
virtual const wxString GetProjectFullName() const
Return the full path and name of the project.
Definition project.cpp:161
virtual void SetElem(PROJECT::ELEM aIndex, _ELEM *aElem)
Definition project.cpp:380
virtual PROJECT_FILE & GetProjectFile() const
Definition project.h:204
virtual const wxString AbsolutePath(const wxString &aFileName) const
Fix up aFileName if it is relative to the project's directory to be an absolute path and filename.
Definition project.cpp:391
@ LEGACY_SYMBOL_LIBS
Definition project.h:74
Holds all the data relating to one schematic.
Definition schematic.h:88
void Reset()
Initialize this schematic to a blank one, unloading anything existing.
void ResolveERCExclusionsPostUpdate()
Update markers to match recorded exclusions.
SCH_SHEET_LIST Hierarchy() const
Return the full schematic flattened hierarchical sheet list.
void FixupJunctionsAfterImport()
Add junctions to this schematic where required.
void SetRoot(SCH_SHEET *aRootSheet)
Initialize the schematic with a new root sheet.
void SetProject(PROJECT *aPrj)
CONNECTION_GRAPH * ConnectionGraph() const
Definition schematic.h:198
SCH_SCREEN * RootScreen() const
Helper to retrieve the screen of the root sheet.
SCH_SHEET & Root() const
Definition schematic.h:125
SCH_DRAW_PANEL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
void SyncView()
Mark all items for refresh.
EESCHEMA_SETTINGS * eeconfig() const
Class for a bus to bus entry.
VECTOR2I GetPosition() const override
VECTOR2I GetEnd() const
void DisplaySheet(SCH_SCREEN *aScreen)
bool IsContentModified() const override
Get if the current schematic has been modified but not saved.
void OnModify() override
Must be called after a schematic change in order to set the "modify" flag and update other data struc...
void SaveProjectLocalSettings() override
Save changes to the project settings to the project (.pro) file.
bool OpenProjectFiles(const std::vector< wxString > &aFileSet, int aCtl=0) override
Open a project or set of files given by aFileList.
SCH_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
void SetScreen(BASE_SCREEN *aScreen) override
bool AskToSaveChanges()
Check if any of the screens has unsaved changes and asks the user whether to save or drop them.
friend class SCH_EDITOR_CONTROL
std::vector< wxEvtHandler * > m_schematicChangeListeners
PANEL_REMOTE_SYMBOL * m_remoteSymbolPane
SCH_SHEET_PATH & GetCurrentSheet() const
void RecalculateConnections(SCH_COMMIT *aCommit, SCH_CLEANUP_FLAGS aCleanupFlags, PROGRESS_REPORTER *aProgressReporter=nullptr)
Generate the connection data for the entire schematic hierarchy.
void ProjectChanged() override
Notification event that the project has changed.
SCHEMATIC & Schematic() const
void updateTitle()
Set the main window title bar text.
void SetSchematic(SCHEMATIC *aSchematic)
bool saveSchematicFile(SCH_SHEET *aSheet, const wxString &aSavePath)
Save aSheet to a schematic file.
bool LoadProjectSettings()
Load the KiCad project file (*.pro) settings specific to Eeschema.
void RecomputeIntersheetRefs()
Update the schematic's page reference map for all global labels, and refresh the labels so that they ...
void UpdateHierarchyNavigator(bool aRefreshNetNavigator=true, bool aClear=false)
Update the hierarchy navigation tree and history.
bool importFile(const wxString &aFileName, int aFileType, const std::map< std::string, UTF8 > *aProperties=nullptr)
Load the given filename but sets the path to the current project path.
void LoadDrawingSheet()
Load the drawing sheet file.
void SetSheetNumberAndCount()
Set the m_ScreenNumber and m_NumberOfScreens members for screens.
void ClearRepeatItemsList()
Clear the list of items which are to be repeated with the insert key.
void initScreenZoom()
Initialize the zoom value of the current screen and mark the screen as zoom-initialized.
void OnImportProject(wxCommandEvent &event)
void UpdateItem(EDA_ITEM *aItem, bool isAddOrDelete=false, bool aUpdateRtree=false) override
Mark an item for refresh.
wxString GetCurrentFileName() const override
Get the full filename + path of the currently opened file in the frame.
void TestDanglingEnds()
Test all of the connectable objects in the schematic for unused connection points.
bool SaveProject(bool aSaveAs=false)
Save the currently-open schematic (including its hierarchy) and associated project.
void saveProjectSettings() override
Save any design-related project settings associated with this frame.
static SCH_FILE_T GuessPluginTypeFromSchPath(const wxString &aSchematicPath, int aCtl=0)
Return a plugin type given a schematic using the file extension of aSchematicPath.
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition sch_item.h:167
Handle actions specific to the schematic editor.
Container class that holds multiple SCH_SCREEN objects in a hierarchy.
Definition sch_screen.h:728
SCH_SCREEN * GetNext()
SCH_SCREEN * GetScreen(unsigned int aIndex) const
void UpdateSymbolLinks(REPORTER *aReporter=nullptr)
Initialize the LIB_SYMBOL reference for each SCH_SYMBOL found in the full schematic.
SCH_SCREEN * GetFirst()
void PruneOrphanedSheetInstances(const wxString &aProjectName, const SCH_SHEET_LIST &aValidSheetPaths)
void BuildClientSheetPathList()
Build the list of sheet paths sharing a screen for each screen in use.
bool HasSymbolFieldNamesWithWhiteSpace() const
size_t GetCount() const
Definition sch_screen.h:733
void PruneOrphanedSymbolInstances(const wxString &aProjectName, const SCH_SHEET_LIST &aValidSheetPaths)
bool HasNoFullyDefinedLibIds()
Test all of the schematic symbols to see if all LIB_ID objects library nickname is not set.
SCH_SHEET * GetSheet(unsigned int aIndex) const
int ReplaceDuplicateTimeStamps()
Test all sheet and symbol objects in the schematic for duplicate time stamps and replaces them as nec...
void ClearDrawingState()
Clear the state flags of all the items in the screen.
std::vector< SCH_SHEET_PATH > & GetClientSheetPaths()
Return the number of times this screen is used.
Definition sch_screen.h:186
void TestDanglingEnds(const SCH_SHEET_PATH *aPath=nullptr, std::function< void(SCH_ITEM *)> *aChangedHandler=nullptr) const
Test all of the connectable objects in the schematic for unused connection points.
EE_RTREE & Items()
Get the full RTree, usually for iterating.
Definition sch_screen.h:117
const wxString & GetFileName() const
Definition sch_screen.h:152
void UpdateLocalLibSymbolLinks()
Initialize the LIB_SYMBOL reference for each SCH_SYMBOL found in this schematic with the local projec...
void SetFileName(const wxString &aFileName)
Set the file name for this screen to aFileName.
int GetFileFormatVersionAtLoad() const
Definition sch_screen.h:137
void AssignNewUuid()
Definition sch_screen.h:522
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
void UpdateSheetInstanceData(const std::vector< SCH_SHEET_INSTANCE > &aSheetInstances)
Update all of the sheet instance information using aSheetInstances.
void SetInitialPageNumbers()
Set initial sheet page numbers.
bool AllSheetPageNumbersEmpty() const
Check all of the sheet instance for empty page numbers.
bool IsModified() const
Check the entire hierarchy for any modifications.
void UpdateSymbolInstanceData(const std::vector< SCH_SYMBOL_INSTANCE > &aSymbolInstances)
Update all of the symbol instance information using aSymbolInstances.
void CheckForMissingSymbolInstances(const wxString &aProjectName)
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
void UpdateAllScreenReferences() const
Update all the symbol references for this sheet path.
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition sch_sheet.h:47
void SetFileName(const wxString &aFilename)
Definition sch_sheet.h:347
wxString GetFileName() const
Return the filename corresponding to this sheet.
Definition sch_sheet.h:341
wxString GetName() const
Definition sch_sheet.h:113
void SetName(const wxString &aName)
Definition sch_sheet.h:114
SCH_SCREEN * GetScreen() const
Definition sch_sheet.h:116
bool IsVirtualRootSheet() const
void SaveProjectAs(const wxString &aFullPath, PROJECT *aProject=nullptr)
Set the currently loaded project path and saves it (pointers remain valid).
void SaveProjectCopy(const wxString &aFullPath, PROJECT *aProject=nullptr)
Save a copy of the current project under the given path.
bool SaveProject(const wxString &aFullPath=wxEmptyString, PROJECT *aProject=nullptr)
Save a loaded project.
bool LoadProject(const wxString &aFullPath, bool aSetActive=true)
Load a project or sets up a new project with a specified path.
bool UnloadProject(PROJECT *aProject, bool aSave=true)
Save, unload and unregister the given PROJECT.
The SIMULATOR_FRAME holds the main user-interface for running simulations.
TOOL_MANAGER * m_toolManager
@ SUPERMODEL_RELOAD
For schematics, the entire schematic changed, not just the sheet.
Definition tool_base.h:81
Temporarily disable a window, and then re-enable on destruction.
Definition raii.h:87
static void ResolvePossibleSymlinks(wxFileName &aFilename)
void Flush()
Build the HTML messages page.
bool HasMessage() const override
Returns true if any messages were reported.
@ OUTDATED_SAVE
OUTDATED_SAVE Messages that should be cleared on save.
Definition wx_infobar.h:96
Multi-thread safe progress reporter dialog, intended for use of tasks that parallel reporting back of...
A wrapper for reporting to a wxString object.
Definition reporter.h:191
const wxString & GetMessages() const
Definition reporter.cpp:77
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:580
The common library.
bool AskOverrideLock(wxWindow *aParent, const wxString &aMessage)
Display a dialog indicating the file is already open, with an option to reset the lock.
Definition confirm.cpp:42
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition confirm.cpp:259
void DisplayInfoMessage(wxWindow *aParent, const wxString &aMessage, const wxString &aExtraInfo)
Display an informational message box with aMessage.
Definition confirm.cpp:230
bool HandleUnsavedChanges(wxWindow *aParent, const wxString &aMessage, const std::function< bool()> &aSaveFunction)
Display a dialog with Save, Cancel and Discard Changes buttons.
Definition confirm.cpp:131
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition confirm.cpp:202
void DisplayError(wxWindow *aParent, const wxString &aText)
Display an error or warning message box with aMessage.
Definition confirm.cpp:177
This file is part of the common library.
static bool empty(const wxTextEntryBase *aCtrl)
#define _(s)
bool PrepareSaveAsFiles(SCHEMATIC &aSchematic, SCH_SCREENS &aScreens, const wxFileName &aOldRoot, const wxFileName &aNewRoot, bool aSaveCopy, bool aCopySubsheets, bool aIncludeExternSheets, std::unordered_map< SCH_SCREEN *, wxString > &aFilenameMap, wxString &aErrorMsg)
void Reset() override
@ FRAME_SIMULATOR
Definition frame_type.h:38
static const std::string LegacySchematicFileExtension
static const std::string ProjectFileExtension
static const std::string LegacyProjectFileExtension
static const std::string KiCadSchematicFileExtension
static const std::string LegacySymbolLibFileExtension
static wxString KiCadSchematicFileWildcard()
const wxChar *const traceSchCurrentSheet
Flag to enable debug output of current sheet tracking in the schematic editor.
const wxChar *const traceAutoSave
Flag to enable auto save feature debug tracing.
const wxChar *const tracePathsAndFiles
Flag to enable path and file name debug output.
std::unique_ptr< T > IO_RELEASER
Helper to hold and release an IO_BASE object when exceptions are thrown.
Definition io_mgr.h:33
#define THROW_IO_ERROR(msg)
macro which captures the "call site" values of FILE_, __FUNCTION & LINE
PROJECT & Prj()
Definition kicad.cpp:629
KIID niluuid(0)
#define KICTL_CREATE
caller thinks requested project files may not exist.
#define KICTL_KICAD_ONLY
chosen file is from KiCad according to user
@ LAYER_BUS
Definition layer_ids.h:453
File locking utilities.
void SetShutdownBlockReason(wxWindow *aWindow, const wxString &aReason)
Sets the block reason why the window/application is preventing OS shutdown.
Definition unix/app.cpp:90
bool RegisterApplicationRestart(const wxString &aCommandLine)
Registers the application for restart with the OS with the given command line string to pass as args.
Definition unix/app.cpp:65
PGM_BASE & Pgm()
The global program "get" accessor.
Definition pgm_base.cpp:946
see class PGM_BASE
#define SEXPR_SCHEMATIC_FILE_VERSION
Schematic file version.
Definition of the SCH_SHEET_PATH and SCH_SHEET_LIST classes for Eeschema.
@ GLOBAL_CLEANUP
Definition schematic.h:77
KIWAY Kiway(KFCTL_STANDALONE)
std::vector< FAB_LAYER_COLOR > dummy
MODEL3D_FORMAT_TYPE fileType(const char *aFileName)
bool show_import_issues
Stored value for "show import issues" when importing non-KiCad designs to this application.
Variant of PARSE_ERROR indicating that a syntax or related error was likely caused by a file generate...
Container that describes file type info.
Definition io_base.h:43
std::vector< std::string > m_FileExtensions
Filter used for file pickers if m_IsFile is true.
Definition io_base.h:47
bool m_CanRead
Whether the IO can read this file type.
Definition io_base.h:52
wxString FileFilter() const
Definition io_base.cpp:40
Implement a participant in the KIWAY alchemy.
Definition kiway.h:155
virtual void PreloadLibraries(KIWAY *aKiway)
Definition kiway.h:258
Information about a top-level schematic sheet.
std::string path
wxLogTrace helper definitions.
@ SCH_SHEET_T
Definition typeinfo.h:179
@ SCH_BUS_BUS_ENTRY_T
Definition typeinfo.h:166
wxString formatWildcardExt(const wxString &aWildcard)
Format wildcard extension to support case sensitive file dialogs.
Definition of file extensions used in Kicad.
#define PR_CAN_ABORT