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