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 sheets.emplace_back( std::make_pair( screen->GetUuid(), sheet->GetName() ) );
1202 }
1203 else
1204 {
1205 sheets.emplace_back( std::make_pair( sheet->m_Uuid, sheet->GetName() ) );
1206 }
1207 }
1208
1209 wxASSERT( filenameMap.count( Schematic().RootScreen() ) );
1210 wxFileName projectPath( filenameMap.at( Schematic().RootScreen() ) );
1211 projectPath.SetExt( FILEEXT::ProjectFileExtension );
1212
1213 if( Prj().IsNullProject() || ( aSaveAs && !saveCopy ) )
1214 {
1215 Prj().SetReadOnly( !createNewProject );
1216 GetSettingsManager()->SaveProjectAs( projectPath.GetFullPath() );
1217 }
1218 else if( saveCopy && createNewProject )
1219 {
1220 GetSettingsManager()->SaveProjectCopy( projectPath.GetFullPath() );
1221 }
1222 else
1223 {
1226 }
1227
1228 if( !Kiface().IsSingle() )
1229 {
1230 WX_STRING_REPORTER backupReporter;
1231
1232 if( !GetSettingsManager()->TriggerBackupIfNeeded( backupReporter ) )
1233 SetStatusText( backupReporter.GetMessages(), 0 );
1234 }
1235
1236 updateTitle();
1237
1239 m_infoBar->Dismiss();
1240
1241 return success;
1242}
1243
1244
1246{
1247 wxFileName tmpFileName = Schematic().Root().GetFileName();
1248 wxFileName fn = tmpFileName;
1249 wxFileName tmp;
1250 SCH_SCREENS screens( Schematic().Root() );
1251
1252 // Don't run autosave if content has not been modified
1253 if( !IsContentModified() )
1254 return true;
1255
1256 bool autoSaveOk = true;
1257
1258 if( fn.GetPath().IsEmpty() )
1259 tmp.AssignDir( Prj().GetProjectPath() );
1260 else
1261 tmp.AssignDir( fn.GetPath() );
1262
1263 if( !tmp.IsOk() )
1264 return false;
1265
1266 if( !IsWritable( tmp ) )
1267 return false;
1268
1269 wxString title = GetTitle(); // Save frame title, that can be modified by the save process
1270
1271 for( size_t i = 0; i < screens.GetCount(); i++ )
1272 {
1273 // Only create auto save files for the schematics that have been modified.
1274 if( !screens.GetScreen( i )->IsContentModified() )
1275 continue;
1276
1277 tmpFileName = fn = screens.GetScreen( i )->GetFileName();
1278
1279 // Auto save file name is the normal file name prefixed with GetAutoSavePrefix().
1280 fn.SetName( FILEEXT::AutoSaveFilePrefix + fn.GetName() );
1281
1282 if( saveSchematicFile( screens.GetSheet( i ), fn.GetFullPath() ) )
1283 {
1284 // This was only an auto-save, not a real save. Reset the modified flag.
1285 screens.GetScreen( i )->SetContentModified();
1286 }
1287 else
1288 {
1289 autoSaveOk = false;
1290 }
1291 }
1292
1293 if( autoSaveOk && updateAutoSaveFile() )
1294 {
1295 m_autoSaveRequired = false;
1296 m_autoSavePending = false;
1297
1298 if( !Kiface().IsSingle()
1299 && GetSettingsManager()->GetCommonSettings()->m_Backup.backup_on_autosave )
1300 {
1302 }
1303 }
1304
1305 SetTitle( title );
1306
1307 return autoSaveOk;
1308}
1309
1310
1311bool SCH_EDIT_FRAME::importFile( const wxString& aFileName, int aFileType,
1312 const std::map<std::string, UTF8>* aProperties )
1313{
1314 wxFileName filename( aFileName );
1315 wxFileName newfilename;
1316 SCH_IO_MGR::SCH_FILE_T fileType = (SCH_IO_MGR::SCH_FILE_T) aFileType;
1317
1318 wxCommandEvent changingEvt( EDA_EVT_SCHEMATIC_CHANGING );
1319 ProcessEventLocally( changingEvt );
1320
1321 switch( fileType )
1322 {
1323 case SCH_IO_MGR::SCH_ALTIUM:
1324 case SCH_IO_MGR::SCH_CADSTAR_ARCHIVE:
1325 case SCH_IO_MGR::SCH_EAGLE:
1326 case SCH_IO_MGR::SCH_LTSPICE:
1327 case SCH_IO_MGR::SCH_EASYEDA:
1328 case SCH_IO_MGR::SCH_EASYEDAPRO:
1329 {
1330 // We insist on caller sending us an absolute path, if it does not, we say it's a bug.
1331 wxCHECK_MSG( filename.IsAbsolute(), false,
1332 wxS( "Import schematic: path is not absolute!" ) );
1333
1334 try
1335 {
1336 IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( fileType ) );
1337 DIALOG_HTML_REPORTER errorReporter( this );
1338 WX_PROGRESS_REPORTER progressReporter( this, _( "Importing Schematic" ), 1 );
1339
1340 if( PROJECT_CHOOSER_PLUGIN* c_pi = dynamic_cast<PROJECT_CHOOSER_PLUGIN*>( pi.get() ) )
1341 {
1342 c_pi->RegisterCallback( std::bind( DIALOG_IMPORT_CHOOSE_PROJECT::RunModal,
1343 this, std::placeholders::_1 ) );
1344 }
1345
1346 if( eeconfig()->m_System.show_import_issues )
1347 pi->SetReporter( errorReporter.m_Reporter );
1348 else
1349 pi->SetReporter( &NULL_REPORTER::GetInstance() );
1350
1351 pi->SetProgressReporter( &progressReporter );
1352
1353 SCH_SHEET* loadedSheet = pi->LoadSchematicFile( aFileName, &Schematic(), nullptr,
1354 aProperties );
1355
1356 if( loadedSheet )
1357 {
1358 Schematic().SetRoot( loadedSheet );
1359
1360 if( errorReporter.m_Reporter->HasMessage() )
1361 {
1362 errorReporter.m_Reporter->Flush(); // Build HTML messages
1363 errorReporter.ShowModal();
1364 }
1365
1366 // Non-KiCad schematics do not use a drawing-sheet (or if they do, it works
1367 // differently to KiCad), so set it to an empty one.
1369 drawingSheet.SetEmptyLayout();
1370 BASE_SCREEN::m_DrawingSheetFileName = "empty.kicad_wks";
1371
1372 newfilename.SetPath( Prj().GetProjectPath() );
1373 newfilename.SetName( Prj().GetProjectName() );
1374 newfilename.SetExt( FILEEXT::KiCadSchematicFileExtension );
1375
1376 SetScreen( GetCurrentSheet().LastScreen() );
1377
1378 Schematic().Root().SetFileName( newfilename.GetFullName() );
1379 GetScreen()->SetFileName( newfilename.GetFullPath() );
1381
1383
1384 // Only perform the dangling end test on root sheet.
1386 }
1387 else
1388 {
1389 CreateScreens();
1390 }
1391 }
1392 catch( const IO_ERROR& ioe )
1393 {
1394 // Do not leave g_RootSheet == NULL because it is expected to be
1395 // a valid sheet. Therefore create a dummy empty root sheet and screen.
1396 CreateScreens();
1398
1399 wxString msg = wxString::Format( _( "Error loading schematic '%s'." ), aFileName );
1400 DisplayErrorMessage( this, msg, ioe.What() );
1401
1402 msg.Printf( _( "Failed to load '%s'." ), aFileName );
1403 SetMsgPanel( wxEmptyString, msg );
1404 }
1405 catch( const std::exception& exc )
1406 {
1407 CreateScreens();
1409
1410 wxString msg = wxString::Format( _( "Unhandled exception occurred loading schematic "
1411 "'%s'." ), aFileName );
1412 DisplayErrorMessage( this, msg, exc.what() );
1413
1414 msg.Printf( _( "Failed to load '%s'." ), aFileName );
1415 SetMsgPanel( wxEmptyString, msg );
1416 }
1417
1420
1423 SyncView();
1424
1426
1427 wxCommandEvent e( EDA_EVT_SCHEMATIC_CHANGED );
1428 ProcessEventLocally( e );
1429
1430 for( wxEvtHandler* listener : m_schematicChangeListeners )
1431 {
1432 wxCHECK2( listener, continue );
1433
1434 // Use the windows variant when handling event messages in case there is any
1435 // special event handler pre and/or post processing specific to windows.
1436 wxWindow* win = dynamic_cast<wxWindow*>( listener );
1437
1438 if( win )
1439 win->HandleWindowEvent( e );
1440 else
1441 listener->SafelyProcessEvent( e );
1442 }
1443
1444 updateTitle();
1445 break;
1446 }
1447
1448 default:
1449 break;
1450 }
1451
1452 return true;
1453}
1454
1455
1457{
1458 SCH_SCREENS screenList( Schematic().Root() );
1459
1460 // Save any currently open and modified project files.
1461 for( SCH_SCREEN* screen = screenList.GetFirst(); screen; screen = screenList.GetNext() )
1462 {
1463 SIMULATOR_FRAME* simFrame = (SIMULATOR_FRAME*) Kiway().Player( FRAME_SIMULATOR, false );
1464
1465 // Simulator must be closed before loading another schematic, otherwise it may crash.
1466 // If there are any changes in the simulator the user will be prompted to save them.
1467 if( simFrame && !simFrame->Close() )
1468 return false;
1469
1470 if( screen->IsContentModified() )
1471 {
1472 if( !HandleUnsavedChanges( this, _( "The current schematic has been modified. "
1473 "Save changes?" ),
1474 [&]() -> bool
1475 {
1476 return SaveProject();
1477 } ) )
1478 {
1479 return false;
1480 }
1481 }
1482 }
1483
1484 return true;
1485}
1486
1487
1489{
1490 wxFileName tmpFn = Prj().GetProjectFullName();
1491 wxFileName autoSaveFileName( tmpFn.GetPath(), getAutoSaveFileName() );
1492
1493 wxLogTrace( traceAutoSave, "Creating auto save file %s", autoSaveFileName.GetFullPath() );
1494
1495 wxCHECK( autoSaveFileName.IsDirWritable(), false );
1496
1497 wxFileName fn;
1498 SCH_SCREENS screens( Schematic().Root() );
1499 std::vector< wxString > autoSavedFiles;
1500
1501 for( size_t i = 0; i < screens.GetCount(); i++ )
1502 {
1503 // Only create auto save files for the schematics that have been modified.
1504 if( !screens.GetScreen( i )->IsContentModified() )
1505 continue;
1506
1507 fn = screens.GetScreen( i )->GetFileName();
1508
1509 // Auto save file name is the normal file name prefixed with GetAutoSavePrefix().
1510 fn.SetName( FILEEXT::AutoSaveFilePrefix + fn.GetName() );
1511 autoSavedFiles.emplace_back( fn.GetFullPath() );
1512 }
1513
1514 wxTextFile autoSaveFile( autoSaveFileName.GetFullPath() );
1515
1516 if( autoSaveFileName.FileExists() && !wxRemoveFile( autoSaveFileName.GetFullPath() ) )
1517 {
1518 wxLogTrace( traceAutoSave, "Error removing auto save file %s",
1519 autoSaveFileName.GetFullPath() );
1520
1521 return false;
1522 }
1523
1524 // No modified sheet files to save.
1525 if( autoSavedFiles.empty() )
1526 return true;
1527
1528 if( !autoSaveFile.Create() )
1529 return false;
1530
1531 for( const wxString& fileName : autoSavedFiles )
1532 {
1533 wxLogTrace( traceAutoSave, "Adding auto save file %s to %s",
1534 fileName, autoSaveFileName.GetName() );
1535 autoSaveFile.AddLine( fileName );
1536 }
1537
1538 if( !autoSaveFile.Write() )
1539 return false;
1540
1541 wxLogTrace( traceAutoSave, "Auto save file '%s' written", autoSaveFileName.GetFullName() );
1542
1543 return true;
1544}
1545
1546
1547void removeFile( const wxString& aFilename, wxArrayString& aUnremoved )
1548{
1549 wxLogTrace( traceAutoSave, wxS( "Removing auto save file " ) + aFilename );
1550
1551 if( wxFileExists( aFilename ) && !wxRemoveFile( aFilename ) )
1552 aUnremoved.Add( aFilename );
1553};
1554
1555
1556void SCH_EDIT_FRAME::CheckForAutoSaveFile( const wxFileName& aFileName )
1557{
1558 if( !Pgm().IsGUI() )
1559 return;
1560
1561 wxCHECK_RET( aFileName.IsOk(), wxS( "Invalid file name!" ) );
1562
1563 wxLogTrace( traceAutoSave,
1564 wxS( "Checking for auto save file " ) + aFileName.GetFullPath() );
1565
1566 if( !aFileName.FileExists() )
1567 return;
1568
1569 wxString msg = _(
1570 "Well this is potentially embarrassing!\n"
1571 "It appears that the last time you were editing one or more of the schematic files\n"
1572 "were not saved properly. Do you wish to restore the last saved edits you made?" );
1573
1574 int response = wxMessageBox( msg, Pgm().App().GetAppDisplayName(), wxYES_NO | wxICON_QUESTION,
1575 this );
1576
1577 wxTextFile fileList( aFileName.GetFullPath() );
1578
1579 if( !fileList.Open() )
1580 {
1581 msg.Printf( _( "The file '%s' could not be opened.\n"
1582 "Manual recovery of automatically saved files is required." ),
1583 aFileName.GetFullPath() );
1584
1585 wxMessageBox( msg, Pgm().App().GetAppDisplayName(), wxOK | wxICON_EXCLAMATION, this );
1586 return;
1587 }
1588
1589 if( response == wxYES )
1590 {
1591 wxArrayString unrecoveredFiles;
1592
1593 for( wxString fn = fileList.GetFirstLine(); !fileList.Eof(); fn = fileList.GetNextLine() )
1594 {
1595 wxFileName recoveredFn = fn;
1596 wxString tmp = recoveredFn.GetName();
1597
1598 // Strip "_autosave-" prefix from the auto save file name.
1599 tmp.Replace( FILEEXT::AutoSaveFilePrefix, wxS( "" ), false );
1600 recoveredFn.SetName( tmp );
1601
1602 wxFileName backupFn = recoveredFn;
1603
1604 backupFn.SetExt( backupFn.GetExt() + FILEEXT::BackupFileSuffix );
1605
1606 wxLogTrace( traceAutoSave, wxS( "Recovering auto save file:\n"
1607 " Original file: '%s'\n"
1608 " Backup file: '%s'\n"
1609 " Auto save file: '%s'" ),
1610 recoveredFn.GetFullPath(), backupFn.GetFullPath(), fn );
1611
1612 if( !wxFileExists( fn ) )
1613 {
1614 unrecoveredFiles.Add( recoveredFn.GetFullPath() );
1615 }
1616 // Attempt to back up the last schematic file before overwriting it with the auto
1617 // save file.
1618 else if( recoveredFn.Exists()
1619 && !wxCopyFile( recoveredFn.GetFullPath(), backupFn.GetFullPath() ) )
1620 {
1621 unrecoveredFiles.Add( recoveredFn.GetFullPath() );
1622 }
1623 // Attempt to replace last saved file with auto save file
1624 else if( !wxRenameFile( fn, recoveredFn.GetFullPath() ) )
1625 {
1626 unrecoveredFiles.Add( recoveredFn.GetFullPath() );
1627 }
1628 }
1629
1630 if( !unrecoveredFiles.IsEmpty() )
1631 {
1632 msg = _( "The following automatically saved file(s) could not be restored\n" );
1633
1634 for( size_t i = 0; i < unrecoveredFiles.GetCount(); i++ )
1635 msg += unrecoveredFiles[i] + wxS( "\n" );
1636
1637 msg += _( "Manual recovery will be required to restore the file(s) above." );
1638 wxMessageBox( msg, Pgm().App().GetAppDisplayName(), wxOK | wxICON_EXCLAMATION,
1639 this );
1640 }
1641
1642 wxArrayString unremovedFiles;
1643 removeFile( aFileName.GetFullPath(), unremovedFiles );
1644
1645 if( !unremovedFiles.IsEmpty() )
1646 {
1647 msg.Printf( _( "The autosave file '%s' could not be removed.\n"
1648 "Manual removal will be required." ),
1649 unremovedFiles[0] );
1650
1651 wxMessageBox( msg, Pgm().App().GetAppDisplayName(), wxOK | wxICON_EXCLAMATION, this );
1652 }
1653 }
1654 else
1655 {
1656 DeleteAutoSaveFile( aFileName );
1657 }
1658}
1659
1660
1661void SCH_EDIT_FRAME::DeleteAutoSaveFile( const wxFileName& aFileName )
1662{
1663 if( !Pgm().IsGUI() )
1664 return;
1665
1666 wxCHECK_RET( aFileName.IsOk(), wxS( "Invalid file name!" ) );
1667
1668 if( !aFileName.FileExists() )
1669 return;
1670
1671 wxTextFile fileList( aFileName.GetFullPath() );
1672 wxArrayString unremovedFiles;
1673
1674 for( wxString fn = fileList.GetFirstLine(); !fileList.Eof(); fn = fileList.GetNextLine() )
1675 removeFile( fn, unremovedFiles );
1676
1677 removeFile( aFileName.GetFullPath(), unremovedFiles );
1678
1679 if( !unremovedFiles.IsEmpty() )
1680 {
1681 wxString msg = _( "The following automatically saved file(s) could not be removed\n" );
1682
1683 for( size_t i = 0; i < unremovedFiles.GetCount(); i++ )
1684 msg += unremovedFiles[i] + wxS( "\n" );
1685
1686 msg += _( "Manual removal will be required for the file(s) above." );
1687 wxMessageBox( msg, Pgm().App().GetAppDisplayName(), wxOK | wxICON_EXCLAMATION, this );
1688 }
1689}
1690
1691
1693{
1694 static wxString autoSaveFileName( wxS( "#auto_saved_files#" ) );
1695
1696 return autoSaveFileName;
1697}
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:843
CONNECTION_GRAPH * ConnectionGraph() const override
Definition: schematic.h:162
void FixupJunctions()
Add junctions to this schematic where required.
Definition: schematic.cpp:740
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:121
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: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: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.