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,
190
191 if( schFileType == SCH_IO_MGR::SCH_LEGACY )
192 {
193 // Don't reload the symbol libraries if we are just launching Eeschema from KiCad again.
194 // They are already saved in the kiface project object.
195 if( differentProject || !Prj().GetElem( PROJECT::ELEM::SCH_SYMBOL_LIBS ) )
196 {
197 // load the libraries here, not in SCH_SCREEN::Draw() which is a context
198 // that will not tolerate DisplayError() dialog since we're already in an
199 // event handler in there.
200 // And when a schematic file is loaded, we need these libs to initialize
201 // some parameters (links to PART LIB, dangling ends ...)
204 }
205 }
206 else
207 {
208 // No legacy symbol libraries including the cache are loaded with the new file format.
210 }
211
212 // Load the symbol library table, this will be used forever more.
215
216 // Load project settings after schematic has been set up with the project link, since this will
217 // update some of the needed schematic settings such as drawing defaults
219
220 wxFileName rfn( GetCurrentFileName() );
221 rfn.MakeRelativeTo( Prj().GetProjectPath() );
222 LoadWindowState( rfn.GetFullPath() );
223
224 KIPLATFORM::APP::SetShutdownBlockReason( this, _( "Schematic file changes are unsaved" ) );
225
226 if( Kiface().IsSingle() )
227 {
229 }
230
231 if( is_new || schFileType == SCH_IO_MGR::SCH_FILE_T::SCH_FILE_UNKNOWN )
232 {
233 // mark new, unsaved file as modified.
235 GetScreen()->SetFileName( fullFileName );
236
237 if( schFileType == SCH_IO_MGR::SCH_FILE_T::SCH_FILE_UNKNOWN )
238 {
239 msg.Printf( _( "'%s' is not a KiCad schematic file.\nUse File -> Import for "
240 "non-KiCad schematic files." ),
241 fullFileName );
242
243 progressReporter.Hide();
244 DisplayErrorMessage( this, msg );
245 }
246 }
247 else
248 {
249 wxFileName autoSaveFn = fullFileName;
250
251 autoSaveFn.SetName( getAutoSaveFileName() );
252 autoSaveFn.ClearExt();
253
254 if( ( aCtl & KICTL_REVERT ) )
255 {
256 DeleteAutoSaveFile( autoSaveFn );
257 }
258 else
259 {
260 // This will rename the file if there is an autosave and the user wants to recover
261 CheckForAutoSaveFile( autoSaveFn );
262 }
263
264 SetScreen( nullptr );
265
266 IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( schFileType ) );
267
268 pi->SetProgressReporter( &progressReporter );
269
270 bool failedLoad = false;
271
272 try
273 {
274 {
275 wxBusyCursor busy;
276 Schematic().SetRoot( pi->LoadSchematicFile( fullFileName, &Schematic() ) );
277
278 // Make ${SHEETNAME} work on the root sheet until we properly support
279 // naming the root sheet
280 Schematic().Root().SetName( _( "Root" ) );
281 wxLogTrace( tracePathsAndFiles, wxS( "Loaded schematic with root sheet UUID %s" ),
282 Schematic().Root().m_Uuid.AsString() );
283 }
284
285 if( !pi->GetError().IsEmpty() )
286 {
287 DisplayErrorMessage( this, _( "The entire schematic could not be loaded. Errors "
288 "occurred attempting to load hierarchical sheets." ),
289 pi->GetError() );
290 }
291 }
292 catch( const FUTURE_FORMAT_ERROR& ffe )
293 {
294 msg.Printf( _( "Error loading schematic '%s'." ), fullFileName);
295 progressReporter.Hide();
296 DisplayErrorMessage( this, msg, ffe.Problem() );
297
298 failedLoad = true;
299 }
300 catch( const IO_ERROR& ioe )
301 {
302 msg.Printf( _( "Error loading schematic '%s'." ), fullFileName);
303 progressReporter.Hide();
304 DisplayErrorMessage( this, msg, ioe.What() );
305
306 failedLoad = true;
307 }
308 catch( const std::bad_alloc& )
309 {
310 msg.Printf( _( "Memory exhausted loading schematic '%s'." ), fullFileName );
311 progressReporter.Hide();
312 DisplayErrorMessage( this, msg, wxEmptyString );
313
314 failedLoad = true;
315 }
316
317 // This fixes a focus issue after the progress reporter is done on GTK. It shouldn't
318 // cause any issues on macOS and Windows. If it does, it will have to be conditionally
319 // compiled.
320 Raise();
321
322 if( failedLoad )
323 {
324 // Do not leave g_RootSheet == NULL because it is expected to be
325 // a valid sheet. Therefore create a dummy empty root sheet and screen.
328
329 msg.Printf( _( "Failed to load '%s'." ), fullFileName );
330 SetMsgPanel( wxEmptyString, msg );
331
332 return false;
333 }
334
335 // It's possible the schematic parser fixed errors due to bugs so warn the user
336 // that the schematic has been fixed (modified).
337 SCH_SHEET_LIST sheetList = Schematic().Hierarchy();
338
339 if( sheetList.IsModified() )
340 {
341 DisplayInfoMessage( this,
342 _( "An error was found when loading the schematic that has "
343 "been automatically fixed. Please save the schematic to "
344 "repair the broken file or it may not be usable with other "
345 "versions of KiCad." ) );
346 }
347
348 if( sheetList.AllSheetPageNumbersEmpty() )
349 sheetList.SetInitialPageNumbers();
350
351 UpdateFileHistory( fullFileName );
352
353 SCH_SCREENS schematic( Schematic().Root() );
354
355 // LIB_ID checks and symbol rescue only apply to the legacy file formats.
356 if( schFileType == SCH_IO_MGR::SCH_LEGACY )
357 {
358 // Convert any legacy bus-bus entries to just be bus wires
359 for( SCH_SCREEN* screen = schematic.GetFirst(); screen; screen = schematic.GetNext() )
360 {
361 std::vector<SCH_ITEM*> deleted;
362
363 for( SCH_ITEM* item : screen->Items() )
364 {
365 if( item->Type() == SCH_BUS_BUS_ENTRY_T )
366 {
367 SCH_BUS_BUS_ENTRY* entry = static_cast<SCH_BUS_BUS_ENTRY*>( item );
368 std::unique_ptr<SCH_LINE> wire = std::make_unique<SCH_LINE>();
369
370 wire->SetLayer( LAYER_BUS );
371 wire->SetStartPoint( entry->GetPosition() );
372 wire->SetEndPoint( entry->GetEnd() );
373
374 screen->Append( wire.release() );
375 deleted.push_back( item );
376 }
377 }
378
379 for( SCH_ITEM* item : deleted )
380 screen->Remove( item );
381 }
382
383
384 // Convert old projects over to use symbol library table.
385 if( schematic.HasNoFullyDefinedLibIds() )
386 {
387 DIALOG_SYMBOL_REMAP dlgRemap( this );
388
389 dlgRemap.ShowQuasiModal();
390 }
391 else
392 {
393 // Double check to ensure no legacy library list entries have been
394 // added to the project file symbol library list.
395 wxString paths;
396 wxArrayString libNames;
397
398 SYMBOL_LIBS::GetLibNamesAndPaths( &Prj(), &paths, &libNames );
399
400 if( !libNames.IsEmpty() )
401 {
402 if( eeconfig()->m_Appearance.show_illegal_symbol_lib_dialog )
403 {
404 wxRichMessageDialog invalidLibDlg(
405 this,
406 _( "Illegal entry found in project file symbol library list." ),
407 _( "Project Load Warning" ),
408 wxOK | wxCENTER | wxICON_EXCLAMATION );
409 invalidLibDlg.ShowDetailedText(
410 _( "Symbol libraries defined in the project file symbol library "
411 "list are no longer supported and will be removed.\n\n"
412 "This may cause broken symbol library links under certain "
413 "conditions." ) );
414 invalidLibDlg.ShowCheckBox( _( "Do not show this dialog again." ) );
415 invalidLibDlg.ShowModal();
417 !invalidLibDlg.IsCheckBoxChecked();
418 }
419
420 libNames.Clear();
421 paths.Clear();
422 SYMBOL_LIBS::SetLibNamesAndPaths( &Prj(), paths, libNames );
423 }
424
425 if( !cfg || !cfg->m_RescueNeverShow )
426 {
428 editor->RescueSymbolLibTableProject( false );
429 }
430 }
431
432 // Ensure there is only one legacy library loaded and that it is the cache library.
433 SYMBOL_LIBS* legacyLibs = PROJECT_SCH::SchLibs( &Schematic().Prj() );
434
435 if( legacyLibs->GetLibraryCount() == 0 )
436 {
437 wxString extMsg;
438 wxFileName cacheFn = pro;
439
440 cacheFn.SetName( cacheFn.GetName() + "-cache" );
442
443 msg.Printf( _( "The project symbol library cache file '%s' was not found." ),
444 cacheFn.GetFullName() );
445 extMsg = _( "This can result in a broken schematic under certain conditions. "
446 "If the schematic does not have any missing symbols upon opening, "
447 "save it immediately before making any changes to prevent data "
448 "loss. If there are missing symbols, either manual recovery of "
449 "the schematic or recovery of the symbol cache library file and "
450 "reloading the schematic is required." );
451
452 wxMessageDialog dlgMissingCache( this, msg, _( "Warning" ),
453 wxOK | wxCANCEL | wxICON_EXCLAMATION | wxCENTER );
454 dlgMissingCache.SetExtendedMessage( extMsg );
455 dlgMissingCache.SetOKCancelLabels(
456 wxMessageDialog::ButtonLabel( _( "Load Without Cache File" ) ),
457 wxMessageDialog::ButtonLabel( _( "Abort" ) ) );
458
459 if( dlgMissingCache.ShowModal() == wxID_CANCEL )
460 {
461 Schematic().Reset();
463 return false;
464 }
465 }
466
467 // Update all symbol library links for all sheets.
468 schematic.UpdateSymbolLinks();
469
472 m_infoBar->ShowMessage( _( "This file was created by an older version of KiCad. "
473 "It will be converted to the new format when saved." ),
475
476 // Legacy schematic can have duplicate time stamps so fix that before converting
477 // to the s-expression format.
478 schematic.ReplaceDuplicateTimeStamps();
479
480 for( SCH_SCREEN* screen = schematic.GetFirst(); screen; screen = schematic.GetNext() )
481 screen->FixLegacyPowerSymbolMismatches();
482
483 // Allow the schematic to be saved to new file format without making any edits.
484 OnModify();
485 }
486 else // S-expression schematic.
487 {
489 {
492 m_infoBar->ShowMessage( _( "This file was created by an older version of KiCad. "
493 "It will be converted to the new format when saved." ),
495 }
496
497 for( SCH_SCREEN* screen = schematic.GetFirst(); screen; screen = schematic.GetNext() )
498 screen->UpdateLocalLibSymbolLinks();
499
500 // Restore all of the loaded symbol and sheet instances from the root sheet.
501 if( Schematic().RootScreen()->GetFileFormatVersionAtLoad() < 20221002 )
502 sheetList.UpdateSymbolInstanceData( Schematic().RootScreen()->GetSymbolInstances() );
503
504 if( Schematic().RootScreen()->GetFileFormatVersionAtLoad() < 20221110 )
505 sheetList.UpdateSheetInstanceData( Schematic().RootScreen()->GetSheetInstances());
506
507 if( Schematic().RootScreen()->GetFileFormatVersionAtLoad() < 20230221 )
508 for( SCH_SCREEN* screen = schematic.GetFirst(); screen;
509 screen = schematic.GetNext() )
510 screen->FixLegacyPowerSymbolMismatches();
511
512 for( SCH_SCREEN* screen = schematic.GetFirst(); screen; screen = schematic.GetNext() )
513 screen->MigrateSimModels();
514
516 {
517 // Allow the schematic to be saved to new file format without making any edits.
518 OnModify();
519 }
520 }
521
522 // After the schematic is successfully loaded, we load the drawing sheet.
523 // This allows us to use the drawing sheet embedded in the schematic (if any)
524 // instead of the default one.
526
527 schematic.PruneOrphanedSymbolInstances( Prj().GetProjectName(), sheetList );
528 schematic.PruneOrphanedSheetInstances( Prj().GetProjectName(), sheetList );
529 sheetList.CheckForMissingSymbolInstances( Prj().GetProjectName() );
530
532
533 SetScreen( GetCurrentSheet().LastScreen() );
534
535 // Migrate conflicting bus definitions
536 // TODO(JE) This should only run once based on schematic file version
537 if( Schematic().ConnectionGraph()->GetBusesNeedingMigration().size() > 0 )
538 {
539 DIALOG_MIGRATE_BUSES dlg( this );
540 dlg.ShowQuasiModal();
541 OnModify();
542 }
543
544 SCH_COMMIT dummy( this );
545
547
548 if( schematic.HasSymbolFieldNamesWithWhiteSpace() )
549 {
550 m_infoBar->QueueShowMessage( _( "This schematic contains symbols that have leading "
551 "and/or trailing white space field names." ),
552 wxICON_WARNING );
553 }
554 }
555
556 // Load any exclusions from the project file
558
561
564
565 // Re-create junctions if needed. Eeschema optimizes wires by merging
566 // colinear segments. If a schematic is saved without a valid
567 // cache library or missing installed libraries, this can cause connectivity errors
568 // unless junctions are added.
569 //
570 // TODO: (RFB) This really needs to be put inside the Load() function of the SCH_IO_KICAD_LEGACY
571 // I can't put it right now because of the extra code that is above to convert legacy bus-bus
572 // entries to bus wires
573 if( schFileType == SCH_IO_MGR::SCH_LEGACY )
575
576 SyncView();
578
580
582
583 wxCommandEvent changedEvt( EDA_EVT_SCHEMATIC_CHANGED );
584 ProcessEventLocally( changedEvt );
585
586 for( wxEvtHandler* listener : m_schematicChangeListeners )
587 {
588 wxCHECK2( listener, continue );
589
590 // Use the windows variant when handling event messages in case there is any special
591 // event handler pre and/or post processing specific to windows.
592 wxWindow* win = dynamic_cast<wxWindow*>( listener );
593
594 if( win )
595 win->HandleWindowEvent( e );
596 else
597 listener->SafelyProcessEvent( e );
598 }
599
600 updateTitle();
601 m_toolManager->GetTool<SCH_NAVIGATE_TOOL>()->ResetHistory();
602
603 wxFileName fn = Prj().AbsolutePath( GetScreen()->GetFileName() );
604
605 if( fn.FileExists() && !fn.IsFileWritable() )
606 {
609 m_infoBar->ShowMessage( _( "Schematic is read only." ),
611 }
612
613#ifdef PROFILE
614 openFiles.Show();
615#endif
616 // Ensure all items are redrawn (especially the drawing-sheet items):
617 if( GetCanvas() )
618 GetCanvas()->DisplaySheet( GetCurrentSheet().LastScreen() );
619
620 return true;
621}
622
623
624void SCH_EDIT_FRAME::OnImportProject( wxCommandEvent& aEvent )
625{
626 if( Schematic().RootScreen() && !Schematic().RootScreen()->Items().empty() )
627 {
628 wxString msg = _( "This operation replaces the contents of the current schematic, "
629 "which will be permanently lost.\n\n"
630 "Do you want to proceed?" );
631
632 if( !IsOK( this, msg ) )
633 return;
634 }
635
636 // Set the project location if none is set or if we are running in standalone mode
637 bool setProject = Prj().GetProjectFullName().IsEmpty() || Kiface().IsSingle();
638 wxString path = wxPathOnly( Prj().GetProjectFullName() );
639
640 wxString fileFiltersStr;
641 wxString allWildcardsStr;
642
643 for( const SCH_IO_MGR::SCH_FILE_T& fileType : SCH_IO_MGR::SCH_FILE_T_vector )
644 {
645 if( fileType == SCH_IO_MGR::SCH_KICAD || fileType == SCH_IO_MGR::SCH_LEGACY )
646 continue; // this is "Import non-KiCad schematic"
647
648 IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( fileType ) );
649
650 if( !pi )
651 continue;
652
653 const IO_BASE::IO_FILE_DESC& desc = pi->GetSchematicFileDesc();
654
655 if( desc.m_FileExtensions.empty() || !desc.m_CanRead )
656 continue;
657
658 if( !fileFiltersStr.IsEmpty() )
659 fileFiltersStr += wxChar( '|' );
660
661 fileFiltersStr += desc.FileFilter();
662
663 for( const std::string& ext : desc.m_FileExtensions )
664 allWildcardsStr << wxS( "*." ) << formatWildcardExt( ext ) << wxS( ";" );
665 }
666
667 fileFiltersStr = _( "All supported formats" ) + wxS( "|" ) + allWildcardsStr + wxS( "|" )
668 + fileFiltersStr;
669
670 wxFileDialog dlg( this, _( "Import Schematic" ), path, wxEmptyString, fileFiltersStr,
671 wxFD_OPEN | wxFD_FILE_MUST_EXIST ); // TODO
672
673 FILEDLG_IMPORT_NON_KICAD importOptions( eeconfig()->m_System.show_import_issues );
674 dlg.SetCustomizeHook( importOptions );
675
676 if( dlg.ShowModal() == wxID_CANCEL )
677 return;
678
680
681 // Don't leave dangling pointers to previously-opened document.
682 m_toolManager->GetTool<EE_SELECTION_TOOL>()->ClearSelection();
685
686 if( setProject )
687 {
688 Schematic().SetProject( nullptr );
689 GetSettingsManager()->UnloadProject( &Prj(), false );
690
691 // Clear view before destroying schematic as repaints depend on schematic being valid
692 SetScreen( nullptr );
693
694 Schematic().Reset();
695
696 wxFileName projectFn( dlg.GetPath() );
697 projectFn.SetExt( FILEEXT::ProjectFileExtension );
698 GetSettingsManager()->LoadProject( projectFn.GetFullPath() );
699
700 Schematic().SetProject( &Prj() );
701 }
702
703 wxFileName fn = dlg.GetPath();
704
705 if( !fn.IsFileReadable() )
706 {
707 wxLogError( _( "Insufficient permissions to read file '%s'." ), fn.GetFullPath() );
708 return;
709 }
710
711 SCH_IO_MGR::SCH_FILE_T pluginType = SCH_IO_MGR::SCH_FILE_T::SCH_FILE_UNKNOWN;
712
713 for( const SCH_IO_MGR::SCH_FILE_T& fileType : SCH_IO_MGR::SCH_FILE_T_vector )
714 {
715 IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( fileType ) );
716
717 if( !pi )
718 continue;
719
720 if( pi->CanReadSchematicFile( fn.GetFullPath() ) )
721 {
722 pluginType = fileType;
723 break;
724 }
725 }
726
727 if( pluginType == SCH_IO_MGR::SCH_FILE_T::SCH_FILE_UNKNOWN )
728 {
729 wxLogError( _( "No loader can read the specified file: '%s'." ), fn.GetFullPath() );
731 SetScreen( Schematic().RootScreen() );
732 return;
733 }
734
735 importFile( dlg.GetPath(), pluginType );
736
738}
739
740
741bool SCH_EDIT_FRAME::saveSchematicFile( SCH_SHEET* aSheet, const wxString& aSavePath )
742{
743 wxString msg;
744 wxFileName schematicFileName;
745 wxFileName oldFileName;
746 bool success;
747
748 SCH_SCREEN* screen = aSheet->GetScreen();
749
750 wxCHECK( screen, false );
751
752 // Cannot save to nowhere
753 if( aSavePath.IsEmpty() )
754 return false;
755
756 // Construct the name of the file to be saved
757 schematicFileName = Prj().AbsolutePath( aSavePath );
758 oldFileName = schematicFileName;
759
760 // Write through symlinks, don't replace them
761 WX_FILENAME::ResolvePossibleSymlinks( schematicFileName );
762
763 if( !schematicFileName.DirExists() )
764 {
765 if( !wxMkdir( schematicFileName.GetPath() ) )
766 {
767 msg.Printf( _( "Error saving schematic file '%s'.\n%s" ),
768 schematicFileName.GetFullPath(),
769 "Could not create directory: %s" + schematicFileName.GetPath() );
770 DisplayError( this, msg );
771
772 return false;
773 }
774 }
775
776 if( !IsWritable( schematicFileName ) )
777 return false;
778
779 wxFileName projectFile( schematicFileName );
780
781 projectFile.SetExt( FILEEXT::ProjectFileExtension );
782
783 if( projectFile.FileExists() )
784 {
785 // Save various ERC settings, such as violation severities (which may have been edited
786 // via the ERC dialog as well as the Schematic Setup dialog), ERC exclusions, etc.
788 }
789
790 wxString tempFile = wxFileName::CreateTempFileName( wxS( "eeschema" ) );
791
792 // Save
793 wxLogTrace( traceAutoSave, wxS( "Saving file " ) + schematicFileName.GetFullPath() );
794
797
798 SCH_IO_MGR::SCH_FILE_T pluginType = SCH_IO_MGR::GuessPluginTypeFromSchPath(
799 schematicFileName.GetFullPath() );
800
801 if( pluginType == SCH_IO_MGR::SCH_FILE_UNKNOWN )
802 pluginType = SCH_IO_MGR::SCH_KICAD;
803
804 IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( pluginType ) );
805
806 try
807 {
808 pi->SaveSchematicFile( tempFile, aSheet, &Schematic() );
809 success = true;
810 }
811 catch( const IO_ERROR& ioe )
812 {
813 msg.Printf( _( "Error saving schematic file '%s'.\n%s" ),
814 schematicFileName.GetFullPath(),
815 ioe.What() );
816 DisplayError( this, msg );
817
818 msg.Printf( _( "Failed to create temporary file '%s'." ),
819 tempFile );
820 SetMsgPanel( wxEmptyString, msg );
821
822 // In case we started a file but didn't fully write it, clean up
823 wxRemoveFile( tempFile );
824
825 success = false;
826 }
827
828 if( success )
829 {
830 // Preserve the permissions of the current file
831 KIPLATFORM::IO::DuplicatePermissions( schematicFileName.GetFullPath(), tempFile );
832
833 // Replace the original with the temporary file we just wrote
834 success = wxRenameFile( tempFile, schematicFileName.GetFullPath() );
835
836 if( !success )
837 {
838 msg.Printf( _( "Error saving schematic file '%s'.\n"
839 "Failed to rename temporary file '%s'." ),
840 schematicFileName.GetFullPath(),
841 tempFile );
842 DisplayError( this, msg );
843
844 msg.Printf( _( "Failed to rename temporary file '%s'." ),
845 tempFile );
846 SetMsgPanel( wxEmptyString, msg );
847 }
848 }
849
850 if( success )
851 {
852 // Delete auto save file.
853 wxFileName autoSaveFileName = schematicFileName;
854 autoSaveFileName.SetName( FILEEXT::AutoSaveFilePrefix + schematicFileName.GetName() );
855
856 if( autoSaveFileName.FileExists() )
857 {
858 wxLogTrace( traceAutoSave,
859 wxS( "Removing auto save file <" ) + autoSaveFileName.GetFullPath() +
860 wxS( ">" ) );
861
862 wxRemoveFile( autoSaveFileName.GetFullPath() );
863 }
864
865 screen->SetContentModified( false );
866
867 msg.Printf( _( "File '%s' saved." ), screen->GetFileName() );
868 SetStatusText( msg, 0 );
869 }
870 else
871 {
872 DisplayError( this, _( "File write operation failed." ) );
873 }
874
875 return success;
876}
877
878
879bool SCH_EDIT_FRAME::SaveProject( bool aSaveAs )
880{
881 wxString msg;
882 SCH_SCREEN* screen;
883 SCH_SCREENS screens( Schematic().Root() );
884 bool saveCopy = aSaveAs && !Kiface().IsSingle();
885 bool success = true;
886 bool updateFileHistory = false;
887 bool createNewProject = false;
888
889 // I want to see it in the debugger, show me the string! Can't do that with wxFileName.
890 wxString fileName = Prj().AbsolutePath( Schematic().Root().GetFileName() );
891 wxFileName fn = fileName;
892
893 // Path to save each screen to: will be the stored filename by default, but is overwritten by
894 // a Save As Copy operation.
895 std::unordered_map<SCH_SCREEN*, wxString> filenameMap;
896
897 // Handle "Save As" and saving a new project/schematic for the first time in standalone
898 if( Prj().IsNullProject() || aSaveAs )
899 {
900 // Null project should only be possible in standalone mode.
901 wxCHECK( Kiface().IsSingle() || aSaveAs, false );
902
903 wxFileName newFileName;
904 wxFileName savePath( Prj().GetProjectFullName() );
905
906 if( !savePath.IsOk() || !savePath.IsDirWritable() )
907 {
908 savePath = GetMruPath();
909
910 if( !savePath.IsOk() || !savePath.IsDirWritable() )
912 }
913
914 if( savePath.HasExt() )
915 savePath.SetExt( FILEEXT::KiCadSchematicFileExtension );
916 else
917 savePath.SetName( wxEmptyString );
918
919 wxFileDialog dlg( this, _( "Schematic Files" ), savePath.GetPath(), savePath.GetFullName(),
921 wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
922
923 FILEDLG_HOOK_SAVE_PROJECT newProjectHook;
924
925 // Add a "Create a project" checkbox in standalone mode and one isn't loaded
926 if( Kiface().IsSingle() || aSaveAs )
927 {
928 dlg.SetCustomizeHook( newProjectHook );
929 }
930
931 if( dlg.ShowModal() == wxID_CANCEL )
932 return false;
933
934 newFileName = EnsureFileExtension( dlg.GetPath(), FILEEXT::KiCadSchematicFileExtension );
935
936 if( ( !newFileName.DirExists() && !newFileName.Mkdir() ) ||
937 !newFileName.IsDirWritable() )
938 {
939 msg.Printf( _( "Folder '%s' could not be created.\n\n"
940 "Make sure you have write permissions and try again." ),
941 newFileName.GetPath() );
942
943 wxMessageDialog dlgBadPath( this, msg, _( "Error" ),
944 wxOK | wxICON_EXCLAMATION | wxCENTER );
945
946 dlgBadPath.ShowModal();
947 return false;
948 }
949
950 if( newProjectHook.IsAttachedToDialog() )
951 createNewProject = newProjectHook.GetCreateNewProject();
952
953 if( !saveCopy )
954 {
955 Schematic().Root().SetFileName( newFileName.GetFullName() );
956 Schematic().RootScreen()->SetFileName( newFileName.GetFullPath() );
957 updateFileHistory = true;
958 }
959 else
960 {
961 filenameMap[Schematic().RootScreen()] = newFileName.GetFullPath();
962 }
963
964 // Set the base path to all new sheets.
965 for( size_t i = 0; i < screens.GetCount(); i++ )
966 {
967 screen = screens.GetScreen( i );
968
969 wxCHECK2( screen, continue );
970
971 // The root screen file name has already been set.
972 if( screen == Schematic().RootScreen() )
973 continue;
974
975 wxFileName tmp = screen->GetFileName();
976
977 // Assume existing sheet files are being reused and do not save them to the new
978 // path. Maybe in the future, add a user option to copy schematic files to the
979 // new project path.
980 if( tmp.FileExists() )
981 continue;
982
983 if( tmp.GetPath().IsEmpty() )
984 {
985 tmp.SetPath( newFileName.GetPath() );
986 }
987 else if( tmp.GetPath() == fn.GetPath() )
988 {
989 tmp.SetPath( newFileName.GetPath() );
990 }
991 else if( tmp.GetPath().StartsWith( fn.GetPath() ) )
992 {
993 // NOTE: this hasn't been tested because the sheet properties dialog no longer
994 // allows adding a path specifier in the file name field.
995 wxString newPath = newFileName.GetPath();
996 newPath += tmp.GetPath().Right( fn.GetPath().Length() );
997 tmp.SetPath( newPath );
998 }
999
1000 wxLogTrace( tracePathsAndFiles,
1001 wxS( "Moving schematic from '%s' to '%s'." ),
1002 screen->GetFileName(),
1003 tmp.GetFullPath() );
1004
1005 if( !tmp.DirExists() && !tmp.Mkdir() )
1006 {
1007 msg.Printf( _( "Folder '%s' could not be created.\n\n"
1008 "Make sure you have write permissions and try again." ),
1009 newFileName.GetPath() );
1010
1011 wxMessageDialog dlgBadFilePath( this, msg, _( "Error" ),
1012 wxOK | wxICON_EXCLAMATION | wxCENTER );
1013
1014 dlgBadFilePath.ShowModal();
1015 return false;
1016 }
1017
1018 if( saveCopy )
1019 filenameMap[screen] = tmp.GetFullPath();
1020 else
1021 screen->SetFileName( tmp.GetFullPath() );
1022 }
1023
1024 // Attempt to make sheet file name paths relative to the new root schematic path.
1025 for( SCH_SHEET_PATH& sheet : Schematic().Hierarchy() )
1026 {
1027 if( !sheet.Last()->IsRootSheet() )
1028 sheet.MakeFilePathRelativeToParentSheet();
1029 }
1030 }
1031 else if( !fn.FileExists() )
1032 {
1033 // File doesn't exist yet; true if we just imported something
1034 updateFileHistory = true;
1035 }
1036 else if( !IsContentModified() )
1037 {
1038 return true;
1039 }
1040
1041 if( filenameMap.empty() || !saveCopy )
1042 {
1043 for( size_t i = 0; i < screens.GetCount(); i++ )
1044 filenameMap[screens.GetScreen( i )] = screens.GetScreen( i )->GetFileName();
1045 }
1046
1047 // Warn user on potential file overwrite. This can happen on shared sheets.
1048 wxArrayString overwrittenFiles;
1049 wxArrayString lockedFiles;
1050
1051 for( size_t i = 0; i < screens.GetCount(); i++ )
1052 {
1053 screen = screens.GetScreen( i );
1054
1055 wxCHECK2( screen, continue );
1056
1057 // Convert legacy schematics file name extensions for the new format.
1058 wxFileName tmpFn = filenameMap[screen];
1059
1060 if( !tmpFn.IsOk() )
1061 continue;
1062
1063 if( tmpFn.FileExists() && !tmpFn.IsFileWritable() )
1064 lockedFiles.Add( tmpFn.GetFullPath() );
1065
1066 if( tmpFn.GetExt() == FILEEXT::KiCadSchematicFileExtension )
1067 continue;
1068
1070
1071 if( tmpFn.FileExists() )
1072 overwrittenFiles.Add( tmpFn.GetFullPath() );
1073 }
1074
1075 if( !lockedFiles.IsEmpty() )
1076 {
1077 for( const wxString& lockedFile : lockedFiles )
1078 {
1079 if( msg.IsEmpty() )
1080 msg = lockedFile;
1081 else
1082 msg += "\n" + lockedFile;
1083 }
1084
1085 wxRichMessageDialog dlg( this, wxString::Format( _( "Failed to save %s." ),
1086 Schematic().Root().GetFileName() ),
1087 _( "Locked File Warning" ),
1088 wxOK | wxICON_WARNING | wxCENTER );
1089 dlg.SetExtendedMessage( _( "You do not have write permissions to:\n\n" ) + msg );
1090
1091 dlg.ShowModal();
1092 return false;
1093 }
1094
1095 if( !overwrittenFiles.IsEmpty() )
1096 {
1097 for( const wxString& overwrittenFile : overwrittenFiles )
1098 {
1099 if( msg.IsEmpty() )
1100 msg = overwrittenFile;
1101 else
1102 msg += "\n" + overwrittenFile;
1103 }
1104
1105 wxRichMessageDialog dlg( this, _( "Saving will overwrite existing files." ),
1106 _( "Save Warning" ),
1107 wxOK | wxCANCEL | wxCANCEL_DEFAULT | wxCENTER |
1108 wxICON_EXCLAMATION );
1109 dlg.ShowDetailedText( _( "The following files will be overwritten:\n\n" ) + msg );
1110 dlg.SetOKCancelLabels( wxMessageDialog::ButtonLabel( _( "Overwrite Files" ) ),
1111 wxMessageDialog::ButtonLabel( _( "Abort Project Save" ) ) );
1112
1113 if( dlg.ShowModal() == wxID_CANCEL )
1114 return false;
1115 }
1116
1117 screens.BuildClientSheetPathList();
1118
1119 for( size_t i = 0; i < screens.GetCount(); i++ )
1120 {
1121 screen = screens.GetScreen( i );
1122
1123 wxCHECK2( screen, continue );
1124
1125 // Convert legacy schematics file name extensions for the new format.
1126 wxFileName tmpFn = filenameMap[screen];
1127
1128 if( tmpFn.IsOk() && tmpFn.GetExt() != FILEEXT::KiCadSchematicFileExtension )
1129 {
1130 updateFileHistory = true;
1132
1133 for( EDA_ITEM* item : screen->Items().OfType( SCH_SHEET_T ) )
1134 {
1135 SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
1136 wxFileName sheetFileName = sheet->GetFileName();
1137
1138 if( !sheetFileName.IsOk()
1139 || sheetFileName.GetExt() == FILEEXT::KiCadSchematicFileExtension )
1140 continue;
1141
1142 sheetFileName.SetExt( FILEEXT::KiCadSchematicFileExtension );
1143 sheet->SetFileName( sheetFileName.GetFullPath() );
1144 UpdateItem( sheet );
1145 }
1146
1147 filenameMap[screen] = tmpFn.GetFullPath();
1148
1149 if( !saveCopy )
1150 screen->SetFileName( tmpFn.GetFullPath() );
1151 }
1152
1153 // Do not save sheet symbols with no valid filename set
1154 if( !tmpFn.IsOk() )
1155 continue;
1156
1157 std::vector<SCH_SHEET_PATH>& sheets = screen->GetClientSheetPaths();
1158
1159 if( sheets.size() == 1 )
1160 screen->SetVirtualPageNumber( 1 );
1161 else
1162 screen->SetVirtualPageNumber( 0 ); // multiple uses; no way to store the real sheet #
1163
1164 // This is a new schematic file so make sure it has a unique ID.
1165 if( !saveCopy && tmpFn.GetFullPath() != screen->GetFileName() )
1166 screen->AssignNewUuid();
1167
1168 success &= saveSchematicFile( screens.GetSheet( i ), tmpFn.GetFullPath() );
1169 }
1170
1171 if( success )
1172 m_autoSaveRequired = false;
1173
1174 // One or more of the modified sheets did not save correctly so update the auto save file.
1175 if( !aSaveAs && !success )
1176 success &= updateAutoSaveFile();
1177
1178 if( aSaveAs && success )
1179 LockFile( Schematic().RootScreen()->GetFileName() );
1180
1181 if( updateFileHistory )
1182 UpdateFileHistory( Schematic().RootScreen()->GetFileName() );
1183
1184 // Save the sheet name map to the project file
1185 std::vector<FILE_INFO_PAIR>& sheets = Prj().GetProjectFile().GetSheets();
1186 sheets.clear();
1187
1188 for( SCH_SHEET_PATH& sheetPath : Schematic().Hierarchy() )
1189 {
1190 SCH_SHEET* sheet = sheetPath.Last();
1191
1192 wxCHECK2( sheet, continue );
1193
1194 // Use the schematic UUID for the root sheet.
1195 if( sheet->IsRootSheet() )
1196 {
1197 screen = sheet->GetScreen();
1198
1199 wxCHECK2( screen, continue );
1200
1201 // For the root sheet we use the canonical name ( "Root" ) because its name
1202 // cannot be modified by the user
1203 sheets.emplace_back( std::make_pair( screen->GetUuid(), wxT( "Root" ) ) );
1204 }
1205 else
1206 {
1207 sheets.emplace_back( std::make_pair( sheet->m_Uuid, sheet->GetName() ) );
1208 }
1209 }
1210
1211 wxASSERT( filenameMap.count( Schematic().RootScreen() ) );
1212 wxFileName projectPath( filenameMap.at( Schematic().RootScreen() ) );
1213 projectPath.SetExt( FILEEXT::ProjectFileExtension );
1214
1215 if( Prj().IsNullProject() || ( aSaveAs && !saveCopy ) )
1216 {
1217 Prj().SetReadOnly( !createNewProject );
1218 GetSettingsManager()->SaveProjectAs( projectPath.GetFullPath() );
1219 }
1220 else if( saveCopy && createNewProject )
1221 {
1222 GetSettingsManager()->SaveProjectCopy( projectPath.GetFullPath() );
1223 }
1224 else
1225 {
1228 }
1229
1230 if( !Kiface().IsSingle() )
1231 {
1232 WX_STRING_REPORTER backupReporter;
1233
1234 if( !GetSettingsManager()->TriggerBackupIfNeeded( backupReporter ) )
1235 SetStatusText( backupReporter.GetMessages(), 0 );
1236 }
1237
1238 updateTitle();
1239
1241 m_infoBar->Dismiss();
1242
1243 return success;
1244}
1245
1246
1248{
1249 wxFileName tmpFileName = Schematic().Root().GetFileName();
1250 wxFileName fn = tmpFileName;
1251 wxFileName tmp;
1252 SCH_SCREENS screens( Schematic().Root() );
1253
1254 // Don't run autosave if content has not been modified
1255 if( !IsContentModified() )
1256 return true;
1257
1258 bool autoSaveOk = true;
1259
1260 if( fn.GetPath().IsEmpty() )
1261 tmp.AssignDir( Prj().GetProjectPath() );
1262 else
1263 tmp.AssignDir( fn.GetPath() );
1264
1265 if( !tmp.IsOk() )
1266 return false;
1267
1268 if( !IsWritable( tmp ) )
1269 return false;
1270
1271 wxString title = GetTitle(); // Save frame title, that can be modified by the save process
1272
1273 for( size_t i = 0; i < screens.GetCount(); i++ )
1274 {
1275 // Only create auto save files for the schematics that have been modified.
1276 if( !screens.GetScreen( i )->IsContentModified() )
1277 continue;
1278
1279 tmpFileName = fn = screens.GetScreen( i )->GetFileName();
1280
1281 // Auto save file name is the normal file name prefixed with GetAutoSavePrefix().
1282 fn.SetName( FILEEXT::AutoSaveFilePrefix + fn.GetName() );
1283
1284 if( saveSchematicFile( screens.GetSheet( i ), fn.GetFullPath() ) )
1285 {
1286 // This was only an auto-save, not a real save. Reset the modified flag.
1287 screens.GetScreen( i )->SetContentModified();
1288 }
1289 else
1290 {
1291 autoSaveOk = false;
1292 }
1293 }
1294
1295 if( autoSaveOk && updateAutoSaveFile() )
1296 {
1297 m_autoSaveRequired = false;
1298 m_autoSavePending = false;
1299
1300 if( !Kiface().IsSingle()
1301 && GetSettingsManager()->GetCommonSettings()->m_Backup.backup_on_autosave )
1302 {
1304 }
1305 }
1306
1307 SetTitle( title );
1308
1309 return autoSaveOk;
1310}
1311
1312
1313bool SCH_EDIT_FRAME::importFile( const wxString& aFileName, int aFileType,
1314 const std::map<std::string, UTF8>* aProperties )
1315{
1316 wxFileName filename( aFileName );
1317 wxFileName newfilename;
1318 SCH_IO_MGR::SCH_FILE_T fileType = (SCH_IO_MGR::SCH_FILE_T) aFileType;
1319
1320 wxCommandEvent changingEvt( EDA_EVT_SCHEMATIC_CHANGING );
1321 ProcessEventLocally( changingEvt );
1322
1323 switch( fileType )
1324 {
1325 case SCH_IO_MGR::SCH_ALTIUM:
1326 case SCH_IO_MGR::SCH_CADSTAR_ARCHIVE:
1327 case SCH_IO_MGR::SCH_EAGLE:
1328 case SCH_IO_MGR::SCH_LTSPICE:
1329 case SCH_IO_MGR::SCH_EASYEDA:
1330 case SCH_IO_MGR::SCH_EASYEDAPRO:
1331 {
1332 // We insist on caller sending us an absolute path, if it does not, we say it's a bug.
1333 wxCHECK_MSG( filename.IsAbsolute(), false,
1334 wxS( "Import schematic: path is not absolute!" ) );
1335
1336 try
1337 {
1338 IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( fileType ) );
1339 DIALOG_HTML_REPORTER errorReporter( this );
1340 WX_PROGRESS_REPORTER progressReporter( this, _( "Importing Schematic" ), 1 );
1341
1342 if( PROJECT_CHOOSER_PLUGIN* c_pi = dynamic_cast<PROJECT_CHOOSER_PLUGIN*>( pi.get() ) )
1343 {
1344 c_pi->RegisterCallback( std::bind( DIALOG_IMPORT_CHOOSE_PROJECT::RunModal,
1345 this, std::placeholders::_1 ) );
1346 }
1347
1348 if( eeconfig()->m_System.show_import_issues )
1349 pi->SetReporter( errorReporter.m_Reporter );
1350 else
1351 pi->SetReporter( &NULL_REPORTER::GetInstance() );
1352
1353 pi->SetProgressReporter( &progressReporter );
1354
1355 SCH_SHEET* loadedSheet = pi->LoadSchematicFile( aFileName, &Schematic(), nullptr,
1356 aProperties );
1357
1358 if( loadedSheet )
1359 {
1360 Schematic().SetRoot( loadedSheet );
1361
1362 if( errorReporter.m_Reporter->HasMessage() )
1363 {
1364 errorReporter.m_Reporter->Flush(); // Build HTML messages
1365 errorReporter.ShowModal();
1366 }
1367
1368 // Non-KiCad schematics do not use a drawing-sheet (or if they do, it works
1369 // differently to KiCad), so set it to an empty one.
1371 drawingSheet.SetEmptyLayout();
1372 BASE_SCREEN::m_DrawingSheetFileName = "empty.kicad_wks";
1373
1374 newfilename.SetPath( Prj().GetProjectPath() );
1375 newfilename.SetName( Prj().GetProjectName() );
1376 newfilename.SetExt( FILEEXT::KiCadSchematicFileExtension );
1377
1378 SetScreen( GetCurrentSheet().LastScreen() );
1379
1380 Schematic().Root().SetFileName( newfilename.GetFullName() );
1381 GetScreen()->SetFileName( newfilename.GetFullPath() );
1383
1385
1386 // Only perform the dangling end test on root sheet.
1388 }
1389 else
1390 {
1391 CreateScreens();
1392 }
1393 }
1394 catch( const IO_ERROR& ioe )
1395 {
1396 // Do not leave g_RootSheet == NULL because it is expected to be
1397 // a valid sheet. Therefore create a dummy empty root sheet and screen.
1398 CreateScreens();
1400
1401 wxString msg = wxString::Format( _( "Error loading schematic '%s'." ), aFileName );
1402 DisplayErrorMessage( this, msg, ioe.What() );
1403
1404 msg.Printf( _( "Failed to load '%s'." ), aFileName );
1405 SetMsgPanel( wxEmptyString, msg );
1406 }
1407 catch( const std::exception& exc )
1408 {
1409 CreateScreens();
1411
1412 wxString msg = wxString::Format( _( "Unhandled exception occurred loading schematic "
1413 "'%s'." ), aFileName );
1414 DisplayErrorMessage( this, msg, exc.what() );
1415
1416 msg.Printf( _( "Failed to load '%s'." ), aFileName );
1417 SetMsgPanel( wxEmptyString, msg );
1418 }
1419
1422
1425 SyncView();
1426
1428
1429 wxCommandEvent e( EDA_EVT_SCHEMATIC_CHANGED );
1430 ProcessEventLocally( e );
1431
1432 for( wxEvtHandler* listener : m_schematicChangeListeners )
1433 {
1434 wxCHECK2( listener, continue );
1435
1436 // Use the windows variant when handling event messages in case there is any
1437 // special event handler pre and/or post processing specific to windows.
1438 wxWindow* win = dynamic_cast<wxWindow*>( listener );
1439
1440 if( win )
1441 win->HandleWindowEvent( e );
1442 else
1443 listener->SafelyProcessEvent( e );
1444 }
1445
1446 updateTitle();
1447 break;
1448 }
1449
1450 default:
1451 break;
1452 }
1453
1454 return true;
1455}
1456
1457
1459{
1460 SCH_SCREENS screenList( Schematic().Root() );
1461
1462 // Save any currently open and modified project files.
1463 for( SCH_SCREEN* screen = screenList.GetFirst(); screen; screen = screenList.GetNext() )
1464 {
1465 SIMULATOR_FRAME* simFrame = (SIMULATOR_FRAME*) Kiway().Player( FRAME_SIMULATOR, false );
1466
1467 // Simulator must be closed before loading another schematic, otherwise it may crash.
1468 // If there are any changes in the simulator the user will be prompted to save them.
1469 if( simFrame && !simFrame->Close() )
1470 return false;
1471
1472 if( screen->IsContentModified() )
1473 {
1474 if( !HandleUnsavedChanges( this, _( "The current schematic has been modified. "
1475 "Save changes?" ),
1476 [&]() -> bool
1477 {
1478 return SaveProject();
1479 } ) )
1480 {
1481 return false;
1482 }
1483 }
1484 }
1485
1486 return true;
1487}
1488
1489
1491{
1492 wxFileName tmpFn = Prj().GetProjectFullName();
1493 wxFileName autoSaveFileName( tmpFn.GetPath(), getAutoSaveFileName() );
1494
1495 wxLogTrace( traceAutoSave, "Creating auto save file %s", autoSaveFileName.GetFullPath() );
1496
1497 wxCHECK( autoSaveFileName.IsDirWritable(), false );
1498
1499 wxFileName fn;
1500 SCH_SCREENS screens( Schematic().Root() );
1501 std::vector< wxString > autoSavedFiles;
1502
1503 for( size_t i = 0; i < screens.GetCount(); i++ )
1504 {
1505 // Only create auto save files for the schematics that have been modified.
1506 if( !screens.GetScreen( i )->IsContentModified() )
1507 continue;
1508
1509 fn = screens.GetScreen( i )->GetFileName();
1510
1511 // Auto save file name is the normal file name prefixed with GetAutoSavePrefix().
1512 fn.SetName( FILEEXT::AutoSaveFilePrefix + fn.GetName() );
1513 autoSavedFiles.emplace_back( fn.GetFullPath() );
1514 }
1515
1516 wxTextFile autoSaveFile( autoSaveFileName.GetFullPath() );
1517
1518 if( autoSaveFileName.FileExists() && !wxRemoveFile( autoSaveFileName.GetFullPath() ) )
1519 {
1520 wxLogTrace( traceAutoSave, "Error removing auto save file %s",
1521 autoSaveFileName.GetFullPath() );
1522
1523 return false;
1524 }
1525
1526 // No modified sheet files to save.
1527 if( autoSavedFiles.empty() )
1528 return true;
1529
1530 if( !autoSaveFile.Create() )
1531 return false;
1532
1533 for( const wxString& fileName : autoSavedFiles )
1534 {
1535 wxLogTrace( traceAutoSave, "Adding auto save file %s to %s",
1536 fileName, autoSaveFileName.GetName() );
1537 autoSaveFile.AddLine( fileName );
1538 }
1539
1540 if( !autoSaveFile.Write() )
1541 return false;
1542
1543 wxLogTrace( traceAutoSave, "Auto save file '%s' written", autoSaveFileName.GetFullName() );
1544
1545 return true;
1546}
1547
1548
1549void removeFile( const wxString& aFilename, wxArrayString& aUnremoved )
1550{
1551 wxLogTrace( traceAutoSave, wxS( "Removing auto save file " ) + aFilename );
1552
1553 if( wxFileExists( aFilename ) && !wxRemoveFile( aFilename ) )
1554 aUnremoved.Add( aFilename );
1555};
1556
1557
1558void SCH_EDIT_FRAME::CheckForAutoSaveFile( const wxFileName& aFileName )
1559{
1560 if( !Pgm().IsGUI() )
1561 return;
1562
1563 wxCHECK_RET( aFileName.IsOk(), wxS( "Invalid file name!" ) );
1564
1565 wxLogTrace( traceAutoSave,
1566 wxS( "Checking for auto save file " ) + aFileName.GetFullPath() );
1567
1568 if( !aFileName.FileExists() )
1569 return;
1570
1571 wxString msg = _(
1572 "Well this is potentially embarrassing!\n"
1573 "It appears that the last time you were editing one or more of the schematic files\n"
1574 "were not saved properly. Do you wish to restore the last saved edits you made?" );
1575
1576 int response = wxMessageBox( msg, Pgm().App().GetAppDisplayName(), wxYES_NO | wxICON_QUESTION,
1577 this );
1578
1579 wxTextFile fileList( aFileName.GetFullPath() );
1580
1581 if( !fileList.Open() )
1582 {
1583 msg.Printf( _( "The file '%s' could not be opened.\n"
1584 "Manual recovery of automatically saved files is required." ),
1585 aFileName.GetFullPath() );
1586
1587 wxMessageBox( msg, Pgm().App().GetAppDisplayName(), wxOK | wxICON_EXCLAMATION, this );
1588 return;
1589 }
1590
1591 if( response == wxYES )
1592 {
1593 wxArrayString unrecoveredFiles;
1594
1595 for( wxString fn = fileList.GetFirstLine(); !fileList.Eof(); fn = fileList.GetNextLine() )
1596 {
1597 wxFileName recoveredFn = fn;
1598 wxString tmp = recoveredFn.GetName();
1599
1600 // Strip "_autosave-" prefix from the auto save file name.
1601 tmp.Replace( FILEEXT::AutoSaveFilePrefix, wxS( "" ), false );
1602 recoveredFn.SetName( tmp );
1603
1604 wxFileName backupFn = recoveredFn;
1605
1606 backupFn.SetExt( backupFn.GetExt() + FILEEXT::BackupFileSuffix );
1607
1608 wxLogTrace( traceAutoSave, wxS( "Recovering auto save file:\n"
1609 " Original file: '%s'\n"
1610 " Backup file: '%s'\n"
1611 " Auto save file: '%s'" ),
1612 recoveredFn.GetFullPath(), backupFn.GetFullPath(), fn );
1613
1614 if( !wxFileExists( fn ) )
1615 {
1616 unrecoveredFiles.Add( recoveredFn.GetFullPath() );
1617 }
1618 // Attempt to back up the last schematic file before overwriting it with the auto
1619 // save file.
1620 else if( recoveredFn.Exists()
1621 && !wxCopyFile( recoveredFn.GetFullPath(), backupFn.GetFullPath() ) )
1622 {
1623 unrecoveredFiles.Add( recoveredFn.GetFullPath() );
1624 }
1625 // Attempt to replace last saved file with auto save file
1626 else if( !wxRenameFile( fn, recoveredFn.GetFullPath() ) )
1627 {
1628 unrecoveredFiles.Add( recoveredFn.GetFullPath() );
1629 }
1630 }
1631
1632 if( !unrecoveredFiles.IsEmpty() )
1633 {
1634 msg = _( "The following automatically saved file(s) could not be restored\n" );
1635
1636 for( size_t i = 0; i < unrecoveredFiles.GetCount(); i++ )
1637 msg += unrecoveredFiles[i] + wxS( "\n" );
1638
1639 msg += _( "Manual recovery will be required to restore the file(s) above." );
1640 wxMessageBox( msg, Pgm().App().GetAppDisplayName(), wxOK | wxICON_EXCLAMATION,
1641 this );
1642 }
1643
1644 wxArrayString unremovedFiles;
1645 removeFile( aFileName.GetFullPath(), unremovedFiles );
1646
1647 if( !unremovedFiles.IsEmpty() )
1648 {
1649 msg.Printf( _( "The autosave file '%s' could not be removed.\n"
1650 "Manual removal will be required." ),
1651 unremovedFiles[0] );
1652
1653 wxMessageBox( msg, Pgm().App().GetAppDisplayName(), wxOK | wxICON_EXCLAMATION, this );
1654 }
1655 }
1656 else
1657 {
1658 DeleteAutoSaveFile( aFileName );
1659 }
1660}
1661
1662
1663void SCH_EDIT_FRAME::DeleteAutoSaveFile( const wxFileName& aFileName )
1664{
1665 if( !Pgm().IsGUI() )
1666 return;
1667
1668 wxCHECK_RET( aFileName.IsOk(), wxS( "Invalid file name!" ) );
1669
1670 if( !aFileName.FileExists() )
1671 return;
1672
1673 wxTextFile fileList( aFileName.GetFullPath() );
1674 wxArrayString unremovedFiles;
1675
1676 for( wxString fn = fileList.GetFirstLine(); !fileList.Eof(); fn = fileList.GetNextLine() )
1677 removeFile( fn, unremovedFiles );
1678
1679 removeFile( aFileName.GetFullPath(), unremovedFiles );
1680
1681 if( !unremovedFiles.IsEmpty() )
1682 {
1683 wxString msg = _( "The following automatically saved file(s) could not be removed\n" );
1684
1685 for( size_t i = 0; i < unremovedFiles.GetCount(); i++ )
1686 msg += unremovedFiles[i] + wxS( "\n" );
1687
1688 msg += _( "Manual removal will be required for the file(s) above." );
1689 wxMessageBox( msg, Pgm().App().GetAppDisplayName(), wxOK | wxICON_EXCLAMATION, this );
1690 }
1691}
1692
1693
1695{
1696 static wxString autoSaveFileName( wxS( "#auto_saved_files#" ) );
1697
1698 return autoSaveFileName;
1699}
KIFACE_BASE & Kiface()
Global KIFACE_BASE "get" accessor.
static TOOL_ACTION zoomFitScreen
Definition: actions.h:134
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
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()
int ShowModal() override
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
EE_TYPE OfType(KICAD_T aType) const
Definition: sch_rtree.h:238
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:115
static wxString GetDefaultUserProjectsPath()
Gets the default path we point users to create projects.
Definition: paths.cpp:140
void HideSplash()
Definition: pgm_base.cpp:446
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:93
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:164
virtual const wxString GetProjectFullName() const
Return the full path and name of the project.
Definition: project.cpp:129
virtual void SetElem(PROJECT::ELEM aIndex, _ELEM *aElem)
Definition: project.cpp:348
virtual PROJECT_FILE & GetProjectFile() const
Definition: project.h:200
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:359
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:841
CONNECTION_GRAPH * ConnectionGraph() const override
Definition: schematic.h:166
void FixupJunctions()
Add junctions to this schematic where required.
Definition: schematic.cpp:738
SCH_SHEET_LIST Hierarchy() const override
Return the full schematic flattened hierarchical sheet list.
Definition: schematic.cpp:214
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:208
SCH_SHEET & Root() const
Definition: schematic.h:125
SCH_DRAW_PANEL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
void SyncView()
Mark all items for refresh.
EESCHEMA_SETTINGS * eeconfig() const
Class for a bus to bus entry.
VECTOR2I GetPosition() const override
VECTOR2I GetEnd() const
void DisplaySheet(SCH_SCREEN *aScreen)
Handle actions specific to the schematic editor.
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.
void UpdateHierarchyNavigator(bool aRefreshNetNavigator=true)
Update the hierarchy navigation tree and history.
std::vector< wxEvtHandler * > m_schematicChangeListeners
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 ...
bool importFile(const wxString &aFileName, int aFileType, const std::map< std::string, UTF8 > *aProperties=nullptr)
Load the given filename but sets the path to the current project path.
void LoadDrawingSheet()
Load the drawing sheet file.
virtual void DeleteAutoSaveFile(const wxFileName &aFileName) override
void SetSheetNumberAndCount()
Set the m_ScreenNumber and m_NumberOfScreens members for screens.
void ClearRepeatItemsList()
Clear the list of items which are to be repeated with the insert key.
void 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)
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:712
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
bool HasSymbolFieldNamesWithWhiteSpace() const
size_t GetCount() const
Definition: sch_screen.h:717
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:118
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.
void CheckForMissingSymbolInstances(const wxString &aProjectName)
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
void UpdateAllScreenReferences() const
Update all the symbol references for this sheet path.
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition: sch_sheet.h: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:205
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
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 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 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
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 QueueShowMessage(const wxString &aMessage, int aFlags=wxICON_INFORMATION)
Send the infobar an event telling it to show a message.
Definition: wx_infobar.cpp:121
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:101
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:171
const wxString & GetMessages() const
Definition: reporter.cpp:84
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:422
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)
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:597
#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:357
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:1060
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:158
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:43
std::vector< std::string > m_FileExtensions
Filter used for file pickers if m_IsFile is true.
Definition: io_base.h:45
bool m_CanRead
Whether the IO can read this file type.
Definition: io_base.h:48
wxString FileFilter() const
Definition: io_base.cpp:40
Definition for symbol library class.
wxLogTrace helper definitions.
@ 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.