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 if( aSavePath.IsEmpty() )
831 return false;
832
833 // Construct the name of the file to be saved
834 schematicFileName = Prj().AbsolutePath( aSavePath );
835 oldFileName = schematicFileName;
836
837 // Write through symlinks, don't replace them
838 WX_FILENAME::ResolvePossibleSymlinks( schematicFileName );
839
840 if( !IsWritable( schematicFileName ) )
841 return false;
842
843 wxFileName projectFile( schematicFileName );
844
845 projectFile.SetExt( FILEEXT::ProjectFileExtension );
846
847 if( projectFile.FileExists() )
848 {
849 // Save various ERC settings, such as violation severities (which may have been edited
850 // via the ERC dialog as well as the Schematic Setup dialog), ERC exclusions, etc.
852 }
853
854 wxString tempFile = wxFileName::CreateTempFileName( wxS( "eeschema" ) );
855
856 // Save
857 wxLogTrace( traceAutoSave, wxS( "Saving file " ) + schematicFileName.GetFullPath() );
858
861
862 SCH_IO_MGR::SCH_FILE_T pluginType = SCH_IO_MGR::GuessPluginTypeFromSchPath(
863 schematicFileName.GetFullPath() );
864
865 if( pluginType == SCH_IO_MGR::SCH_FILE_UNKNOWN )
866 pluginType = SCH_IO_MGR::SCH_KICAD;
867
868 IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( pluginType ) );
869
870 try
871 {
872 pi->SaveSchematicFile( tempFile, aSheet, &Schematic() );
873 success = true;
874 }
875 catch( const IO_ERROR& ioe )
876 {
877 msg.Printf( _( "Error saving schematic file '%s'.\n%s" ),
878 schematicFileName.GetFullPath(),
879 ioe.What() );
880 DisplayError( this, msg );
881
882 msg.Printf( _( "Failed to create temporary file '%s'." ),
883 tempFile );
884 SetMsgPanel( wxEmptyString, msg );
885
886 // In case we started a file but didn't fully write it, clean up
887 wxRemoveFile( tempFile );
888
889 success = false;
890 }
891
892 if( success )
893 {
894 // Preserve the permissions of the current file
895 KIPLATFORM::IO::DuplicatePermissions( schematicFileName.GetFullPath(), tempFile );
896
897 // Replace the original with the temporary file we just wrote
898 success = wxRenameFile( tempFile, schematicFileName.GetFullPath() );
899
900 if( !success )
901 {
902 msg.Printf( _( "Error saving schematic file '%s'.\n"
903 "Failed to rename temporary file '%s'." ),
904 schematicFileName.GetFullPath(),
905 tempFile );
906 DisplayError( this, msg );
907
908 msg.Printf( _( "Failed to rename temporary file '%s'." ),
909 tempFile );
910 SetMsgPanel( wxEmptyString, msg );
911 }
912 }
913
914 if( success )
915 {
916 // Delete auto save file.
917 wxFileName autoSaveFileName = schematicFileName;
918 autoSaveFileName.SetName( FILEEXT::AutoSaveFilePrefix + schematicFileName.GetName() );
919
920 if( autoSaveFileName.FileExists() )
921 {
922 wxLogTrace( traceAutoSave,
923 wxS( "Removing auto save file <" ) + autoSaveFileName.GetFullPath() +
924 wxS( ">" ) );
925
926 wxRemoveFile( autoSaveFileName.GetFullPath() );
927 }
928
929 screen->SetContentModified( false );
930
931 msg.Printf( _( "File '%s' saved." ), screen->GetFileName() );
932 SetStatusText( msg, 0 );
933 }
934 else
935 {
936 DisplayError( this, _( "File write operation failed." ) );
937 }
938
939 return success;
940}
941
942
943bool SCH_EDIT_FRAME::SaveProject( bool aSaveAs )
944{
945 wxString msg;
946 SCH_SCREEN* screen;
947 SCH_SCREENS screens( Schematic().Root() );
948 bool saveCopy = aSaveAs && !Kiface().IsSingle();
949 bool success = true;
950 bool updateFileHistory = false;
951 bool createNewProject = false;
952
953 // I want to see it in the debugger, show me the string! Can't do that with wxFileName.
954 wxString fileName = Prj().AbsolutePath( Schematic().Root().GetFileName() );
955 wxFileName fn = fileName;
956
957 // Path to save each screen to: will be the stored filename by default, but is overwritten by
958 // a Save As Copy operation.
959 std::unordered_map<SCH_SCREEN*, wxString> filenameMap;
960
961 // Handle "Save As" and saving a new project/schematic for the first time in standalone
962 if( Prj().IsNullProject() || aSaveAs )
963 {
964 // Null project should only be possible in standalone mode.
965 wxCHECK( Kiface().IsSingle() || aSaveAs, false );
966
967 wxFileName newFileName;
968 wxFileName savePath( Prj().GetProjectFullName() );
969
970 if( !savePath.IsOk() || !savePath.IsDirWritable() )
971 {
972 savePath = GetMruPath();
973
974 if( !savePath.IsOk() || !savePath.IsDirWritable() )
976 }
977
978 if( savePath.HasExt() )
979 savePath.SetExt( FILEEXT::KiCadSchematicFileExtension );
980 else
981 savePath.SetName( wxEmptyString );
982
983 wxFileDialog dlg( this, _( "Schematic Files" ), savePath.GetPath(), savePath.GetFullName(),
985 wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
986
987 FILEDLG_HOOK_SAVE_PROJECT newProjectHook;
988
989 // Add a "Create a project" checkbox in standalone mode and one isn't loaded
990 if( Kiface().IsSingle() || aSaveAs )
991 {
992 dlg.SetCustomizeHook( newProjectHook );
993 }
994
995 if( dlg.ShowModal() == wxID_CANCEL )
996 return false;
997
998 newFileName = EnsureFileExtension( dlg.GetPath(), FILEEXT::KiCadSchematicFileExtension );
999
1000 if( ( !newFileName.DirExists() && !newFileName.Mkdir() ) ||
1001 !newFileName.IsDirWritable() )
1002 {
1003 msg.Printf( _( "Folder '%s' could not be created.\n\n"
1004 "Make sure you have write permissions and try again." ),
1005 newFileName.GetPath() );
1006
1007 wxMessageDialog dlgBadPath( this, msg, _( "Error" ),
1008 wxOK | wxICON_EXCLAMATION | wxCENTER );
1009
1010 dlgBadPath.ShowModal();
1011 return false;
1012 }
1013
1014 if( newProjectHook.IsAttachedToDialog() )
1015 createNewProject = newProjectHook.GetCreateNewProject();
1016
1017 if( !saveCopy )
1018 {
1019 Schematic().Root().SetFileName( newFileName.GetFullName() );
1020 Schematic().RootScreen()->SetFileName( newFileName.GetFullPath() );
1021 updateFileHistory = true;
1022 }
1023 else
1024 {
1025 filenameMap[Schematic().RootScreen()] = newFileName.GetFullPath();
1026 }
1027
1028 // Set the base path to all new sheets.
1029 for( size_t i = 0; i < screens.GetCount(); i++ )
1030 {
1031 screen = screens.GetScreen( i );
1032
1033 wxCHECK2( screen, continue );
1034
1035 // The root screen file name has already been set.
1036 if( screen == Schematic().RootScreen() )
1037 continue;
1038
1039 wxFileName tmp = screen->GetFileName();
1040
1041 // Assume existing sheet files are being reused and do not save them to the new
1042 // path. Maybe in the future, add a user option to copy schematic files to the
1043 // new project path.
1044 if( tmp.FileExists() )
1045 continue;
1046
1047 if( tmp.GetPath().IsEmpty() )
1048 {
1049 tmp.SetPath( newFileName.GetPath() );
1050 }
1051 else if( tmp.GetPath() == fn.GetPath() )
1052 {
1053 tmp.SetPath( newFileName.GetPath() );
1054 }
1055 else if( tmp.GetPath().StartsWith( fn.GetPath() ) )
1056 {
1057 // NOTE: this hasn't been tested because the sheet properties dialog no longer
1058 // allows adding a path specifier in the file name field.
1059 wxString newPath = newFileName.GetPath();
1060 newPath += tmp.GetPath().Right( fn.GetPath().Length() );
1061 tmp.SetPath( newPath );
1062 }
1063
1064 wxLogTrace( tracePathsAndFiles,
1065 wxS( "Moving schematic from '%s' to '%s'." ),
1066 screen->GetFileName(),
1067 tmp.GetFullPath() );
1068
1069 if( !tmp.DirExists() && !tmp.Mkdir() )
1070 {
1071 msg.Printf( _( "Folder '%s' could not be created.\n\n"
1072 "Make sure you have write permissions and try again." ),
1073 newFileName.GetPath() );
1074
1075 wxMessageDialog dlgBadFilePath( this, msg, _( "Error" ),
1076 wxOK | wxICON_EXCLAMATION | wxCENTER );
1077
1078 dlgBadFilePath.ShowModal();
1079 return false;
1080 }
1081
1082 if( saveCopy )
1083 filenameMap[screen] = tmp.GetFullPath();
1084 else
1085 screen->SetFileName( tmp.GetFullPath() );
1086 }
1087
1088 // Attempt to make sheet file name paths relative to the new root schematic path.
1089 for( SCH_SHEET_PATH& sheet : Schematic().BuildUnorderedSheetList() )
1090 {
1091 if( !sheet.Last()->IsRootSheet() )
1092 sheet.MakeFilePathRelativeToParentSheet();
1093 }
1094 }
1095 else if( !fn.FileExists() )
1096 {
1097 // File doesn't exist yet; true if we just imported something
1098 updateFileHistory = true;
1099 }
1100 else if( !IsContentModified() )
1101 {
1102 return true;
1103 }
1104
1105 if( filenameMap.empty() || !saveCopy )
1106 {
1107 for( size_t i = 0; i < screens.GetCount(); i++ )
1108 filenameMap[screens.GetScreen( i )] = screens.GetScreen( i )->GetFileName();
1109 }
1110
1111 // Warn user on potential file overwrite. This can happen on shared sheets.
1112 wxArrayString overwrittenFiles;
1113 wxArrayString lockedFiles;
1114
1115 for( size_t i = 0; i < screens.GetCount(); i++ )
1116 {
1117 screen = screens.GetScreen( i );
1118
1119 wxCHECK2( screen, continue );
1120
1121 // Convert legacy schematics file name extensions for the new format.
1122 wxFileName tmpFn = filenameMap[screen];
1123
1124 if( !tmpFn.IsOk() )
1125 continue;
1126
1127 if( tmpFn.FileExists() && !tmpFn.IsFileWritable() )
1128 lockedFiles.Add( tmpFn.GetFullPath() );
1129
1130 if( tmpFn.GetExt() == FILEEXT::KiCadSchematicFileExtension )
1131 continue;
1132
1134
1135 if( tmpFn.FileExists() )
1136 overwrittenFiles.Add( tmpFn.GetFullPath() );
1137 }
1138
1139 if( !lockedFiles.IsEmpty() )
1140 {
1141 for( const wxString& lockedFile : lockedFiles )
1142 {
1143 if( msg.IsEmpty() )
1144 msg = lockedFile;
1145 else
1146 msg += "\n" + lockedFile;
1147 }
1148
1149 wxRichMessageDialog dlg( this, wxString::Format( _( "Failed to save %s." ),
1150 Schematic().Root().GetFileName() ),
1151 _( "Locked File Warning" ),
1152 wxOK | wxICON_WARNING | wxCENTER );
1153 dlg.SetExtendedMessage( _( "You do not have write permissions to:\n\n" ) + msg );
1154
1155 dlg.ShowModal();
1156 return false;
1157 }
1158
1159 if( !overwrittenFiles.IsEmpty() )
1160 {
1161 for( const wxString& overwrittenFile : overwrittenFiles )
1162 {
1163 if( msg.IsEmpty() )
1164 msg = overwrittenFile;
1165 else
1166 msg += "\n" + overwrittenFile;
1167 }
1168
1169 wxRichMessageDialog dlg( this, _( "Saving will overwrite existing files." ),
1170 _( "Save Warning" ),
1171 wxOK | wxCANCEL | wxCANCEL_DEFAULT | wxCENTER |
1172 wxICON_EXCLAMATION );
1173 dlg.ShowDetailedText( _( "The following files will be overwritten:\n\n" ) + msg );
1174 dlg.SetOKCancelLabels( wxMessageDialog::ButtonLabel( _( "Overwrite Files" ) ),
1175 wxMessageDialog::ButtonLabel( _( "Abort Project Save" ) ) );
1176
1177 if( dlg.ShowModal() == wxID_CANCEL )
1178 return false;
1179 }
1180
1181 screens.BuildClientSheetPathList();
1182
1183 for( size_t i = 0; i < screens.GetCount(); i++ )
1184 {
1185 screen = screens.GetScreen( i );
1186
1187 wxCHECK2( screen, continue );
1188
1189 // Convert legacy schematics file name extensions for the new format.
1190 wxFileName tmpFn = filenameMap[screen];
1191
1192 if( tmpFn.IsOk() && tmpFn.GetExt() != FILEEXT::KiCadSchematicFileExtension )
1193 {
1194 updateFileHistory = true;
1196
1197 for( EDA_ITEM* item : screen->Items().OfType( SCH_SHEET_T ) )
1198 {
1199 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
1200 wxFileName sheetFileName = sheet->GetFileName();
1201
1202 if( !sheetFileName.IsOk()
1203 || sheetFileName.GetExt() == FILEEXT::KiCadSchematicFileExtension )
1204 continue;
1205
1206 sheetFileName.SetExt( FILEEXT::KiCadSchematicFileExtension );
1207 sheet->SetFileName( sheetFileName.GetFullPath() );
1208 UpdateItem( sheet );
1209 }
1210
1211 filenameMap[screen] = tmpFn.GetFullPath();
1212
1213 if( !saveCopy )
1214 screen->SetFileName( tmpFn.GetFullPath() );
1215 }
1216
1217 // Do not save sheet symbols with no valid filename set
1218 if( !tmpFn.IsOk() )
1219 continue;
1220
1221 std::vector<SCH_SHEET_PATH>& sheets = screen->GetClientSheetPaths();
1222
1223 if( sheets.size() == 1 )
1224 screen->SetVirtualPageNumber( 1 );
1225 else
1226 screen->SetVirtualPageNumber( 0 ); // multiple uses; no way to store the real sheet #
1227
1228 // This is a new schematic file so make sure it has a unique ID.
1229 if( !saveCopy && tmpFn.GetFullPath() != screen->GetFileName() )
1230 screen->AssignNewUuid();
1231
1232 success &= saveSchematicFile( screens.GetSheet( i ), tmpFn.GetFullPath() );
1233 }
1234
1235 if( success )
1236 m_autoSaveRequired = false;
1237
1238 // One or more of the modified sheets did not save correctly so update the auto save file.
1239 if( !aSaveAs && !success )
1240 success &= updateAutoSaveFile();
1241
1242 if( aSaveAs && success )
1243 LockFile( Schematic().RootScreen()->GetFileName() );
1244
1245 if( updateFileHistory )
1246 UpdateFileHistory( Schematic().RootScreen()->GetFileName() );
1247
1248 // Save the sheet name map to the project file
1249 std::vector<FILE_INFO_PAIR>& sheets = Prj().GetProjectFile().GetSheets();
1250 sheets.clear();
1251
1252 for( SCH_SHEET_PATH& sheetPath : Schematic().BuildUnorderedSheetList() )
1253 {
1254 SCH_SHEET* sheet = sheetPath.Last();
1255
1256 wxCHECK2( sheet, continue );
1257
1258 // Use the schematic UUID for the root sheet.
1259 if( sheet->IsRootSheet() )
1260 {
1261 screen = sheet->GetScreen();
1262
1263 wxCHECK2( screen, continue );
1264
1265 sheets.emplace_back( std::make_pair( screen->GetUuid(), sheet->GetName() ) );
1266 }
1267 else
1268 {
1269 sheets.emplace_back( std::make_pair( sheet->m_Uuid, sheet->GetName() ) );
1270 }
1271 }
1272
1273 wxASSERT( filenameMap.count( Schematic().RootScreen() ) );
1274 wxFileName projectPath( filenameMap.at( Schematic().RootScreen() ) );
1275 projectPath.SetExt( FILEEXT::ProjectFileExtension );
1276
1277 if( Prj().IsNullProject() || ( aSaveAs && !saveCopy ) )
1278 {
1279 Prj().SetReadOnly( !createNewProject );
1280 GetSettingsManager()->SaveProjectAs( projectPath.GetFullPath() );
1281 }
1282 else if( saveCopy && createNewProject )
1283 {
1284 GetSettingsManager()->SaveProjectCopy( projectPath.GetFullPath() );
1285 }
1286 else
1287 {
1290 }
1291
1292 if( !Kiface().IsSingle() )
1293 {
1294 WX_STRING_REPORTER backupReporter( &msg );
1295
1296 if( !GetSettingsManager()->TriggerBackupIfNeeded( backupReporter ) )
1297 SetStatusText( msg, 0 );
1298 }
1299
1300 updateTitle();
1301
1303 m_infoBar->Dismiss();
1304
1305 return success;
1306}
1307
1308
1310{
1311 wxFileName tmpFileName = Schematic().Root().GetFileName();
1312 wxFileName fn = tmpFileName;
1313 wxFileName tmp;
1314 SCH_SCREENS screens( Schematic().Root() );
1315
1316 // Don't run autosave if content has not been modified
1317 if( !IsContentModified() )
1318 return true;
1319
1320 bool autoSaveOk = true;
1321
1322 if( fn.GetPath().IsEmpty() )
1323 tmp.AssignDir( Prj().GetProjectPath() );
1324 else
1325 tmp.AssignDir( fn.GetPath() );
1326
1327 if( !tmp.IsOk() )
1328 return false;
1329
1330 if( !IsWritable( tmp ) )
1331 return false;
1332
1333 wxString title = GetTitle(); // Save frame title, that can be modified by the save process
1334
1335 for( size_t i = 0; i < screens.GetCount(); i++ )
1336 {
1337 // Only create auto save files for the schematics that have been modified.
1338 if( !screens.GetScreen( i )->IsContentModified() )
1339 continue;
1340
1341 tmpFileName = fn = screens.GetScreen( i )->GetFileName();
1342
1343 // Auto save file name is the normal file name prefixed with GetAutoSavePrefix().
1344 fn.SetName( FILEEXT::AutoSaveFilePrefix + fn.GetName() );
1345
1346 if( saveSchematicFile( screens.GetSheet( i ), fn.GetFullPath() ) )
1347 {
1348 // This was only an auto-save, not a real save. Reset the modified flag.
1349 screens.GetScreen( i )->SetContentModified();
1350 }
1351 else
1352 {
1353 autoSaveOk = false;
1354 }
1355 }
1356
1357 if( autoSaveOk && updateAutoSaveFile() )
1358 {
1359 m_autoSaveRequired = false;
1360 m_autoSavePending = false;
1361
1362 if( !Kiface().IsSingle()
1363 && GetSettingsManager()->GetCommonSettings()->m_Backup.backup_on_autosave )
1364 {
1366 }
1367 }
1368
1369 SetTitle( title );
1370
1371 return autoSaveOk;
1372}
1373
1374
1375bool SCH_EDIT_FRAME::importFile( const wxString& aFileName, int aFileType,
1376 const STRING_UTF8_MAP* aProperties )
1377{
1378 wxFileName filename( aFileName );
1379 wxFileName newfilename;
1380 SCH_IO_MGR::SCH_FILE_T fileType = (SCH_IO_MGR::SCH_FILE_T) aFileType;
1381
1382 wxCommandEvent changingEvt( EDA_EVT_SCHEMATIC_CHANGING );
1383 ProcessEventLocally( changingEvt );
1384
1385 switch( fileType )
1386 {
1387 case SCH_IO_MGR::SCH_ALTIUM:
1388 case SCH_IO_MGR::SCH_CADSTAR_ARCHIVE:
1389 case SCH_IO_MGR::SCH_EAGLE:
1390 case SCH_IO_MGR::SCH_LTSPICE:
1391 case SCH_IO_MGR::SCH_EASYEDA:
1392 case SCH_IO_MGR::SCH_EASYEDAPRO:
1393 {
1394 // We insist on caller sending us an absolute path, if it does not, we say it's a bug.
1395 wxCHECK_MSG( filename.IsAbsolute(), false,
1396 wxS( "Import schematic: path is not absolute!" ) );
1397
1398 try
1399 {
1400 IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( fileType ) );
1401 DIALOG_HTML_REPORTER errorReporter( this );
1402 WX_PROGRESS_REPORTER progressReporter( this, _( "Importing Schematic" ), 1 );
1403
1404 if( PROJECT_CHOOSER_PLUGIN* c_pi = dynamic_cast<PROJECT_CHOOSER_PLUGIN*>( pi.get() ) )
1405 {
1406 c_pi->RegisterCallback( std::bind( DIALOG_IMPORT_CHOOSE_PROJECT::RunModal,
1407 this, std::placeholders::_1 ) );
1408 }
1409
1410 if( eeconfig()->m_System.show_import_issues )
1411 pi->SetReporter( errorReporter.m_Reporter );
1412 else
1413 pi->SetReporter( &NULL_REPORTER::GetInstance() );
1414
1415 pi->SetProgressReporter( &progressReporter );
1416
1417 SCH_SHEET* loadedSheet = pi->LoadSchematicFile( aFileName, &Schematic(), nullptr,
1418 aProperties );
1419
1420 if( loadedSheet )
1421 {
1422 Schematic().SetRoot( loadedSheet );
1423
1424 if( errorReporter.m_Reporter->HasMessage() )
1425 {
1426 errorReporter.m_Reporter->Flush(); // Build HTML messages
1427 errorReporter.ShowModal();
1428 }
1429
1430 // Non-KiCad schematics do not use a drawing-sheet (or if they do, it works
1431 // differently to KiCad), so set it to an empty one.
1433 drawingSheet.SetEmptyLayout();
1434 BASE_SCREEN::m_DrawingSheetFileName = "empty.kicad_wks";
1435
1436 newfilename.SetPath( Prj().GetProjectPath() );
1437 newfilename.SetName( Prj().GetProjectName() );
1438 newfilename.SetExt( FILEEXT::KiCadSchematicFileExtension );
1439
1440 SetScreen( GetCurrentSheet().LastScreen() );
1441
1442 Schematic().Root().SetFileName( newfilename.GetFullName() );
1443 GetScreen()->SetFileName( newfilename.GetFullPath() );
1445
1447
1448 // Only perform the dangling end test on root sheet.
1450 }
1451 else
1452 {
1453 CreateScreens();
1454 }
1455 }
1456 catch( const IO_ERROR& ioe )
1457 {
1458 // Do not leave g_RootSheet == NULL because it is expected to be
1459 // a valid sheet. Therefore create a dummy empty root sheet and screen.
1460 CreateScreens();
1462
1463 wxString msg = wxString::Format( _( "Error loading schematic '%s'." ), aFileName );
1464 DisplayErrorMessage( this, msg, ioe.What() );
1465
1466 msg.Printf( _( "Failed to load '%s'." ), aFileName );
1467 SetMsgPanel( wxEmptyString, msg );
1468 }
1469 catch( const std::exception& exc )
1470 {
1471 CreateScreens();
1473
1474 wxString msg = wxString::Format( _( "Unhandled exception occurred loading schematic "
1475 "'%s'." ), aFileName );
1476 DisplayErrorMessage( this, msg, exc.what() );
1477
1478 msg.Printf( _( "Failed to load '%s'." ), aFileName );
1479 SetMsgPanel( wxEmptyString, msg );
1480 }
1481
1484
1487 SyncView();
1488
1490
1491 wxCommandEvent e( EDA_EVT_SCHEMATIC_CHANGED );
1492 ProcessEventLocally( e );
1493
1494 for( wxEvtHandler* listener : m_schematicChangeListeners )
1495 {
1496 wxCHECK2( listener, continue );
1497
1498 // Use the windows variant when handling event messages in case there is any
1499 // special event handler pre and/or post processing specific to windows.
1500 wxWindow* win = dynamic_cast<wxWindow*>( listener );
1501
1502 if( win )
1503 win->HandleWindowEvent( e );
1504 else
1505 listener->SafelyProcessEvent( e );
1506 }
1507
1508 updateTitle();
1509 break;
1510 }
1511
1512 default:
1513 break;
1514 }
1515
1516 return true;
1517}
1518
1519
1521{
1522 SCH_SCREENS screenList( Schematic().Root() );
1523
1524 // Save any currently open and modified project files.
1525 for( SCH_SCREEN* screen = screenList.GetFirst(); screen; screen = screenList.GetNext() )
1526 {
1527 SIMULATOR_FRAME* simFrame = (SIMULATOR_FRAME*) Kiway().Player( FRAME_SIMULATOR, false );
1528
1529 // Simulator must be closed before loading another schematic, otherwise it may crash.
1530 // If there are any changes in the simulator the user will be prompted to save them.
1531 if( simFrame && !simFrame->Close() )
1532 return false;
1533
1534 if( screen->IsContentModified() )
1535 {
1536 if( !HandleUnsavedChanges( this, _( "The current schematic has been modified. "
1537 "Save changes?" ),
1538 [&]() -> bool
1539 {
1540 return SaveProject();
1541 } ) )
1542 {
1543 return false;
1544 }
1545 }
1546 }
1547
1548 return true;
1549}
1550
1551
1553{
1554 wxFileName tmpFn = Prj().GetProjectFullName();
1555 wxFileName autoSaveFileName( tmpFn.GetPath(), getAutoSaveFileName() );
1556
1557 wxLogTrace( traceAutoSave, "Creating auto save file %s", autoSaveFileName.GetFullPath() );
1558
1559 wxCHECK( autoSaveFileName.IsDirWritable(), false );
1560
1561 wxFileName fn;
1562 SCH_SCREENS screens( Schematic().Root() );
1563 std::vector< wxString > autoSavedFiles;
1564
1565 for( size_t i = 0; i < screens.GetCount(); i++ )
1566 {
1567 // Only create auto save files for the schematics that have been modified.
1568 if( !screens.GetScreen( i )->IsContentModified() )
1569 continue;
1570
1571 fn = screens.GetScreen( i )->GetFileName();
1572
1573 // Auto save file name is the normal file name prefixed with GetAutoSavePrefix().
1574 fn.SetName( FILEEXT::AutoSaveFilePrefix + fn.GetName() );
1575 autoSavedFiles.emplace_back( fn.GetFullPath() );
1576 }
1577
1578 wxTextFile autoSaveFile( autoSaveFileName.GetFullPath() );
1579
1580 if( autoSaveFileName.FileExists() && !wxRemoveFile( autoSaveFileName.GetFullPath() ) )
1581 {
1582 wxLogTrace( traceAutoSave, "Error removing auto save file %s",
1583 autoSaveFileName.GetFullPath() );
1584
1585 return false;
1586 }
1587
1588 // No modified sheet files to save.
1589 if( autoSavedFiles.empty() )
1590 return true;
1591
1592 if( !autoSaveFile.Create() )
1593 return false;
1594
1595 for( const wxString& fileName : autoSavedFiles )
1596 {
1597 wxLogTrace( traceAutoSave, "Adding auto save file %s to %s",
1598 fileName, autoSaveFileName.GetName() );
1599 autoSaveFile.AddLine( fileName );
1600 }
1601
1602 if( !autoSaveFile.Write() )
1603 return false;
1604
1605 wxLogTrace( traceAutoSave, "Auto save file '%s' written", autoSaveFileName.GetFullName() );
1606
1607 return true;
1608}
1609
1610
1611void removeFile( const wxString& aFilename, wxArrayString& aUnremoved )
1612{
1613 wxLogTrace( traceAutoSave, wxS( "Removing auto save file " ) + aFilename );
1614
1615 if( wxFileExists( aFilename ) && !wxRemoveFile( aFilename ) )
1616 aUnremoved.Add( aFilename );
1617};
1618
1619
1620void SCH_EDIT_FRAME::CheckForAutoSaveFile( const wxFileName& aFileName )
1621{
1622 if( !Pgm().IsGUI() )
1623 return;
1624
1625 wxCHECK_RET( aFileName.IsOk(), wxS( "Invalid file name!" ) );
1626
1627 wxLogTrace( traceAutoSave,
1628 wxS( "Checking for auto save file " ) + aFileName.GetFullPath() );
1629
1630 if( !aFileName.FileExists() )
1631 return;
1632
1633 wxString msg = _(
1634 "Well this is potentially embarrassing!\n"
1635 "It appears that the last time you were editing one or more of the schematic files\n"
1636 "were not saved properly. Do you wish to restore the last saved edits you made?" );
1637
1638 int response = wxMessageBox( msg, Pgm().App().GetAppDisplayName(), wxYES_NO | wxICON_QUESTION,
1639 this );
1640
1641 wxTextFile fileList( aFileName.GetFullPath() );
1642
1643 if( !fileList.Open() )
1644 {
1645 msg.Printf( _( "The file '%s' could not be opened.\n"
1646 "Manual recovery of automatically saved files is required." ),
1647 aFileName.GetFullPath() );
1648
1649 wxMessageBox( msg, Pgm().App().GetAppDisplayName(), wxOK | wxICON_EXCLAMATION, this );
1650 return;
1651 }
1652
1653 if( response == wxYES )
1654 {
1655 wxArrayString unrecoveredFiles;
1656
1657 for( wxString fn = fileList.GetFirstLine(); !fileList.Eof(); fn = fileList.GetNextLine() )
1658 {
1659 wxFileName recoveredFn = fn;
1660 wxString tmp = recoveredFn.GetName();
1661
1662 // Strip "_autosave-" prefix from the auto save file name.
1663 tmp.Replace( FILEEXT::AutoSaveFilePrefix, wxS( "" ), false );
1664 recoveredFn.SetName( tmp );
1665
1666 wxFileName backupFn = recoveredFn;
1667
1668 backupFn.SetExt( backupFn.GetExt() + FILEEXT::BackupFileSuffix );
1669
1670 wxLogTrace( traceAutoSave, wxS( "Recovering auto save file:\n"
1671 " Original file: '%s'\n"
1672 " Backup file: '%s'\n"
1673 " Auto save file: '%s'" ),
1674 recoveredFn.GetFullPath(), backupFn.GetFullPath(), fn );
1675
1676 if( !wxFileExists( fn ) )
1677 {
1678 unrecoveredFiles.Add( recoveredFn.GetFullPath() );
1679 }
1680 // Attempt to back up the last schematic file before overwriting it with the auto
1681 // save file.
1682 else if( recoveredFn.Exists()
1683 && !wxCopyFile( recoveredFn.GetFullPath(), backupFn.GetFullPath() ) )
1684 {
1685 unrecoveredFiles.Add( recoveredFn.GetFullPath() );
1686 }
1687 // Attempt to replace last saved file with auto save file
1688 else if( !wxRenameFile( fn, recoveredFn.GetFullPath() ) )
1689 {
1690 unrecoveredFiles.Add( recoveredFn.GetFullPath() );
1691 }
1692 }
1693
1694 if( !unrecoveredFiles.IsEmpty() )
1695 {
1696 msg = _( "The following automatically saved file(s) could not be restored\n" );
1697
1698 for( size_t i = 0; i < unrecoveredFiles.GetCount(); i++ )
1699 msg += unrecoveredFiles[i] + wxS( "\n" );
1700
1701 msg += _( "Manual recovery will be required to restore the file(s) above." );
1702 wxMessageBox( msg, Pgm().App().GetAppDisplayName(), wxOK | wxICON_EXCLAMATION,
1703 this );
1704 }
1705
1706 wxArrayString unremovedFiles;
1707 removeFile( aFileName.GetFullPath(), unremovedFiles );
1708
1709 if( !unremovedFiles.IsEmpty() )
1710 {
1711 msg.Printf( _( "The autosave file '%s' could not be removed.\n"
1712 "Manual removal will be required." ),
1713 unremovedFiles[0] );
1714
1715 wxMessageBox( msg, Pgm().App().GetAppDisplayName(), wxOK | wxICON_EXCLAMATION, this );
1716 }
1717 }
1718 else
1719 {
1720 DeleteAutoSaveFile( aFileName );
1721 }
1722}
1723
1724
1725void SCH_EDIT_FRAME::DeleteAutoSaveFile( const wxFileName& aFileName )
1726{
1727 if( !Pgm().IsGUI() )
1728 return;
1729
1730 wxCHECK_RET( aFileName.IsOk(), wxS( "Invalid file name!" ) );
1731
1732 if( !aFileName.FileExists() )
1733 return;
1734
1735 wxTextFile fileList( aFileName.GetFullPath() );
1736 wxArrayString unremovedFiles;
1737
1738 for( wxString fn = fileList.GetFirstLine(); !fileList.Eof(); fn = fileList.GetNextLine() )
1739 removeFile( fn, unremovedFiles );
1740
1741 removeFile( aFileName.GetFullPath(), unremovedFiles );
1742
1743 if( !unremovedFiles.IsEmpty() )
1744 {
1745 wxString msg = _( "The following automatically saved file(s) could not be removed\n" );
1746
1747 for( size_t i = 0; i < unremovedFiles.GetCount(); i++ )
1748 msg += unremovedFiles[i] + wxS( "\n" );
1749
1750 msg += _( "Manual removal will be required for the file(s) above." );
1751 wxMessageBox( msg, Pgm().App().GetAppDisplayName(), wxOK | wxICON_EXCLAMATION, this );
1752 }
1753}
1754
1755
1757{
1758 static wxString autoSaveFileName( wxS( "#auto_saved_files#" ) );
1759
1760 return autoSaveFileName;
1761}
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.