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 (C) 1992-2024 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#include <symbol_library.h>
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>
38#include <lockfile.h>
39#include <pgm_base.h>
40#include <core/profile.h>
42#include <project_rescue.h>
43#include <project_sch.h>
46#include <reporter.h>
47#include <richio.h>
48#include <sch_bus_entry.h>
49#include <sch_commit.h>
50#include <sch_edit_frame.h>
52#include <sch_file_versions.h>
53#include <sch_line.h>
54#include <sch_sheet.h>
55#include <sch_sheet_path.h>
56#include <schematic.h>
58#include <sim/simulator_frame.h>
59#include <tool/actions.h>
60#include <tool/tool_manager.h>
63#include <trace_helpers.h>
65#include <widgets/wx_infobar.h>
68#include <wx/app.h>
69#include <wx/ffile.h>
70#include <wx/filedlg.h>
71#include <wx/log.h>
72#include <wx/richmsgdlg.h>
73#include <wx/stdpaths.h>
74#include <tools/ee_actions.h>
77#include <paths.h>
78#include <wx_filename.h> // For ::ResolvePossibleSymlinks
81
82#include <kiplatform/io.h>
83
84#include "widgets/filedlg_hook_save_project.h"
85
86bool SCH_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, int aCtl )
87{
88 // ensure the splash screen does not obscure any dialog at startup
89 Pgm().HideSplash();
90
91 // implement the pseudo code from KIWAY_PLAYER.h:
92 wxString msg;
93
94 EESCHEMA_SETTINGS* cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
95
96 // This is for python:
97 if( aFileSet.size() != 1 )
98 {
99 msg.Printf( "Eeschema:%s() takes only a single filename.", __WXFUNCTION__ );
100 DisplayError( this, msg );
101 return false;
102 }
103
104 wxString fullFileName( aFileSet[0] );
105 wxFileName wx_filename( fullFileName );
106
107 // We insist on caller sending us an absolute path, if it does not, we say it's a bug.
108 wxASSERT_MSG( wx_filename.IsAbsolute(), wxS( "Path is not absolute!" ) );
109
110 if( !LockFile( fullFileName ) )
111 {
112 msg.Printf( _( "Schematic '%s' is already open by '%s' at '%s'." ), fullFileName,
113 m_file_checker->GetUsername(), m_file_checker->GetHostname() );
114
115 if( !AskOverrideLock( this, msg ) )
116 return false;
117
118 m_file_checker->OverrideLock();
119 }
120
121 if( !AskToSaveChanges() )
122 return false;
123
124#ifdef PROFILE
125 PROF_TIMER openFiles( "OpenProjectFile" );
126#endif
127
128 wxFileName pro = fullFileName;
129 pro.SetExt( FILEEXT::ProjectFileExtension );
130
131 bool is_new = !wxFileName::IsFileReadable( fullFileName );
132
133 // If its a non-existent schematic and caller thinks it exists
134 if( is_new && !( aCtl & KICTL_CREATE ) )
135 {
136 // notify user that fullFileName does not exist, ask if user wants to create it.
137 msg.Printf( _( "Schematic '%s' does not exist. Do you wish to create it?" ),
138 fullFileName );
139
140 if( !IsOK( this, msg ) )
141 return false;
142 }
143
144 wxCommandEvent e( EDA_EVT_SCHEMATIC_CHANGING );
145 ProcessEventLocally( e );
146
147 // unload current project file before loading new
148 {
151 SetScreen( nullptr );
154 }
155
156 SetStatusText( wxEmptyString );
158
159 WX_PROGRESS_REPORTER progressReporter( this, is_new ? _( "Creating Schematic" )
160 : _( "Loading Schematic" ), 1 );
161
162 bool differentProject = pro.GetFullPath() != Prj().GetProjectFullName();
163
164 if( differentProject )
165 {
166 if( !Prj().IsNullProject() )
167 {
170 }
171
172 Schematic().SetProject( nullptr );
173 GetSettingsManager()->UnloadProject( &Prj(), false );
174
175 GetSettingsManager()->LoadProject( pro.GetFullPath() );
176
177 wxFileName legacyPro( pro );
178 legacyPro.SetExt( FILEEXT::LegacyProjectFileExtension );
179
180 // Do not allow saving a project if one doesn't exist. This normally happens if we are
181 // standalone and opening a schematic that has been moved from its project folder.
182 if( !pro.Exists() && !legacyPro.Exists() && !( aCtl & KICTL_CREATE ) )
183 Prj().SetReadOnly();
184
186 }
187
188 SCH_IO_MGR::SCH_FILE_T schFileType = SCH_IO_MGR::GuessPluginTypeFromSchPath( fullFileName, KICTL_KICAD_ONLY );
189
190 if( schFileType == SCH_IO_MGR::SCH_LEGACY )
191 {
192 // Don't reload the symbol libraries if we are just launching Eeschema from KiCad again.
193 // They are already saved in the kiface project object.
194 if( differentProject || !Prj().GetElem( PROJECT::ELEM_SCH_SYMBOL_LIBS ) )
195 {
196 // load the libraries here, not in SCH_SCREEN::Draw() which is a context
197 // that will not tolerate DisplayError() dialog since we're already in an
198 // event handler in there.
199 // And when a schematic file is loaded, we need these libs to initialize
200 // some parameters (links to PART LIB, dangling ends ...)
203 }
204 }
205 else
206 {
207 // No legacy symbol libraries including the cache are loaded with the new file format.
209 }
210
211 // Load the symbol library table, this will be used forever more.
214
215 // Load project settings after schematic has been set up with the project link, since this will
216 // update some of the needed schematic settings such as drawing defaults
218
219 wxFileName rfn( GetCurrentFileName() );
220 rfn.MakeRelativeTo( Prj().GetProjectPath() );
221 LoadWindowState( rfn.GetFullPath() );
222
223 KIPLATFORM::APP::SetShutdownBlockReason( this, _( "Schematic file changes are unsaved" ) );
224
225 if( Kiface().IsSingle() )
226 {
228 }
229
230 if( is_new || schFileType == SCH_IO_MGR::SCH_FILE_T::SCH_FILE_UNKNOWN )
231 {
232 // mark new, unsaved file as modified.
234 GetScreen()->SetFileName( fullFileName );
235
236 if( schFileType == SCH_IO_MGR::SCH_FILE_T::SCH_FILE_UNKNOWN )
237 {
238 msg.Printf( _( "'%s' is not a KiCad schematic file.\nUse File -> Import for "
239 "non-KiCad schematic files." ),
240 fullFileName );
241
242 progressReporter.Hide();
243 DisplayErrorMessage( this, msg );
244 }
245 }
246 else
247 {
248 wxFileName autoSaveFn = fullFileName;
249
250 autoSaveFn.SetName( getAutoSaveFileName() );
251 autoSaveFn.ClearExt();
252
253 if( ( aCtl & KICTL_REVERT ) )
254 {
255 DeleteAutoSaveFile( autoSaveFn );
256 }
257 else
258 {
259 // This will rename the file if there is an autosave and the user wants to recover
260 CheckForAutoSaveFile( autoSaveFn );
261 }
262
263 SetScreen( nullptr );
264
265 IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( schFileType ) );
266
267 pi->SetProgressReporter( &progressReporter );
268
269 bool failedLoad = false;
270
271 try
272 {
273 {
274 wxBusyCursor busy;
275 Schematic().SetRoot( pi->LoadSchematicFile( fullFileName, &Schematic() ) );
276
277 // Make ${SHEETNAME} work on the root sheet until we properly support
278 // naming the root sheet
279 Schematic().Root().SetName( _( "Root" ) );
280 wxLogTrace( tracePathsAndFiles, wxS( "Loaded schematic with root sheet UUID %s" ),
281 Schematic().Root().m_Uuid.AsString() );
282 }
283
284 if( !pi->GetError().IsEmpty() )
285 {
286 DisplayErrorMessage( this, _( "The entire schematic could not be loaded. Errors "
287 "occurred attempting to load hierarchical sheets." ),
288 pi->GetError() );
289 }
290 }
291 catch( const FUTURE_FORMAT_ERROR& ffe )
292 {
293 msg.Printf( _( "Error loading schematic '%s'." ), fullFileName);
294 progressReporter.Hide();
295 DisplayErrorMessage( this, msg, ffe.Problem() );
296
297 failedLoad = true;
298 }
299 catch( const IO_ERROR& ioe )
300 {
301 msg.Printf( _( "Error loading schematic '%s'." ), fullFileName);
302 progressReporter.Hide();
303 DisplayErrorMessage( this, msg, ioe.What() );
304
305 failedLoad = true;
306 }
307 catch( const std::bad_alloc& )
308 {
309 msg.Printf( _( "Memory exhausted loading schematic '%s'." ), fullFileName );
310 progressReporter.Hide();
311 DisplayErrorMessage( this, msg, wxEmptyString );
312
313 failedLoad = true;
314 }
315
316 // This fixes a focus issue after the progress reporter is done on GTK. It shouldn't
317 // cause any issues on macOS and Windows. If it does, it will have to be conditionally
318 // compiled.
319 Raise();
320
321 if( failedLoad )
322 {
323 // Do not leave g_RootSheet == NULL because it is expected to be
324 // a valid sheet. Therefore create a dummy empty root sheet and screen.
327
328 msg.Printf( _( "Failed to load '%s'." ), fullFileName );
329 SetMsgPanel( wxEmptyString, msg );
330
331 return false;
332 }
333
334 // It's possible the schematic parser fixed errors due to bugs so warn the user
335 // that the schematic has been fixed (modified).
337
338 if( sheetList.IsModified() )
339 {
340 DisplayInfoMessage( this,
341 _( "An error was found when loading the schematic that has "
342 "been automatically fixed. Please save the schematic to "
343 "repair the broken file or it may not be usable with other "
344 "versions of KiCad." ) );
345 }
346
347 if( sheetList.AllSheetPageNumbersEmpty() )
348 sheetList.SetInitialPageNumbers();
349
350 UpdateFileHistory( fullFileName );
351
352 SCH_SCREENS schematic( Schematic().Root() );
353
354 // LIB_ID checks and symbol rescue only apply to the legacy file formats.
355 if( schFileType == SCH_IO_MGR::SCH_LEGACY )
356 {
357 // Convert any legacy bus-bus entries to just be bus wires
358 for( SCH_SCREEN* screen = schematic.GetFirst(); screen; screen = schematic.GetNext() )
359 {
360 std::vector<SCH_ITEM*> deleted;
361
362 for( SCH_ITEM* item : screen->Items() )
363 {
364 if( item->Type() == SCH_BUS_BUS_ENTRY_T )
365 {
366 SCH_BUS_BUS_ENTRY* entry = static_cast<SCH_BUS_BUS_ENTRY*>( item );
367 std::unique_ptr<SCH_LINE> wire = std::make_unique<SCH_LINE>();
368
369 wire->SetLayer( LAYER_BUS );
370 wire->SetStartPoint( entry->GetPosition() );
371 wire->SetEndPoint( entry->GetEnd() );
372
373 screen->Append( wire.release() );
374 deleted.push_back( item );
375 }
376 }
377
378 for( SCH_ITEM* item : deleted )
379 screen->Remove( item );
380 }
381
382
383 // Convert old projects over to use symbol library table.
384 if( schematic.HasNoFullyDefinedLibIds() )
385 {
386 DIALOG_SYMBOL_REMAP dlgRemap( this );
387
388 dlgRemap.ShowQuasiModal();
389 }
390 else
391 {
392 // Double check to ensure no legacy library list entries have been
393 // added to the project file symbol library list.
394 wxString paths;
395 wxArrayString libNames;
396
397 SYMBOL_LIBS::GetLibNamesAndPaths( &Prj(), &paths, &libNames );
398
399 if( !libNames.IsEmpty() )
400 {
401 if( eeconfig()->m_Appearance.show_illegal_symbol_lib_dialog )
402 {
403 wxRichMessageDialog invalidLibDlg(
404 this,
405 _( "Illegal entry found in project file symbol library list." ),
406 _( "Project Load Warning" ),
407 wxOK | wxCENTER | wxICON_EXCLAMATION );
408 invalidLibDlg.ShowDetailedText(
409 _( "Symbol libraries defined in the project file symbol library "
410 "list are no longer supported and will be removed.\n\n"
411 "This may cause broken symbol library links under certain "
412 "conditions." ) );
413 invalidLibDlg.ShowCheckBox( _( "Do not show this dialog again." ) );
414 invalidLibDlg.ShowModal();
416 !invalidLibDlg.IsCheckBoxChecked();
417 }
418
419 libNames.Clear();
420 paths.Clear();
421 SYMBOL_LIBS::SetLibNamesAndPaths( &Prj(), paths, libNames );
422 }
423
424 if( !cfg || !cfg->m_RescueNeverShow )
425 {
427 editor->RescueSymbolLibTableProject( false );
428 }
429 }
430
431 // Ensure there is only one legacy library loaded and that it is the cache library.
432 SYMBOL_LIBS* legacyLibs = PROJECT_SCH::SchLibs( &Schematic().Prj() );
433
434 if( legacyLibs->GetLibraryCount() == 0 )
435 {
436 wxString extMsg;
437 wxFileName cacheFn = pro;
438
439 cacheFn.SetName( cacheFn.GetName() + "-cache" );
441
442 msg.Printf( _( "The project symbol library cache file '%s' was not found." ),
443 cacheFn.GetFullName() );
444 extMsg = _( "This can result in a broken schematic under certain conditions. "
445 "If the schematic does not have any missing symbols upon opening, "
446 "save it immediately before making any changes to prevent data "
447 "loss. If there are missing symbols, either manual recovery of "
448 "the schematic or recovery of the symbol cache library file and "
449 "reloading the schematic is required." );
450
451 wxMessageDialog dlgMissingCache( this, msg, _( "Warning" ),
452 wxOK | wxCANCEL | wxICON_EXCLAMATION | wxCENTER );
453 dlgMissingCache.SetExtendedMessage( extMsg );
454 dlgMissingCache.SetOKCancelLabels(
455 wxMessageDialog::ButtonLabel( _( "Load Without Cache File" ) ),
456 wxMessageDialog::ButtonLabel( _( "Abort" ) ) );
457
458 if( dlgMissingCache.ShowModal() == wxID_CANCEL )
459 {
460 Schematic().Reset();
462 return false;
463 }
464 }
465
466 // Update all symbol library links for all sheets.
467 schematic.UpdateSymbolLinks();
468
471 m_infoBar->ShowMessage( _( "This file was created by an older version of KiCad. "
472 "It will be converted to the new format when saved." ),
474
475 // Legacy schematic can have duplicate time stamps so fix that before converting
476 // to the s-expression format.
477 schematic.ReplaceDuplicateTimeStamps();
478
479 for( SCH_SCREEN* screen = schematic.GetFirst(); screen; screen = schematic.GetNext() )
480 screen->FixLegacyPowerSymbolMismatches();
481
482 // Allow the schematic to be saved to new file format without making any edits.
483 OnModify();
484 }
485 else // S-expression schematic.
486 {
488 {
491 m_infoBar->ShowMessage( _( "This file was created by an older version of KiCad. "
492 "It will be converted to the new format when saved." ),
494 }
495
496 for( SCH_SCREEN* screen = schematic.GetFirst(); screen; screen = schematic.GetNext() )
497 screen->UpdateLocalLibSymbolLinks();
498
499 // Restore all of the loaded symbol and sheet instances from the root sheet.
500 if( Schematic().RootScreen()->GetFileFormatVersionAtLoad() < 20221002 )
501 sheetList.UpdateSymbolInstanceData( Schematic().RootScreen()->GetSymbolInstances());
502
503 if( Schematic().RootScreen()->GetFileFormatVersionAtLoad() < 20221110 )
504 sheetList.UpdateSheetInstanceData( Schematic().RootScreen()->GetSheetInstances());
505
506 if( Schematic().RootScreen()->GetFileFormatVersionAtLoad() < 20230221 )
507 for( SCH_SCREEN* screen = schematic.GetFirst(); screen; screen = schematic.GetNext() )
508 screen->FixLegacyPowerSymbolMismatches();
509
510 for( SCH_SCREEN* screen = schematic.GetFirst(); screen; screen = schematic.GetNext() )
511 screen->MigrateSimModels();
512
514 {
515 // Allow the schematic to be saved to new file format without making any edits.
516 OnModify();
517 }
518 }
519
520 // After the schematic is successfully loaded, we load the drawing sheet.
521 // This allows us to use the drawing sheet embedded in the schematic (if any)
522 // instead of the default one.
524
525 schematic.PruneOrphanedSymbolInstances( Prj().GetProjectName(), sheetList );
526 schematic.PruneOrphanedSheetInstances( Prj().GetProjectName(), sheetList );
527
529
530 SetScreen( GetCurrentSheet().LastScreen() );
531
532 // Migrate conflicting bus definitions
533 // TODO(JE) This should only run once based on schematic file version
534 if( Schematic().ConnectionGraph()->GetBusesNeedingMigration().size() > 0 )
535 {
536 DIALOG_MIGRATE_BUSES dlg( this );
537 dlg.ShowQuasiModal();
538 OnModify();
539 }
540
541 SCH_COMMIT dummy( this );
542
544 }
545
546 // Load any exclusions from the project file
548
551
554
555 // Re-create junctions if needed. Eeschema optimizes wires by merging
556 // colinear segments. If a schematic is saved without a valid
557 // cache library or missing installed libraries, this can cause connectivity errors
558 // unless junctions are added.
559 //
560 // TODO: (RFB) This really needs to be put inside the Load() function of the SCH_IO_KICAD_LEGACY
561 // I can't put it right now because of the extra code that is above to convert legacy bus-bus
562 // entries to bus wires
563 if( schFileType == SCH_IO_MGR::SCH_LEGACY )
565
566 SyncView();
568
570
572
573 wxCommandEvent changedEvt( EDA_EVT_SCHEMATIC_CHANGED );
574 ProcessEventLocally( changedEvt );
575
576 for( wxEvtHandler* listener : m_schematicChangeListeners )
577 {
578 wxCHECK2( listener, continue );
579
580 // Use the windows variant when handling event messages in case there is any special
581 // event handler pre and/or post processing specific to windows.
582 wxWindow* win = dynamic_cast<wxWindow*>( listener );
583
584 if( win )
585 win->HandleWindowEvent( e );
586 else
587 listener->SafelyProcessEvent( e );
588 }
589
590 updateTitle();
591 m_toolManager->GetTool<SCH_NAVIGATE_TOOL>()->ResetHistory();
592
593 wxFileName fn = Prj().AbsolutePath( GetScreen()->GetFileName() );
594
595 if( fn.FileExists() && !fn.IsFileWritable() )
596 {
599 m_infoBar->ShowMessage( _( "Schematic is read only." ),
601 }
602
603#ifdef PROFILE
604 openFiles.Show();
605#endif
606 // Ensure all items are redrawn (especially the drawing-sheet items):
607 if( GetCanvas() )
608 GetCanvas()->DisplaySheet( GetCurrentSheet().LastScreen() );
609
610 return true;
611}
612
613
615{
616 SCH_SCREEN* screen = GetScreen();
617
618 wxCHECK( screen, false );
619
620 // open file chooser dialog
621 wxString path = wxPathOnly( Prj().GetProjectFullName() );
622
623 wxFileDialog dlg( this, _( "Insert Schematic" ), path, wxEmptyString,
624 FILEEXT::KiCadSchematicFileWildcard(), wxFD_OPEN | wxFD_FILE_MUST_EXIST );
625
626 if( dlg.ShowModal() == wxID_CANCEL )
627 return false;
628
629 return AddSheetAndUpdateDisplay( dlg.GetPath() );
630}
631
632
633bool SCH_EDIT_FRAME::AddSheetAndUpdateDisplay( const wxString aFullFileName )
634{
635 SCH_COMMIT commit( m_toolManager );
637
638 selectionTool->ClearSelection();
639
640 // Mark all existing items on the screen so we don't select them after appending
641 for( EDA_ITEM* item : GetScreen()->Items() )
642 item->SetFlags( SKIP_STRUCT );
643
644 if( !LoadSheetFromFile( GetCurrentSheet().Last(), &GetCurrentSheet(), aFullFileName ) )
645 return false;
646
649
650 SyncView();
651 OnModify();
652 HardRedraw(); // Full reinit of the current screen and the display.
653 bool selected = false;
654
655 // Select all new items
656 for( EDA_ITEM* item : GetScreen()->Items() )
657 {
658 if( !item->HasFlag( SKIP_STRUCT ) )
659 {
660 commit.Added( item, GetScreen() );
661 selectionTool->AddItemToSel( item, true );
662 selected = true;
663
664 if( item->Type() == SCH_LINE_T )
665 item->SetFlags( STARTPOINT | ENDPOINT );
666 }
667 else
668 item->ClearFlags( SKIP_STRUCT );
669 }
670
671 if( selected )
673
674 // Start moving selection, cancel undoes the insertion
676 commit.Revert();
677 else
678 commit.Push( _( "Import Schematic Sheet Content..." ) );
679
681
682 return true;
683}
684
685
686void SCH_EDIT_FRAME::OnAppendProject( wxCommandEvent& event )
687{
688 if( GetScreen() && GetScreen()->IsModified() )
689 {
690 wxString msg = _( "This operation cannot be undone.\n\n"
691 "Do you want to save the current document before proceeding?" );
692
693 if( IsOK( this, msg ) )
694 SaveProject();
695 }
696
698}
699
700
701void SCH_EDIT_FRAME::OnImportProject( wxCommandEvent& aEvent )
702{
703 if( Schematic().RootScreen() && !Schematic().RootScreen()->Items().empty() )
704 {
705 wxString msg = _( "This operation replaces the contents of the current schematic, "
706 "which will be permanently lost.\n\n"
707 "Do you want to proceed?" );
708
709 if( !IsOK( this, msg ) )
710 return;
711 }
712
713 // Set the project location if none is set or if we are running in standalone mode
714 bool setProject = Prj().GetProjectFullName().IsEmpty() || Kiface().IsSingle();
715 wxString path = wxPathOnly( Prj().GetProjectFullName() );
716
717 wxString fileFiltersStr;
718 wxString allWildcardsStr;
719
720 for( const SCH_IO_MGR::SCH_FILE_T& fileType : SCH_IO_MGR::SCH_FILE_T_vector )
721 {
722 if( fileType == SCH_IO_MGR::SCH_KICAD || fileType == SCH_IO_MGR::SCH_LEGACY )
723 continue; // this is "Import non-KiCad schematic"
724
725 IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( fileType ) );
726
727 if( !pi )
728 continue;
729
730 const IO_BASE::IO_FILE_DESC& desc = pi->GetSchematicFileDesc();
731
732 if( desc.m_FileExtensions.empty() || !desc.m_CanRead )
733 continue;
734
735 if( !fileFiltersStr.IsEmpty() )
736 fileFiltersStr += wxChar( '|' );
737
738 fileFiltersStr += desc.FileFilter();
739
740 for( const std::string& ext : desc.m_FileExtensions )
741 allWildcardsStr << wxS( "*." ) << formatWildcardExt( ext ) << wxS( ";" );
742 }
743
744 fileFiltersStr = _( "All supported formats" ) + wxS( "|" ) + allWildcardsStr + wxS( "|" )
745 + fileFiltersStr;
746
747 wxFileDialog dlg( this, _( "Import Schematic" ), path, wxEmptyString, fileFiltersStr,
748 wxFD_OPEN | wxFD_FILE_MUST_EXIST ); // TODO
749
750 FILEDLG_IMPORT_NON_KICAD importOptions( eeconfig()->m_System.show_import_issues );
751 dlg.SetCustomizeHook( importOptions );
752
753 if( dlg.ShowModal() == wxID_CANCEL )
754 return;
755
757
758 // Don't leave dangling pointers to previously-opened document.
759 m_toolManager->GetTool<EE_SELECTION_TOOL>()->ClearSelection();
762
763 if( setProject )
764 {
765 Schematic().SetProject( nullptr );
766 GetSettingsManager()->UnloadProject( &Prj(), false );
767
768 // Clear view before destroying schematic as repaints depend on schematic being valid
769 SetScreen( nullptr );
770
771 Schematic().Reset();
772
773 wxFileName projectFn( dlg.GetPath() );
774 projectFn.SetExt( FILEEXT::ProjectFileExtension );
775 GetSettingsManager()->LoadProject( projectFn.GetFullPath() );
776
777 Schematic().SetProject( &Prj() );
778 }
779
780 wxFileName fn = dlg.GetPath();
781
782 if( !fn.IsFileReadable() )
783 {
784 wxLogError( _( "Insufficient permissions to read file '%s'." ), fn.GetFullPath() );
785 return;
786 }
787
788 SCH_IO_MGR::SCH_FILE_T pluginType = SCH_IO_MGR::SCH_FILE_T::SCH_FILE_UNKNOWN;
789
790 for( const SCH_IO_MGR::SCH_FILE_T& fileType : SCH_IO_MGR::SCH_FILE_T_vector )
791 {
792 IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( fileType ) );
793
794 if( !pi )
795 continue;
796
797 if( pi->CanReadSchematicFile( fn.GetFullPath() ) )
798 {
799 pluginType = fileType;
800 break;
801 }
802 }
803
804 if( pluginType == SCH_IO_MGR::SCH_FILE_T::SCH_FILE_UNKNOWN )
805 {
806 wxLogError( _( "No loader can read the specified file: '%s'." ), fn.GetFullPath() );
808 SetScreen( Schematic().RootScreen() );
809 return;
810 }
811
812 importFile( dlg.GetPath(), pluginType );
813
815}
816
817
818bool SCH_EDIT_FRAME::saveSchematicFile( SCH_SHEET* aSheet, const wxString& aSavePath )
819{
820 wxString msg;
821 wxFileName schematicFileName;
822 wxFileName oldFileName;
823 bool success;
824
825 SCH_SCREEN* screen = aSheet->GetScreen();
826
827 wxCHECK( screen, false );
828
829 // Cannot save to nowhere
830 wxCHECK( !aSavePath.IsEmpty(), false );
831
832 // Construct the name of the file to be saved
833 schematicFileName = Prj().AbsolutePath( aSavePath );
834 oldFileName = schematicFileName;
835
836 // Write through symlinks, don't replace them
837 WX_FILENAME::ResolvePossibleSymlinks( schematicFileName );
838
839 if( !IsWritable( schematicFileName ) )
840 return false;
841
842 wxFileName projectFile( schematicFileName );
843
844 projectFile.SetExt( FILEEXT::ProjectFileExtension );
845
846 if( projectFile.FileExists() )
847 {
848 // Save various ERC settings, such as violation severities (which may have been edited
849 // via the ERC dialog as well as the Schematic Setup dialog), ERC exclusions, etc.
851 }
852
853 wxString tempFile = wxFileName::CreateTempFileName( wxS( "eeschema" ) );
854
855 // Save
856 wxLogTrace( traceAutoSave, wxS( "Saving file " ) + schematicFileName.GetFullPath() );
857
860
861 SCH_IO_MGR::SCH_FILE_T pluginType = SCH_IO_MGR::GuessPluginTypeFromSchPath(
862 schematicFileName.GetFullPath() );
863
864 if( pluginType == SCH_IO_MGR::SCH_FILE_UNKNOWN )
865 pluginType = SCH_IO_MGR::SCH_KICAD;
866
867 IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( pluginType ) );
868
869 try
870 {
871 pi->SaveSchematicFile( tempFile, aSheet, &Schematic() );
872 success = true;
873 }
874 catch( const IO_ERROR& ioe )
875 {
876 msg.Printf( _( "Error saving schematic file '%s'.\n%s" ),
877 schematicFileName.GetFullPath(),
878 ioe.What() );
879 DisplayError( this, msg );
880
881 msg.Printf( _( "Failed to create temporary file '%s'." ),
882 tempFile );
883 SetMsgPanel( wxEmptyString, msg );
884
885 // In case we started a file but didn't fully write it, clean up
886 wxRemoveFile( tempFile );
887
888 success = false;
889 }
890
891 if( success )
892 {
893 // Preserve the permissions of the current file
894 KIPLATFORM::IO::DuplicatePermissions( schematicFileName.GetFullPath(), tempFile );
895
896 // Replace the original with the temporary file we just wrote
897 success = wxRenameFile( tempFile, schematicFileName.GetFullPath() );
898
899 if( !success )
900 {
901 msg.Printf( _( "Error saving schematic file '%s'.\n"
902 "Failed to rename temporary file '%s'." ),
903 schematicFileName.GetFullPath(),
904 tempFile );
905 DisplayError( this, msg );
906
907 msg.Printf( _( "Failed to rename temporary file '%s'." ),
908 tempFile );
909 SetMsgPanel( wxEmptyString, msg );
910 }
911 }
912
913 if( success )
914 {
915 // Delete auto save file.
916 wxFileName autoSaveFileName = schematicFileName;
917 autoSaveFileName.SetName( FILEEXT::AutoSaveFilePrefix + schematicFileName.GetName() );
918
919 if( autoSaveFileName.FileExists() )
920 {
921 wxLogTrace( traceAutoSave,
922 wxS( "Removing auto save file <" ) + autoSaveFileName.GetFullPath() +
923 wxS( ">" ) );
924
925 wxRemoveFile( autoSaveFileName.GetFullPath() );
926 }
927
928 screen->SetContentModified( false );
929
930 msg.Printf( _( "File '%s' saved." ), screen->GetFileName() );
931 SetStatusText( msg, 0 );
932 }
933 else
934 {
935 DisplayError( this, _( "File write operation failed." ) );
936 }
937
938 return success;
939}
940
941
942bool SCH_EDIT_FRAME::SaveProject( bool aSaveAs )
943{
944 wxString msg;
945 SCH_SCREEN* screen;
946 SCH_SCREENS screens( Schematic().Root() );
947 bool saveCopy = aSaveAs && !Kiface().IsSingle();
948 bool success = true;
949 bool updateFileHistory = false;
950 bool createNewProject = false;
951
952 // I want to see it in the debugger, show me the string! Can't do that with wxFileName.
953 wxString fileName = Prj().AbsolutePath( Schematic().Root().GetFileName() );
954 wxFileName fn = fileName;
955
956 // Path to save each screen to: will be the stored filename by default, but is overwritten by
957 // a Save As Copy operation.
958 std::unordered_map<SCH_SCREEN*, wxString> filenameMap;
959
960 // Handle "Save As" and saving a new project/schematic for the first time in standalone
961 if( Prj().IsNullProject() || aSaveAs )
962 {
963 // Null project should only be possible in standalone mode.
964 wxCHECK( Kiface().IsSingle() || aSaveAs, false );
965
966 wxFileName newFileName;
967 wxFileName savePath( Prj().GetProjectFullName() );
968
969 if( !savePath.IsOk() || !savePath.IsDirWritable() )
970 {
971 savePath = GetMruPath();
972
973 if( !savePath.IsOk() || !savePath.IsDirWritable() )
975 }
976
977 if( savePath.HasExt() )
978 savePath.SetExt( FILEEXT::KiCadSchematicFileExtension );
979 else
980 savePath.SetName( wxEmptyString );
981
982 wxFileDialog dlg( this, _( "Schematic Files" ), savePath.GetPath(), savePath.GetFullName(),
984 wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
985
986 FILEDLG_HOOK_SAVE_PROJECT newProjectHook;
987
988 // Add a "Create a project" checkbox in standalone mode and one isn't loaded
989 if( Kiface().IsSingle() || aSaveAs )
990 {
991 dlg.SetCustomizeHook( newProjectHook );
992 }
993
994 if( dlg.ShowModal() == wxID_CANCEL )
995 return false;
996
997 newFileName = EnsureFileExtension( dlg.GetPath(), FILEEXT::KiCadSchematicFileExtension );
998
999 if( ( !newFileName.DirExists() && !newFileName.Mkdir() ) ||
1000 !newFileName.IsDirWritable() )
1001 {
1002 msg.Printf( _( "Folder '%s' could not be created.\n\n"
1003 "Make sure you have write permissions and try again." ),
1004 newFileName.GetPath() );
1005
1006 wxMessageDialog dlgBadPath( this, msg, _( "Error" ),
1007 wxOK | wxICON_EXCLAMATION | wxCENTER );
1008
1009 dlgBadPath.ShowModal();
1010 return false;
1011 }
1012
1013 if( newProjectHook.IsAttachedToDialog() )
1014 createNewProject = newProjectHook.GetCreateNewProject();
1015
1016 if( !saveCopy )
1017 {
1018 Schematic().Root().SetFileName( newFileName.GetFullName() );
1019 Schematic().RootScreen()->SetFileName( newFileName.GetFullPath() );
1020 updateFileHistory = true;
1021 }
1022 else
1023 {
1024 filenameMap[Schematic().RootScreen()] = newFileName.GetFullPath();
1025 }
1026
1027 // Set the base path to all new sheets.
1028 for( size_t i = 0; i < screens.GetCount(); i++ )
1029 {
1030 screen = screens.GetScreen( i );
1031
1032 wxCHECK2( screen, continue );
1033
1034 // The root screen file name has already been set.
1035 if( screen == Schematic().RootScreen() )
1036 continue;
1037
1038 wxFileName tmp = screen->GetFileName();
1039
1040 // Assume existing sheet files are being reused and do not save them to the new
1041 // path. Maybe in the future, add a user option to copy schematic files to the
1042 // new project path.
1043 if( tmp.FileExists() )
1044 continue;
1045
1046 if( tmp.GetPath().IsEmpty() )
1047 {
1048 tmp.SetPath( newFileName.GetPath() );
1049 }
1050 else if( tmp.GetPath() == fn.GetPath() )
1051 {
1052 tmp.SetPath( newFileName.GetPath() );
1053 }
1054 else if( tmp.GetPath().StartsWith( fn.GetPath() ) )
1055 {
1056 // NOTE: this hasn't been tested because the sheet properties dialog no longer
1057 // allows adding a path specifier in the file name field.
1058 wxString newPath = newFileName.GetPath();
1059 newPath += tmp.GetPath().Right( fn.GetPath().Length() );
1060 tmp.SetPath( newPath );
1061 }
1062
1063 wxLogTrace( tracePathsAndFiles,
1064 wxS( "Moving schematic from '%s' to '%s'." ),
1065 screen->GetFileName(),
1066 tmp.GetFullPath() );
1067
1068 if( !tmp.DirExists() && !tmp.Mkdir() )
1069 {
1070 msg.Printf( _( "Folder '%s' could not be created.\n\n"
1071 "Make sure you have write permissions and try again." ),
1072 newFileName.GetPath() );
1073
1074 wxMessageDialog dlgBadFilePath( this, msg, _( "Error" ),
1075 wxOK | wxICON_EXCLAMATION | wxCENTER );
1076
1077 dlgBadFilePath.ShowModal();
1078 return false;
1079 }
1080
1081 if( saveCopy )
1082 filenameMap[screen] = tmp.GetFullPath();
1083 else
1084 screen->SetFileName( tmp.GetFullPath() );
1085 }
1086
1087 // Attempt to make sheet file name paths relative to the new root schematic path.
1088 for( SCH_SHEET_PATH& sheet : Schematic().BuildUnorderedSheetList() )
1089 {
1090 if( !sheet.Last()->IsRootSheet() )
1091 sheet.MakeFilePathRelativeToParentSheet();
1092 }
1093 }
1094 else if( !fn.FileExists() )
1095 {
1096 // File doesn't exist yet; true if we just imported something
1097 updateFileHistory = true;
1098 }
1099 else if( !IsContentModified() )
1100 {
1101 return true;
1102 }
1103
1104 if( filenameMap.empty() || !saveCopy )
1105 {
1106 for( size_t i = 0; i < screens.GetCount(); i++ )
1107 filenameMap[screens.GetScreen( i )] = screens.GetScreen( i )->GetFileName();
1108 }
1109
1110 // Warn user on potential file overwrite. This can happen on shared sheets.
1111 wxArrayString overwrittenFiles;
1112 wxArrayString lockedFiles;
1113
1114 for( size_t i = 0; i < screens.GetCount(); i++ )
1115 {
1116 screen = screens.GetScreen( i );
1117
1118 wxCHECK2( screen, continue );
1119
1120 // Convert legacy schematics file name extensions for the new format.
1121 wxFileName tmpFn = filenameMap[screen];
1122
1123 if( !tmpFn.IsOk() )
1124 continue;
1125
1126 if( tmpFn.FileExists() && !tmpFn.IsFileWritable() )
1127 lockedFiles.Add( tmpFn.GetFullPath() );
1128
1129 if( tmpFn.GetExt() == FILEEXT::KiCadSchematicFileExtension )
1130 continue;
1131
1133
1134 if( tmpFn.FileExists() )
1135 overwrittenFiles.Add( tmpFn.GetFullPath() );
1136 }
1137
1138 if( !lockedFiles.IsEmpty() )
1139 {
1140 for( const wxString& lockedFile : lockedFiles )
1141 {
1142 if( msg.IsEmpty() )
1143 msg = lockedFile;
1144 else
1145 msg += "\n" + lockedFile;
1146 }
1147
1148 wxRichMessageDialog dlg( this, wxString::Format( _( "Failed to save %s." ),
1149 Schematic().Root().GetFileName() ),
1150 _( "Locked File Warning" ),
1151 wxOK | wxICON_WARNING | wxCENTER );
1152 dlg.SetExtendedMessage( _( "You do not have write permissions to:\n\n" ) + msg );
1153
1154 dlg.ShowModal();
1155 return false;
1156 }
1157
1158 if( !overwrittenFiles.IsEmpty() )
1159 {
1160 for( const wxString& overwrittenFile : overwrittenFiles )
1161 {
1162 if( msg.IsEmpty() )
1163 msg = overwrittenFile;
1164 else
1165 msg += "\n" + overwrittenFile;
1166 }
1167
1168 wxRichMessageDialog dlg( this, _( "Saving will overwrite existing files." ),
1169 _( "Save Warning" ),
1170 wxOK | wxCANCEL | wxCANCEL_DEFAULT | wxCENTER |
1171 wxICON_EXCLAMATION );
1172 dlg.ShowDetailedText( _( "The following files will be overwritten:\n\n" ) + msg );
1173 dlg.SetOKCancelLabels( wxMessageDialog::ButtonLabel( _( "Overwrite Files" ) ),
1174 wxMessageDialog::ButtonLabel( _( "Abort Project Save" ) ) );
1175
1176 if( dlg.ShowModal() == wxID_CANCEL )
1177 return false;
1178 }
1179
1180 screens.BuildClientSheetPathList();
1181
1182 for( size_t i = 0; i < screens.GetCount(); i++ )
1183 {
1184 screen = screens.GetScreen( i );
1185
1186 wxCHECK2( screen, continue );
1187
1188 // Convert legacy schematics file name extensions for the new format.
1189 wxFileName tmpFn = filenameMap[screen];
1190
1191 if( tmpFn.IsOk() && tmpFn.GetExt() != FILEEXT::KiCadSchematicFileExtension )
1192 {
1193 updateFileHistory = true;
1195
1196 for( EDA_ITEM* item : screen->Items().OfType( SCH_SHEET_T ) )
1197 {
1198 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
1199 wxFileName sheetFileName = sheet->GetFileName();
1200
1201 if( !sheetFileName.IsOk()
1202 || sheetFileName.GetExt() == FILEEXT::KiCadSchematicFileExtension )
1203 continue;
1204
1205 sheetFileName.SetExt( FILEEXT::KiCadSchematicFileExtension );
1206 sheet->SetFileName( sheetFileName.GetFullPath() );
1207 UpdateItem( sheet );
1208 }
1209
1210 filenameMap[screen] = tmpFn.GetFullPath();
1211
1212 if( !saveCopy )
1213 screen->SetFileName( tmpFn.GetFullPath() );
1214 }
1215
1216 // Do not save sheet symbols with no valid filename set
1217 if( !tmpFn.IsOk() )
1218 continue;
1219
1220 std::vector<SCH_SHEET_PATH>& sheets = screen->GetClientSheetPaths();
1221
1222 if( sheets.size() == 1 )
1223 screen->SetVirtualPageNumber( 1 );
1224 else
1225 screen->SetVirtualPageNumber( 0 ); // multiple uses; no way to store the real sheet #
1226
1227 // This is a new schematic file so make sure it has a unique ID.
1228 if( !saveCopy && tmpFn.GetFullPath() != screen->GetFileName() )
1229 screen->AssignNewUuid();
1230
1231 success &= saveSchematicFile( screens.GetSheet( i ), tmpFn.GetFullPath() );
1232 }
1233
1234 if( success )
1235 m_autoSaveRequired = false;
1236
1237 // One or more of the modified sheets did not save correctly so update the auto save file.
1238 if( !aSaveAs && !success )
1239 success &= updateAutoSaveFile();
1240
1241 if( aSaveAs && success )
1242 LockFile( Schematic().RootScreen()->GetFileName() );
1243
1244 if( updateFileHistory )
1245 UpdateFileHistory( Schematic().RootScreen()->GetFileName() );
1246
1247 // Save the sheet name map to the project file
1248 std::vector<FILE_INFO_PAIR>& sheets = Prj().GetProjectFile().GetSheets();
1249 sheets.clear();
1250
1251 for( SCH_SHEET_PATH& sheetPath : Schematic().BuildUnorderedSheetList() )
1252 {
1253 SCH_SHEET* sheet = sheetPath.Last();
1254
1255 wxCHECK2( sheet, continue );
1256
1257 // Use the schematic UUID for the root sheet.
1258 if( sheet->IsRootSheet() )
1259 {
1260 screen = sheet->GetScreen();
1261
1262 wxCHECK2( screen, continue );
1263
1264 sheets.emplace_back( std::make_pair( screen->GetUuid(), sheet->GetName() ) );
1265 }
1266 else
1267 {
1268 sheets.emplace_back( std::make_pair( sheet->m_Uuid, sheet->GetName() ) );
1269 }
1270 }
1271
1272 wxASSERT( filenameMap.count( Schematic().RootScreen() ) );
1273 wxFileName projectPath( filenameMap.at( Schematic().RootScreen() ) );
1274 projectPath.SetExt( FILEEXT::ProjectFileExtension );
1275
1276 if( Prj().IsNullProject() || ( aSaveAs && !saveCopy ) )
1277 {
1278 Prj().SetReadOnly( !createNewProject );
1279 GetSettingsManager()->SaveProjectAs( projectPath.GetFullPath() );
1280 }
1281 else if( saveCopy && createNewProject )
1282 {
1283 GetSettingsManager()->SaveProjectCopy( projectPath.GetFullPath() );
1284 }
1285 else
1286 {
1289 }
1290
1291 if( !Kiface().IsSingle() )
1292 {
1293 WX_STRING_REPORTER backupReporter( &msg );
1294
1295 if( !GetSettingsManager()->TriggerBackupIfNeeded( backupReporter ) )
1296 SetStatusText( msg, 0 );
1297 }
1298
1299 updateTitle();
1300
1302 m_infoBar->Dismiss();
1303
1304 return success;
1305}
1306
1307
1309{
1310 wxFileName tmpFileName = Schematic().Root().GetFileName();
1311 wxFileName fn = tmpFileName;
1312 wxFileName tmp;
1313 SCH_SCREENS screens( Schematic().Root() );
1314
1315 // Don't run autosave if content has not been modified
1316 if( !IsContentModified() )
1317 return true;
1318
1319 bool autoSaveOk = true;
1320
1321 if( fn.GetPath().IsEmpty() )
1322 tmp.AssignDir( Prj().GetProjectPath() );
1323 else
1324 tmp.AssignDir( fn.GetPath() );
1325
1326 if( !tmp.IsOk() )
1327 return false;
1328
1329 if( !IsWritable( tmp ) )
1330 return false;
1331
1332 wxString title = GetTitle(); // Save frame title, that can be modified by the save process
1333
1334 for( size_t i = 0; i < screens.GetCount(); i++ )
1335 {
1336 // Only create auto save files for the schematics that have been modified.
1337 if( !screens.GetScreen( i )->IsContentModified() )
1338 continue;
1339
1340 tmpFileName = fn = screens.GetScreen( i )->GetFileName();
1341
1342 // Auto save file name is the normal file name prefixed with GetAutoSavePrefix().
1343 fn.SetName( FILEEXT::AutoSaveFilePrefix + fn.GetName() );
1344
1345 if( saveSchematicFile( screens.GetSheet( i ), fn.GetFullPath() ) )
1346 {
1347 // This was only an auto-save, not a real save. Reset the modified flag.
1348 screens.GetScreen( i )->SetContentModified();
1349 }
1350 else
1351 {
1352 autoSaveOk = false;
1353 }
1354 }
1355
1356 if( autoSaveOk && updateAutoSaveFile() )
1357 {
1358 m_autoSaveRequired = false;
1359 m_autoSavePending = false;
1360
1361 if( !Kiface().IsSingle()
1362 && GetSettingsManager()->GetCommonSettings()->m_Backup.backup_on_autosave )
1363 {
1365 }
1366 }
1367
1368 SetTitle( title );
1369
1370 return autoSaveOk;
1371}
1372
1373
1374bool SCH_EDIT_FRAME::importFile( const wxString& aFileName, int aFileType,
1375 const STRING_UTF8_MAP* aProperties )
1376{
1377 wxFileName filename( aFileName );
1378 wxFileName newfilename;
1379 SCH_IO_MGR::SCH_FILE_T fileType = (SCH_IO_MGR::SCH_FILE_T) aFileType;
1380
1381 wxCommandEvent changingEvt( EDA_EVT_SCHEMATIC_CHANGING );
1382 ProcessEventLocally( changingEvt );
1383
1384 switch( fileType )
1385 {
1386 case SCH_IO_MGR::SCH_ALTIUM:
1387 case SCH_IO_MGR::SCH_CADSTAR_ARCHIVE:
1388 case SCH_IO_MGR::SCH_EAGLE:
1389 case SCH_IO_MGR::SCH_LTSPICE:
1390 case SCH_IO_MGR::SCH_EASYEDA:
1391 case SCH_IO_MGR::SCH_EASYEDAPRO:
1392 {
1393 // We insist on caller sending us an absolute path, if it does not, we say it's a bug.
1394 wxCHECK_MSG( filename.IsAbsolute(), false,
1395 wxS( "Import schematic: path is not absolute!" ) );
1396
1397 try
1398 {
1399 IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( fileType ) );
1400 DIALOG_HTML_REPORTER errorReporter( this );
1401 WX_PROGRESS_REPORTER progressReporter( this, _( "Importing Schematic" ), 1 );
1402
1403 if( PROJECT_CHOOSER_PLUGIN* c_pi = dynamic_cast<PROJECT_CHOOSER_PLUGIN*>( pi.get() ) )
1404 {
1405 c_pi->RegisterCallback( std::bind( DIALOG_IMPORT_CHOOSE_PROJECT::RunModal,
1406 this, std::placeholders::_1 ) );
1407 }
1408
1409 if( eeconfig()->m_System.show_import_issues )
1410 pi->SetReporter( errorReporter.m_Reporter );
1411 else
1412 pi->SetReporter( &NULL_REPORTER::GetInstance() );
1413
1414 pi->SetProgressReporter( &progressReporter );
1415
1416 SCH_SHEET* loadedSheet = pi->LoadSchematicFile( aFileName, &Schematic(), nullptr,
1417 aProperties );
1418
1419 if( loadedSheet )
1420 {
1421 Schematic().SetRoot( loadedSheet );
1422
1423 if( errorReporter.m_Reporter->HasMessage() )
1424 {
1425 errorReporter.m_Reporter->Flush(); // Build HTML messages
1426 errorReporter.ShowModal();
1427 }
1428
1429 // Non-KiCad schematics do not use a drawing-sheet (or if they do, it works
1430 // differently to KiCad), so set it to an empty one.
1432 drawingSheet.SetEmptyLayout();
1433 BASE_SCREEN::m_DrawingSheetFileName = "empty.kicad_wks";
1434
1435 newfilename.SetPath( Prj().GetProjectPath() );
1436 newfilename.SetName( Prj().GetProjectName() );
1437 newfilename.SetExt( FILEEXT::KiCadSchematicFileExtension );
1438
1439 SetScreen( GetCurrentSheet().LastScreen() );
1440
1441 Schematic().Root().SetFileName( newfilename.GetFullName() );
1442 GetScreen()->SetFileName( newfilename.GetFullPath() );
1444
1446
1447 // Only perform the dangling end test on root sheet.
1449 }
1450 else
1451 {
1452 CreateScreens();
1453 }
1454 }
1455 catch( const IO_ERROR& ioe )
1456 {
1457 // Do not leave g_RootSheet == NULL because it is expected to be
1458 // a valid sheet. Therefore create a dummy empty root sheet and screen.
1459 CreateScreens();
1461
1462 wxString msg = wxString::Format( _( "Error loading schematic '%s'." ), aFileName );
1463 DisplayErrorMessage( this, msg, ioe.What() );
1464
1465 msg.Printf( _( "Failed to load '%s'." ), aFileName );
1466 SetMsgPanel( wxEmptyString, msg );
1467 }
1468 catch( const std::exception& exc )
1469 {
1470 CreateScreens();
1472
1473 wxString msg = wxString::Format( _( "Unhandled exception occurred loading schematic "
1474 "'%s'." ), aFileName );
1475 DisplayErrorMessage( this, msg, exc.what() );
1476
1477 msg.Printf( _( "Failed to load '%s'." ), aFileName );
1478 SetMsgPanel( wxEmptyString, msg );
1479 }
1480
1483
1486 SyncView();
1487
1489
1490 wxCommandEvent e( EDA_EVT_SCHEMATIC_CHANGED );
1491 ProcessEventLocally( e );
1492
1493 for( wxEvtHandler* listener : m_schematicChangeListeners )
1494 {
1495 wxCHECK2( listener, continue );
1496
1497 // Use the windows variant when handling event messages in case there is any
1498 // special event handler pre and/or post processing specific to windows.
1499 wxWindow* win = dynamic_cast<wxWindow*>( listener );
1500
1501 if( win )
1502 win->HandleWindowEvent( e );
1503 else
1504 listener->SafelyProcessEvent( e );
1505 }
1506
1507 updateTitle();
1508 break;
1509 }
1510
1511 default:
1512 break;
1513 }
1514
1515 return true;
1516}
1517
1518
1520{
1521 SCH_SCREENS screenList( Schematic().Root() );
1522
1523 // Save any currently open and modified project files.
1524 for( SCH_SCREEN* screen = screenList.GetFirst(); screen; screen = screenList.GetNext() )
1525 {
1526 SIMULATOR_FRAME* simFrame = (SIMULATOR_FRAME*) Kiway().Player( FRAME_SIMULATOR, false );
1527
1528 // Simulator must be closed before loading another schematic, otherwise it may crash.
1529 // If there are any changes in the simulator the user will be prompted to save them.
1530 if( simFrame && !simFrame->Close() )
1531 return false;
1532
1533 if( screen->IsContentModified() )
1534 {
1535 if( !HandleUnsavedChanges( this, _( "The current schematic has been modified. "
1536 "Save changes?" ),
1537 [&]() -> bool
1538 {
1539 return SaveProject();
1540 } ) )
1541 {
1542 return false;
1543 }
1544 }
1545 }
1546
1547 return true;
1548}
1549
1550
1552{
1553 wxFileName tmpFn = Prj().GetProjectFullName();
1554 wxFileName autoSaveFileName( tmpFn.GetPath(), getAutoSaveFileName() );
1555
1556 wxLogTrace( traceAutoSave, "Creating auto save file %s", autoSaveFileName.GetFullPath() );
1557
1558 wxCHECK( autoSaveFileName.IsDirWritable(), false );
1559
1560 wxFileName fn;
1561 SCH_SCREENS screens( Schematic().Root() );
1562 std::vector< wxString > autoSavedFiles;
1563
1564 for( size_t i = 0; i < screens.GetCount(); i++ )
1565 {
1566 // Only create auto save files for the schematics that have been modified.
1567 if( !screens.GetScreen( i )->IsContentModified() )
1568 continue;
1569
1570 fn = screens.GetScreen( i )->GetFileName();
1571
1572 // Auto save file name is the normal file name prefixed with GetAutoSavePrefix().
1573 fn.SetName( FILEEXT::AutoSaveFilePrefix + fn.GetName() );
1574 autoSavedFiles.emplace_back( fn.GetFullPath() );
1575 }
1576
1577 wxTextFile autoSaveFile( autoSaveFileName.GetFullPath() );
1578
1579 if( autoSaveFileName.FileExists() && !wxRemoveFile( autoSaveFileName.GetFullPath() ) )
1580 {
1581 wxLogTrace( traceAutoSave, "Error removing auto save file %s",
1582 autoSaveFileName.GetFullPath() );
1583
1584 return false;
1585 }
1586
1587 // No modified sheet files to save.
1588 if( autoSavedFiles.empty() )
1589 return true;
1590
1591 if( !autoSaveFile.Create() )
1592 return false;
1593
1594 for( const wxString& fileName : autoSavedFiles )
1595 {
1596 wxLogTrace( traceAutoSave, "Adding auto save file %s to %s",
1597 fileName, autoSaveFileName.GetName() );
1598 autoSaveFile.AddLine( fileName );
1599 }
1600
1601 if( !autoSaveFile.Write() )
1602 return false;
1603
1604 wxLogTrace( traceAutoSave, "Auto save file '%s' written", autoSaveFileName.GetFullName() );
1605
1606 return true;
1607}
1608
1609
1610void removeFile( const wxString& aFilename, wxArrayString& aUnremoved )
1611{
1612 wxLogTrace( traceAutoSave, wxS( "Removing auto save file " ) + aFilename );
1613
1614 if( wxFileExists( aFilename ) && !wxRemoveFile( aFilename ) )
1615 aUnremoved.Add( aFilename );
1616};
1617
1618
1619void SCH_EDIT_FRAME::CheckForAutoSaveFile( const wxFileName& aFileName )
1620{
1621 if( !Pgm().IsGUI() )
1622 return;
1623
1624 wxCHECK_RET( aFileName.IsOk(), wxS( "Invalid file name!" ) );
1625
1626 wxLogTrace( traceAutoSave,
1627 wxS( "Checking for auto save file " ) + aFileName.GetFullPath() );
1628
1629 if( !aFileName.FileExists() )
1630 return;
1631
1632 wxString msg = _(
1633 "Well this is potentially embarrassing!\n"
1634 "It appears that the last time you were editing one or more of the schematic files\n"
1635 "were not saved properly. Do you wish to restore the last saved edits you made?" );
1636
1637 int response = wxMessageBox( msg, Pgm().App().GetAppDisplayName(), wxYES_NO | wxICON_QUESTION,
1638 this );
1639
1640 wxTextFile fileList( aFileName.GetFullPath() );
1641
1642 if( !fileList.Open() )
1643 {
1644 msg.Printf( _( "The file '%s' could not be opened.\n"
1645 "Manual recovery of automatically saved files is required." ),
1646 aFileName.GetFullPath() );
1647
1648 wxMessageBox( msg, Pgm().App().GetAppDisplayName(), wxOK | wxICON_EXCLAMATION, this );
1649 return;
1650 }
1651
1652 if( response == wxYES )
1653 {
1654 wxArrayString unrecoveredFiles;
1655
1656 for( wxString fn = fileList.GetFirstLine(); !fileList.Eof(); fn = fileList.GetNextLine() )
1657 {
1658 wxFileName recoveredFn = fn;
1659 wxString tmp = recoveredFn.GetName();
1660
1661 // Strip "_autosave-" prefix from the auto save file name.
1662 tmp.Replace( FILEEXT::AutoSaveFilePrefix, wxS( "" ), false );
1663 recoveredFn.SetName( tmp );
1664
1665 wxFileName backupFn = recoveredFn;
1666
1667 backupFn.SetExt( backupFn.GetExt() + FILEEXT::BackupFileSuffix );
1668
1669 wxLogTrace( traceAutoSave, wxS( "Recovering auto save file:\n"
1670 " Original file: '%s'\n"
1671 " Backup file: '%s'\n"
1672 " Auto save file: '%s'" ),
1673 recoveredFn.GetFullPath(), backupFn.GetFullPath(), fn );
1674
1675 if( !wxFileExists( fn ) )
1676 {
1677 unrecoveredFiles.Add( recoveredFn.GetFullPath() );
1678 }
1679 // Attempt to back up the last schematic file before overwriting it with the auto
1680 // save file.
1681 else if( recoveredFn.Exists()
1682 && !wxCopyFile( recoveredFn.GetFullPath(), backupFn.GetFullPath() ) )
1683 {
1684 unrecoveredFiles.Add( recoveredFn.GetFullPath() );
1685 }
1686 // Attempt to replace last saved file with auto save file
1687 else if( !wxRenameFile( fn, recoveredFn.GetFullPath() ) )
1688 {
1689 unrecoveredFiles.Add( recoveredFn.GetFullPath() );
1690 }
1691 }
1692
1693 if( !unrecoveredFiles.IsEmpty() )
1694 {
1695 msg = _( "The following automatically saved file(s) could not be restored\n" );
1696
1697 for( size_t i = 0; i < unrecoveredFiles.GetCount(); i++ )
1698 msg += unrecoveredFiles[i] + wxS( "\n" );
1699
1700 msg += _( "Manual recovery will be required to restore the file(s) above." );
1701 wxMessageBox( msg, Pgm().App().GetAppDisplayName(), wxOK | wxICON_EXCLAMATION,
1702 this );
1703 }
1704
1705 wxArrayString unremovedFiles;
1706 removeFile( aFileName.GetFullPath(), unremovedFiles );
1707
1708 if( !unremovedFiles.IsEmpty() )
1709 {
1710 msg.Printf( _( "The autosave file '%s' could not be removed.\n"
1711 "Manual removal will be required." ),
1712 unremovedFiles[0] );
1713
1714 wxMessageBox( msg, Pgm().App().GetAppDisplayName(), wxOK | wxICON_EXCLAMATION, this );
1715 }
1716 }
1717 else
1718 {
1719 DeleteAutoSaveFile( aFileName );
1720 }
1721}
1722
1723
1724void SCH_EDIT_FRAME::DeleteAutoSaveFile( const wxFileName& aFileName )
1725{
1726 if( !Pgm().IsGUI() )
1727 return;
1728
1729 wxCHECK_RET( aFileName.IsOk(), wxS( "Invalid file name!" ) );
1730
1731 if( !aFileName.FileExists() )
1732 return;
1733
1734 wxTextFile fileList( aFileName.GetFullPath() );
1735 wxArrayString unremovedFiles;
1736
1737 for( wxString fn = fileList.GetFirstLine(); !fileList.Eof(); fn = fileList.GetNextLine() )
1738 removeFile( fn, unremovedFiles );
1739
1740 removeFile( aFileName.GetFullPath(), unremovedFiles );
1741
1742 if( !unremovedFiles.IsEmpty() )
1743 {
1744 wxString msg = _( "The following automatically saved file(s) could not be removed\n" );
1745
1746 for( size_t i = 0; i < unremovedFiles.GetCount(); i++ )
1747 msg += unremovedFiles[i] + wxS( "\n" );
1748
1749 msg += _( "Manual removal will be required for the file(s) above." );
1750 wxMessageBox( msg, Pgm().App().GetAppDisplayName(), wxOK | wxICON_EXCLAMATION, this );
1751 }
1752}
1753
1754
1756{
1757 static wxString autoSaveFileName( wxS( "#auto_saved_files#" ) );
1758
1759 return autoSaveFileName;
1760}
KIFACE_BASE & Kiface()
Global KIFACE_BASE "get" accessor.
static TOOL_ACTION zoomFitScreen
Definition: actions.h:126
bool IsContentModified() const
Definition: base_screen.h:60
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
COMMIT & Added(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Remove a new item from the model.
Definition: commit.h:86
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 ShowQuasiModal()
Handle the graphic items list to draw/plot the frame and title block.
Definition: ds_data_model.h:39
static DS_DATA_MODEL & GetTheInstance()
static function: returns 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
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)
Checks 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:89
const KIID m_Uuid
Definition: eda_item.h:489
static TOOL_ACTION move
Definition: ee_actions.h:121
EE_TYPE OfType(KICAD_T aType) const
Definition: sch_rtree.h:238
int ClearSelection(const TOOL_EVENT &aEvent)
Select all visible items in sheet.
static const TOOL_EVENT SelectedEvent
Definition: actions.h:270
bool GetCreateNewProject() 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.
Definition: ki_exception.h:77
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:30
virtual const wxString Problem() const
what was the problem?
Definition: exceptions.cpp:46
APP_SETTINGS_BASE * KifaceSettings() const
Definition: kiface_base.h:95
bool IsSingle() const
Is this KIFACE running under single_top?
Definition: kiface_base.h:107
virtual KIWAY_PLAYER * Player(FRAME_T aFrameType, bool doCreate=true, wxTopLevelWindow *aParent=nullptr)
Return the KIWAY_PLAYER* given a FRAME_T.
Definition: kiway.cpp:406
static REPORTER & GetInstance()
Definition: reporter.cpp:128
static wxString GetDefaultUserProjectsPath()
Gets the default path we point users to create projects.
Definition: paths.cpp:129
void HideSplash()
Definition: pgm_base.cpp:445
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
Plugin class for import plugins that support choosing a project.
std::vector< FILE_INFO_PAIR > & GetSheets()
Definition: project_file.h:91
static SYMBOL_LIB_TABLE * SchSymbolLibTable(PROJECT *aProject)
Accessor for project symbol library table.
static SYMBOL_LIBS * SchLibs(PROJECT *aProject)
Definition: project_sch.cpp:90
virtual void SetReadOnly(bool aReadOnly=true)
Definition: project.h:144
virtual const wxString GetProjectFullName() const
Return the full path and name of the project.
Definition: project.cpp:129
virtual PROJECT_FILE & GetProjectFile() const
Definition: project.h:166
virtual void SetElem(ELEM_T aIndex, _ELEM *aElem)
Definition: project.cpp:309
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:320
@ ELEM_SYMBOL_LIB_TABLE
Definition: project.h:228
@ ELEM_SCH_SYMBOL_LIBS
Definition: project.h:225
void Reset()
Initialize this schematic to a blank one, unloading anything existing.
Definition: schematic.cpp:138
void ResolveERCExclusionsPostUpdate()
Update markers to match recorded exclusions.
Definition: schematic.cpp:837
CONNECTION_GRAPH * ConnectionGraph() const override
Definition: schematic.h:154
void FixupJunctions()
Add junctions to this schematic where required.
Definition: schematic.cpp:734
void SetRoot(SCH_SHEET *aRootSheet)
Initialize the schematic with a new root sheet.
Definition: schematic.cpp:194
void SetProject(PROJECT *aPrj)
Definition: schematic.cpp:164
SCH_SCREEN * RootScreen() const
Helper to retrieve the screen of the root sheet.
Definition: schematic.cpp:207
SCH_SHEET & Root() const
Definition: schematic.h:113
SCH_SHEET_LIST BuildSheetListSortedByPageNumbers() const override
Definition: schematic.h:96
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
virtual void Push(const wxString &aMessage=wxT("A commit"), int aCommitFlags=0) override
Revert the commit by restoring the modified items state.
Definition: sch_commit.cpp:406
virtual void Revert() override
Definition: sch_commit.cpp:484
void DisplaySheet(SCH_SCREEN *aScreen)
Handle actions specific to the schematic editor.
bool LoadSheetFromFile(SCH_SHEET *aSheet, SCH_SHEET_PATH *aCurrentSheet, const wxString &aFileName)
Load a the KiCad schematic file aFileName into the sheet aSheet.
Definition: sheet.cpp:166
bool IsContentModified() const override
Get if the current schematic has been modified but not saved.
const wxString & getAutoSaveFileName() const
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.
bool doAutoSave() override
Save the schematic files that have been modified and not yet saved.
bool importFile(const wxString &aFileName, int aFileType, const STRING_UTF8_MAP *aProperties=nullptr)
Load the given filename but sets the path to the current project path.
void UpdateHierarchyNavigator(bool aRefreshNetNavigator=true)
Update the hierarchy navigation tree and history.
std::vector< wxEvtHandler * > m_schematicChangeListeners
void HardRedraw() override
Rebuild the GAL and redraw the screen.
void OnAppendProject(wxCommandEvent &event)
SCH_SHEET_PATH & GetCurrentSheet() const
SCHEMATIC & Schematic() const
void updateTitle()
Set the main window title bar text.
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 LoadDrawingSheet()
Load the drawing sheet file.
virtual void DeleteAutoSaveFile(const wxFileName &aFileName) override
void SetSheetNumberAndCount()
Set the m_ScreenNumber and m_NumberOfScreens members for screens.
bool AddSheetAndUpdateDisplay(const wxString aFullFileName)
Add a sheet file into the current sheet and updates display.
void ClearRepeatItemsList()
Clear the list of items which are to be repeated with the insert key.
void RecalculateConnections(SCH_COMMIT *aCommit, SCH_CLEANUP_FLAGS aCleanupFlags)
Generate the connection data for the entire schematic hierarchy.
void initScreenZoom()
Initialize the zoom value of the current screen and mark the screen as zoom-initialized.
void OnImportProject(wxCommandEvent &event)
bool AppendSchematic()
Import a KiCad schematic into the current sheet.
virtual void CheckForAutoSaveFile(const wxFileName &aFileName) override
This overloaded version checks if the auto save master file "#auto_saved_files#" exists and recovers ...
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
Saves 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.
Definition: sch_io_mgr.cpp:165
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:166
Handle actions specific to the schematic editor.
Container class that holds multiple SCH_SCREEN objects in a hierarchy.
Definition: sch_screen.h:710
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()
built the list of sheet paths sharing a screen for each screen in use
size_t GetCount() const
Definition: sch_screen.h:715
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:177
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()
Gets the full RTree, usually for iterating.
Definition: sch_screen.h:108
const wxString & GetFileName() const
Definition: sch_screen.h:143
const KIID & GetUuid() const
Definition: sch_screen.h:531
void SetFileName(const wxString &aFileName)
Set the file name for this screen to aFileName.
Definition: sch_screen.cpp:117
int GetFileFormatVersionAtLoad() const
Definition: sch_screen.h:128
void AssignNewUuid()
Definition: sch_screen.h:533
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.
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:57
void SetFileName(const wxString &aFilename)
Definition: sch_sheet.h:312
wxString GetFileName() const
Return the filename corresponding to this sheet.
Definition: sch_sheet.h:306
bool IsRootSheet() const
Definition: sch_sheet.cpp:204
wxString GetName() const
Definition: sch_sheet.h:107
void SetName(const wxString &aName)
Definition: sch_sheet.h:108
SCH_SCREEN * GetScreen() const
Definition: sch_sheet.h:110
int AddItemToSel(const TOOL_EVENT &aEvent)
void SaveProjectAs(const wxString &aFullPath, PROJECT *aProject=nullptr)
Sets the currently loaded project path and saves it (pointers remain valid) Note that this will not m...
void SaveProjectCopy(const wxString &aFullPath, PROJECT *aProject=nullptr)
Saves a copy of the current project under the given path.
bool SaveProject(const wxString &aFullPath=wxEmptyString, PROJECT *aProject=nullptr)
Saves a loaded project.
bool LoadProject(const wxString &aFullPath, bool aSetActive=true)
Loads a project or sets up a new project with a specified path.
bool UnloadProject(PROJECT *aProject, bool aSave=true)
Saves, unloads and unregisters the given PROJECT.
bool TriggerBackupIfNeeded(REPORTER &aReporter) const
Calls BackupProject if a new backup is needed according to the current backup policy.
The SIMULATOR_FRAME holds the main user-interface for running simulations.
A name/value tuple with unique names and optional values.
A collection of SYMBOL_LIB objects.
int GetLibraryCount()
static void SetLibNamesAndPaths(PROJECT *aProject, const wxString &aPaths, const wxArrayString &aNames)
static void GetLibNamesAndPaths(PROJECT *aProject, wxString *aPaths, wxArrayString *aNames=nullptr)
TOOL_MANAGER * m_toolManager
Definition: tools_holder.h:167
@ SUPERMODEL_RELOAD
For schematics, the entire schematic changed, not just the sheet.
Definition: tool_base.h:81
bool ProcessEvent(const TOOL_EVENT &aEvent)
Propagate an event to tools that requested events of matching type(s).
bool RunAction(const std::string &aActionName, T aParam)
Run the specified action immediately, pausing the current action to run the new one.
Definition: tool_manager.h:150
bool RunSynchronousAction(const TOOL_ACTION &aAction, COMMIT *aCommit, T aParam)
Run the specified action immediately, pausing the current action to run the new one.
Definition: tool_manager.h:197
static void ResolvePossibleSymlinks(wxFileName &aFilename)
Definition: wx_filename.cpp:92
void Flush()
Build the HTML messages page.
bool HasMessage() const override
Returns true if the reporter client is non-empty.
void RemoveAllButtons()
Remove all the buttons that have been added by the user.
Definition: wx_infobar.cpp:304
@ OUTDATED_SAVE
OUTDATED_SAVE Messages that should be cleared on save.
void Dismiss() override
Dismisses the infobar and updates the containing layout and AUI manager (if one is provided).
Definition: wx_infobar.cpp:190
void AddCloseButton(const wxString &aTooltip=_("Hide this message."))
Add the default close button to the infobar on the right side.
Definition: wx_infobar.cpp:294
MESSAGE_TYPE GetMessageType() const
Definition: wx_infobar.h:100
void ShowMessage(const wxString &aMessage, int aFlags=wxICON_INFORMATION) override
Show the info bar with the provided message and icon.
Definition: wx_infobar.cpp:154
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:164
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:424
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:44
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition: confirm.cpp:250
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:170
void DisplayInfoMessage(wxWindow *aParent, const wxString &aMessage, const wxString &aExtraInfo)
Display an informational message box with aMessage.
Definition: confirm.cpp:222
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:130
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition: confirm.cpp:195
This file is part of the common library.
static bool empty(const wxTextEntryBase *aCtrl)
#define _(s)
#define ENDPOINT
ends. (Used to support dragging.)
#define SKIP_STRUCT
flag indicating that the structure should be ignored
#define STARTPOINT
When a line is selected, these flags indicate which.
void removeFile(const wxString &aFilename, wxArrayString &aUnremoved)
void Reset() override
@ FRAME_SIMULATOR
Definition: frame_type.h:38
static const std::string ProjectFileExtension
static const std::string LegacyProjectFileExtension
static const std::string KiCadSchematicFileExtension
static const std::string LegacySymbolLibFileExtension
static const std::string BackupFileSuffix
static const std::string AutoSaveFilePrefix
static wxString KiCadSchematicFileWildcard()
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
PROJECT & Prj()
Definition: kicad.cpp:595
#define KICTL_CREATE
caller thinks requested project files may not exist.
Definition: kiway_player.h:76
#define KICTL_REVERT
reverting to a previously-saved (KiCad) file.
Definition: kiway_player.h:78
#define KICTL_KICAD_ONLY
chosen file is from KiCad according to user
Definition: kiway_player.h:75
@ LAYER_BUS
Definition: layer_ids.h:358
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
bool DuplicatePermissions(const wxString &aSrc, const wxString &aDest)
Duplicates the file security data from one file to another ensuring that they are the same between bo...
Definition: unix/io.cpp:40
PGM_BASE & Pgm()
The global Program "get" accessor.
Definition: pgm_base.cpp:1059
see class PGM_BASE
@ GLOBAL_CLEANUP
#define SEXPR_SCHEMATIC_FILE_VERSION
Schematic file version.
Definition of the SCH_SHEET_PATH and SCH_SHEET_LIST classes for Eeschema.
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.
Definition: app_settings.h:146
Variant of PARSE_ERROR indicating that a syntax or related error was likely caused by a file generate...
Definition: ki_exception.h:176
Container that describes file type info.
Definition: io_base.h:40
std::vector< std::string > m_FileExtensions
Filter used for file pickers if m_IsFile is true.
Definition: io_base.h:42
bool m_CanRead
Whether the IO can read this file type.
Definition: io_base.h:45
wxString FileFilter() const
Definition: io_base.cpp:40
Definition for symbol library class.
wxLogTrace helper definitions.
@ SCH_LINE_T
Definition: typeinfo.h:163
@ SCH_SHEET_T
Definition: typeinfo.h:174
@ SCH_BUS_BUS_ENTRY_T
Definition: typeinfo.h:162
wxString formatWildcardExt(const wxString &aWildcard)
Format wildcard extension to support case sensitive file dialogs.
Definition of file extensions used in Kicad.