KiCad PCB EDA Suite
Loading...
Searching...
No Matches
sheet.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) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
21#include <map>
22#include <core/utf8.h>
23#include <sch_draw_panel.h>
24#include <common.h>
25#include <confirm.h>
26#include <kiface_base.h>
27#include <project.h>
28#include <math/vector2wx.h>
29#include <string_utils.h>
30#include <trace_helpers.h>
32#include <wx_filename.h>
33#include <tool/tool_manager.h>
34#include <project_sch.h>
35#include <sch_edit_frame.h>
36#include <sch_io/sch_io.h>
37#include <sch_io/sch_io_mgr.h>
39#include <sch_sheet.h>
40#include <sch_sheet_path.h>
41#include <sch_view.h>
42#include <sch_painter.h>
43#include <schematic.h>
45#include <tool/actions.h>
46
47#include <wx/clipbrd.h>
48#include <wx/dcmemory.h>
49#include <wx/log.h>
50#include <wx/msgdlg.h>
51#include <wx/richmsgdlg.h>
52
53#include <advanced_config.h>
54#include <pgm_base.h>
56
58
59
61{
62 wxASSERT( aSheet && aCurrentSheet );
63
64 wxString msg;
65 SCH_SHEET_LIST schematicSheets = Schematic().Hierarchy();
66 SCH_SHEET_LIST loadedSheets( aSheet ); // This is the schematicSheets of the loaded file.
67
68 wxString destFilePath = aCurrentSheet->LastScreen()->GetFileName();
69
70 if( destFilePath.IsEmpty() )
71 {
72 // If file is unsaved then there can't (yet) be any recursion.
73 return false;
74 }
75
76 // SCH_SCREEN object file paths are expected to be absolute. If this assert fires,
77 // something is seriously broken.
78 wxASSERT_MSG( wxFileName( destFilePath ).IsAbsolute(), destFilePath + wxS( " is not absolute" ) );
79
80 if( schematicSheets.TestForRecursion( loadedSheets, destFilePath ) )
81 {
82 msg.Printf( _( "The sheet changes cannot be made because the destination sheet already "
83 "has the sheet '%s' or one of its subsheets as a parent somewhere in the "
84 "schematic hierarchy." ),
85 destFilePath );
86 DisplayError( this, msg );
87 return true;
88 }
89
90 return false;
91}
92
93
95{
96 wxASSERT( aSheet && aSheet->GetScreen() );
97
98 wxString msg;
99 SCH_SCREENS newScreens( aSheet );
100
101 if( newScreens.HasNoFullyDefinedLibIds() )
102 {
103 msg.Printf( _( "The schematic '%s' has not had its symbol library links remapped "
104 "to the symbol library table. The project this schematic belongs to "
105 "must first be remapped before it can be imported into the current "
106 "project." ),
107 aSheet->GetScreen()->GetFileName() );
108 DisplayInfoMessage( this, msg );
109 return true;
110 }
111
112 return false;
113}
114
115
116void SCH_EDIT_FRAME::InitSheet( SCH_SHEET* aSheet, const wxString& aNewFilename )
117{
118 SCH_SCREEN* newScreen = new SCH_SCREEN( &Schematic() );
119 aSheet->SetScreen( newScreen );
120 aSheet->GetScreen()->SetContentModified();
121 aSheet->GetScreen()->SetFileName( aNewFilename );
122
124 wxCHECK( cfg, /* void */ );
125
127 newScreen->SetPageSettings( GetScreen()->GetPageSettings() );
128
129 const TITLE_BLOCK& tb1 = GetScreen()->GetTitleBlock();
130 TITLE_BLOCK tb2 = newScreen->GetTitleBlock();
131
133 tb2.SetRevision( tb1.GetRevision() );
134
135 if( cfg->m_PageSettings.export_date )
136 tb2.SetDate( tb1.GetDate() );
137
139 tb2.SetTitle( tb1.GetTitle() );
140
142 tb2.SetCompany( tb1.GetCompany() );
143
145 tb2.SetComment( 0, tb1.GetComment( 0 ) );
146
148 tb2.SetComment( 1, tb1.GetComment( 1 ) );
149
151 tb2.SetComment( 2, tb1.GetComment( 2 ) );
152
154 tb2.SetComment( 3, tb1.GetComment( 3 ) );
155
157 tb2.SetComment( 4, tb1.GetComment( 4 ) );
158
160 tb2.SetComment( 5, tb1.GetComment( 5 ) );
161
163 tb2.SetComment( 6, tb1.GetComment( 6 ) );
164
166 tb2.SetComment( 7, tb1.GetComment( 7 ) );
167
169 tb2.SetComment( 8, tb1.GetComment( 8 ) );
170
171 newScreen->SetTitleBlock( tb2 );
172}
173
174
175bool SCH_EDIT_FRAME::ChangeSheetFile( SCH_SHEET* aSheet, const wxString& aNewFilename,
176 bool* aClearAnnotationNewItems, bool* aIsUndoable,
177 const wxString* aSourceSheetFilename )
178{
179 wxString msg;
180 SCHEMATIC& schematic = Schematic();
181
182 // Resolve text variables before touching disk. The field keeps the raw text for portability.
183 wxFileName sheetFileName( ExpandTextVars( aNewFilename, &schematic.Project(), INTERNAL ) );
184 SCH_SCREEN* currentScreen = GetCurrentSheet().LastScreen();
185
186 wxCHECK( currentScreen, false );
187
188 // SCH_SCREEN file names are always absolute.
189 wxFileName currentScreenFileName = currentScreen->GetFileName();
190 wxFileName screenFileName( sheetFileName );
191
192 if( !screenFileName.Normalize( FN_NORMALIZE_FLAGS | wxPATH_NORM_ENV_VARS,
193 currentScreenFileName.GetPath() ) )
194 {
195 msg = wxString::Format( _( "Cannot normalize new sheet schematic file path:\n"
196 "'%s'\n"
197 "against parent sheet schematic file path:\n"
198 "'%s'." ),
199 sheetFileName.GetPath(),
200 currentScreenFileName.GetPath() );
201 DisplayError( this, msg );
202 return false;
203 }
204
205 wxString newAbsoluteFilename = screenFileName.GetFullPath();
206 newAbsoluteFilename.Replace( wxT( "\\" ), wxT( "/" ) );
207
208 if( !AllowCaseSensitiveFileNameClashes( aSheet->GetFileName(), newAbsoluteFilename ) )
209 return false;
210
211 SCH_SHEET_LIST fullHierarchy = schematic.Hierarchy();
212
213 bool renameFile = false;
214 bool loadFromFile = false;
215 bool clearAnnotation = false;
216 bool isExistingSheet = false;
217 SCH_SCREEN* useScreen = nullptr;
218 SCH_SCREEN* oldScreen = nullptr;
219
220 // Search for a schematic file already in use in the hierarchy or on disk
221 if( !schematic.Root().SearchHierarchy( newAbsoluteFilename, &useScreen ) )
222 {
223 loadFromFile = wxFileExists( newAbsoluteFilename );
224
225 wxLogTrace( tracePathsAndFiles, "\n Sheet requested file '%s', %s",
226 newAbsoluteFilename,
227 loadFromFile ? "found" : "not found" );
228 }
229
230 if( aSheet->GetScreen() == nullptr )
231 {
232 // New sheet with no screen yet
233 if( useScreen || loadFromFile )
234 {
235 clearAnnotation = true;
236
237 if( !IsOK( this, wxString::Format( _( "'%s' already exists." ),
238 sheetFileName.GetFullName() )
239 + wxT( "\n\n" )
240 + wxString::Format( _( "Link '%s' to this file?" ),
241 newAbsoluteFilename ) ) )
242 {
243 return false;
244 }
245 }
246 else if( aSourceSheetFilename && !aSourceSheetFilename->IsEmpty() )
247 {
248 // Design block / sheet import -- copy source file to destination
249 loadFromFile = true;
250
251 if( !wxCopyFile( *aSourceSheetFilename, newAbsoluteFilename, false ) )
252 {
253 msg.Printf( _( "Failed to copy schematic file '%s' to destination '%s'." ),
254 *aSourceSheetFilename,
255 newAbsoluteFilename );
256 DisplayError( this, msg );
257 return false;
258 }
259 }
260 else
261 {
262 InitSheet( aSheet, newAbsoluteFilename );
263 }
264 }
265 else
266 {
267 // Existing sheet
268 isExistingSheet = true;
269
270 wxString oldAbsoluteFilename = aSheet->GetScreen()->GetFileName();
271 oldAbsoluteFilename.Replace( wxT( "\\" ), wxT( "/" ) );
272
273 if( newAbsoluteFilename.Cmp( oldAbsoluteFilename ) != 0 )
274 {
275 // Sheet file name changes cannot be undone
276 if( aIsUndoable )
277 *aIsUndoable = false;
278
279 if( useScreen || loadFromFile )
280 {
281 clearAnnotation = true;
282 oldScreen = aSheet->GetScreen();
283
284 if( !IsOK( this, wxString::Format( _( "Change '%s' link from '%s' to '%s'?" ),
285 newAbsoluteFilename,
286 aSheet->GetFileName(),
287 sheetFileName.GetFullName() )
288 + wxT( "\n\n" )
289 + _( "This action cannot be undone." ) ) )
290 {
291 return false;
292 }
293
294 if( loadFromFile )
295 aSheet->SetScreen( nullptr );
296 }
297 else
298 {
299 // Save current content to new file name
300 if( aSheet->GetScreenCount() > 1 )
301 {
302 if( !IsOK( this, wxString::Format( _( "Create new file '%s' with contents "
303 "of '%s'?" ),
304 sheetFileName.GetFullName(),
305 aSheet->GetFileName() )
306 + wxT( "\n\n" )
307 + _( "This action cannot be undone." ) ) )
308 {
309 return false;
310 }
311 }
312
313 renameFile = true;
314 }
315 }
316
317 if( renameFile )
318 {
319 IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_KICAD ) );
320
321 // Only update the screen filename when this is the sole user
322 if( aSheet->GetScreenCount() <= 1 )
323 aSheet->GetScreen()->SetFileName( newAbsoluteFilename );
324
325 try
326 {
327 pi->SaveSchematicFile( newAbsoluteFilename, aSheet, &schematic );
328 }
329 catch( const IO_ERROR& ioe )
330 {
331 msg = wxString::Format( _( "Error occurred saving schematic file '%s'." ),
332 newAbsoluteFilename );
333 DisplayErrorMessage( this, msg, ioe.What() );
334
335 msg = wxString::Format( _( "Failed to save schematic '%s'" ),
336 newAbsoluteFilename );
337 SetMsgPanel( wxEmptyString, msg );
338 return false;
339 }
340
341 // Shared screen needs reload to maintain correct reference counting
342 if( aSheet->GetScreenCount() > 1 )
343 {
344 oldScreen = aSheet->GetScreen();
345 aSheet->SetScreen( nullptr );
346 loadFromFile = true;
347 }
348 }
349 }
350
351 SCH_SHEET_PATH& currentSheet = GetCurrentSheet();
352
353 if( useScreen )
354 {
355 // Recursion test with a temporary sheet
356 std::unique_ptr<SCH_SHEET> tmpSheet = std::make_unique<SCH_SHEET>( &schematic );
357 tmpSheet->GetField( FIELD_T::SHEET_FILENAME )->SetText( sheetFileName.GetFullPath() );
358 tmpSheet->SetScreen( useScreen );
359
360 if( CheckSheetForRecursion( tmpSheet.get(), &currentSheet ) )
361 return false;
362
363 aSheet->SetScreen( useScreen );
364
365 SCH_SHEET_LIST sheetHierarchy( aSheet );
366 sheetHierarchy.AddNewSymbolInstances( currentSheet, Prj().GetProjectName() );
367 sheetHierarchy.AddNewSheetInstances( currentSheet,
368 fullHierarchy.GetLastVirtualPageNumber() );
369 }
370 else if( loadFromFile )
371 {
372 bool restoreSheet = false;
373
374 if( isExistingSheet )
375 {
376 restoreSheet = true;
377 currentSheet.LastScreen()->Remove( aSheet );
378 }
379
380 if( !LoadSheetFromFile( aSheet, &currentSheet, newAbsoluteFilename, false, true )
381 || CheckSheetForRecursion( aSheet, &currentSheet ) )
382 {
383 if( restoreSheet )
384 {
385 if( oldScreen )
386 aSheet->SetScreen( oldScreen );
387
388 currentSheet.LastScreen()->Append( aSheet );
389 }
390
391 return false;
392 }
393
394 if( restoreSheet )
395 currentSheet.LastScreen()->Append( aSheet );
396 }
397
398 if( aClearAnnotationNewItems )
399 *aClearAnnotationNewItems = clearAnnotation;
400
402
403 SCH_SHEET_LIST repairedList;
404 repairedList.BuildSheetList( &schematic.Root(), true );
405
406 return true;
407}
408
409
411 const wxString& aFileName, bool aSkipRecursionCheck,
412 bool aSkipLibCheck )
413{
414 wxASSERT( aSheet && aCurrentSheet );
415
416 wxString msg;
417 wxFileName currentSheetFileName;
418 bool libTableChanged = false;
419
420 SCH_IO_MGR::SCH_FILE_T schFileType = SCH_IO_MGR::GuessPluginTypeFromSchPath( aFileName );
421
422 if( schFileType == SCH_IO_MGR::SCH_FILE_UNKNOWN )
423 schFileType = SCH_IO_MGR::SCH_KICAD;
424
425 IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( schFileType ) );
426 std::unique_ptr< SCH_SHEET> tmpSheet = std::make_unique<SCH_SHEET>( &Schematic() );
427
428 // This will cause the sheet UUID to be set to the UUID of the aSheet argument. This is
429 // required to ensure all of the sheet paths in any sub-sheets are correctly generated when
430 // using the temporary SCH_SHEET object that the file is loaded into..
431 const_cast<KIID&>( tmpSheet->m_Uuid ) = aSheet->m_Uuid;
432
433 wxFileName fileName( aFileName );
434
435 if( !fileName.IsAbsolute() && !fileName.MakeAbsolute() )
436 {
437 wxFAIL_MSG( wxString::Format( "Cannot make file name '%s' path absolute.", aFileName ) );
438 return false;
439 }
440
441 wxString fullFilename = fileName.GetFullPath();
442
443 // The caller owns the sheet a plugin returns here, so name the context. An importer that can
444 // only adopt a whole document into the schematic cannot satisfy that and refuses instead.
445 std::map<std::string, UTF8> loadProps;
446 loadProps["hierarchical_sheet_load"] = "1";
447
448 try
449 {
450 if( aSheet->GetScreen() != nullptr )
451 {
452 tmpSheet.reset( pi->LoadSchematicFile( fullFilename, &Schematic(), nullptr, &loadProps ) );
453 }
454 else
455 {
456 tmpSheet->SetFileName( fullFilename );
457 pi->LoadSchematicFile( fullFilename, &Schematic(), tmpSheet.get(), &loadProps );
458 }
459
460 if( !pi->GetError().IsEmpty() )
461 {
462 msg = _( "The entire schematic could not be loaded. Errors occurred attempting "
463 "to load hierarchical sheet schematics." );
464
465 KICAD_MESSAGE_DIALOG msgDlg1( this, msg, _( "Schematic Load Error" ),
466 wxOK | wxCANCEL | wxCANCEL_DEFAULT |
467 wxCENTER | wxICON_QUESTION );
468 msgDlg1.SetOKLabel( wxMessageDialog::ButtonLabel( _( "Use partial schematic" ) ) );
469 msgDlg1.SetExtendedMessage( pi->GetError() );
470
471 if( msgDlg1.ShowModal() == wxID_CANCEL )
472 return false;
473 }
474 }
475 catch( const IO_ERROR& ioe )
476 {
477 msg.Printf( _( "Error loading schematic '%s'." ), fullFilename );
478 DisplayErrorMessage( this, msg, ioe.What() );
479
480 msg.Printf( _( "Failed to load '%s'." ), fullFilename );
481 SetMsgPanel( wxEmptyString, msg );
482
483 return false;
484 }
485
486 // If the loaded schematic is in a different folder from the current project and
487 // it contains hierarchical sheets, the hierarchical sheet paths need to be updated.
488 //
489 // Additionally, we need to make all backing screens absolute paths be in the current project
490 // path not the source path.
491 if( fileName.GetPathWithSep() != Prj().GetProjectPath() )
492 {
493 SCH_SHEET_LIST loadedSheets( tmpSheet.get() );
494
495 for( const SCH_SHEET_PATH& sheetPath : loadedSheets )
496 {
497 // Skip the loaded sheet since the user already determined if the file path should
498 // be relative or absolute.
499 if( sheetPath.size() == 1 )
500 continue;
501
502 wxString lastSheetPath = Prj().GetProjectPath();
503
504 for( unsigned i = 1; i < sheetPath.size(); i++ )
505 {
506 SCH_SHEET* sheet = sheetPath.at( i );
507 wxCHECK2( sheet, continue );
508
509 SCH_SCREEN* screen = sheet->GetScreen();
510 wxCHECK2( screen, continue );
511
512 // Use the screen file name which should always be absolute.
513 wxFileName loadedSheetFileName = screen->GetFileName();
514 wxCHECK2( loadedSheetFileName.IsAbsolute(), continue );
515
516 wxFileName tmp = loadedSheetFileName;
517 wxString sheetFileName;
518
519 if( tmp.MakeRelativeTo( lastSheetPath ) )
520 sheetFileName = tmp.GetFullPath();
521 else
522 sheetFileName = loadedSheetFileName.GetFullPath();
523
524 sheetFileName.Replace( wxT( "\\" ), wxT( "/" ) );
525 sheet->SetFileName( sheetFileName );
526 lastSheetPath = loadedSheetFileName.GetPath();
527 }
528 }
529 }
530
532 LIBRARY_TABLE* projectTable = adapter->ProjectTable().value_or( nullptr );
533
534 SCH_SHEET_LIST loadedSheets( tmpSheet.get() );
536 SCH_SHEET_LIST schematicSheets = Schematic().Hierarchy();
537
538 // Make sure any new sheet changes do not cause any recursion issues.
539 if( !aSkipRecursionCheck && CheckSheetForRecursion( tmpSheet.get(), aCurrentSheet ) )
540 return false;
541
542 if( checkForNoFullyDefinedLibIds( tmpSheet.get() ) )
543 return false;
544
545 // Make a valiant attempt to warn the user of all possible scenarios where there could
546 // be broken symbol library links.
547 wxArrayString names;
548 wxArrayString newLibNames;
549 SCH_SCREENS newScreens( tmpSheet.get() ); // All screens associated with the import.
550 SCH_SCREENS prjScreens( &Schematic().Root() );
551
552 newScreens.GetLibNicknames( names );
553
554 KICAD_MESSAGE_DIALOG::ButtonLabel okButtonLabel( _( "Continue Load" ) );
555 KICAD_MESSAGE_DIALOG::ButtonLabel cancelButtonLabel( _( "Cancel Load" ) );
556
557 // Prior to schematic file format 20221002, all symbol instance data was saved in the root
558 // sheet so loading a hierarchical sheet that is not the root sheet will have no symbol
559 // instance data. Give the user a chance to go back and save the project that contains this
560 // hierarchical sheet so the symbol instance data will be correct on load.
561 if( ( tmpSheet->GetScreen()->GetFileFormatVersionAtLoad() < 20221002 )
562 && tmpSheet->GetScreen()->GetSymbolInstances().empty() )
563 {
564 msg = _( "There are hierarchical sheets in the loaded schematic file from an older "
565 "file version resulting in missing symbol instance data. This will "
566 "result in all of the symbols in the loaded schematic to use either the "
567 "default instance setting or fall back to the library symbol settings. "
568 "Loading the project that uses this schematic file and saving to the "
569 "latest file version will resolve this issue.\n\n"
570 "Do you wish to continue?" );
571 KICAD_MESSAGE_DIALOG msgDlg7( this, msg, _( "Continue Load Schematic" ),
572 wxOK | wxCANCEL | wxCANCEL_DEFAULT | wxCENTER | wxICON_QUESTION );
573 msgDlg7.SetOKCancelLabels( okButtonLabel, cancelButtonLabel );
574
575 if( msgDlg7.ShowModal() == wxID_CANCEL )
576 return false;
577 }
578
579 if( !aSkipLibCheck && !prjScreens.HasSchematic( fullFilename ) )
580 {
581 if( fileName.GetPathWithSep() == Prj().GetProjectPath() )
582 {
583 // A schematic in the current project path that isn't part of the current project.
584 // It's possible the user copied this schematic from another project so the library
585 // links may not be available. Even this is check is no guarantee that all symbol
586 // library links are valid but it's better than nothing.
587 for( const wxString& name : names )
588 {
589 if( !PROJECT_SCH::SymbolLibAdapter( &Prj() )->HasLibrary( name ) )
590 newLibNames.Add( name );
591 }
592
593 if( !newLibNames.IsEmpty() )
594 {
595 msg = _( "There are library names in the selected schematic that are missing "
596 "from the current project library table. This may result in broken "
597 "symbol library references for the loaded schematic.\n\n"
598 "Do you wish to continue?" );
599 KICAD_MESSAGE_DIALOG msgDlg3( this, msg, _( "Continue Load Schematic" ),
600 wxOK | wxCANCEL | wxCANCEL_DEFAULT |
601 wxCENTER | wxICON_QUESTION );
602 msgDlg3.SetOKCancelLabels( okButtonLabel, cancelButtonLabel );
603
604 if( msgDlg3.ShowModal() == wxID_CANCEL )
605 return false;
606 }
607 }
608 else if( fileName.GetPathWithSep() != Prj().GetProjectPath() && projectTable )
609 {
610 // A schematic loaded from a path other than the current project path.
611
612 // If there are symbol libraries in the imported schematic that are not in the
613 // symbol library table of this project, there could be a lot of broken symbol
614 // library links. Attempt to add the missing libraries to the project symbol
615 // library table.
616 wxArrayString duplicateLibNames;
617
618 for( const wxString& name : names )
619 {
620 if( !PROJECT_SCH::SymbolLibAdapter( &Prj() )->HasLibrary( name ) )
621 newLibNames.Add( name );
622 else
623 duplicateLibNames.Add( name );
624 }
625
626 wxFileName symLibTableFn( fileName.GetPath(), FILEEXT::SymbolLibraryTableFileName );
628
629 // If there are any new or duplicate libraries, check to see if it's possible that
630 // there could be any missing libraries that would cause broken symbol library links.
631 if( !newLibNames.IsEmpty() || !duplicateLibNames.IsEmpty() )
632 {
633 if( !symLibTableFn.Exists() || !symLibTableFn.IsFileReadable() )
634 {
635 msg = _( "The selected file was created as part of a different project. "
636 "Linking the file to this project may result in missing or "
637 "incorrect symbol library references.\n\n"
638 "Do you wish to continue?" );
639 KICAD_MESSAGE_DIALOG msgDlg4( this, msg, _( "Continue Load Schematic" ),
640 wxOK | wxCANCEL | wxCANCEL_DEFAULT | wxCENTER
641 | wxICON_QUESTION );
642 msgDlg4.SetOKCancelLabels( okButtonLabel, cancelButtonLabel );
643
644 if( msgDlg4.ShowModal() == wxID_CANCEL )
645 return false;
646 }
647 else
648 {
649 if( !table.IsOk() )
650 {
651 msg.Printf( _( "Error loading the symbol library table '%s'." ),
652 symLibTableFn.GetFullPath() );
653 DisplayErrorMessage( nullptr, msg, table.ErrorDescription() );
654 return false;
655 }
656 }
657 }
658
659 // Check to see if any of the symbol libraries found in the appended schematic do
660 // not exist in the current project are missing from the appended project symbol
661 // library table.
662 if( !newLibNames.IsEmpty() )
663 {
664 bool missingLibNames = table.Rows().empty();
665
666 if( !missingLibNames )
667 {
668 for( const wxString& newLibName : newLibNames )
669 {
670 if( !table.HasRow( newLibName ) )
671 {
672 missingLibNames = true;
673 break;
674 }
675 }
676 }
677
678 if( missingLibNames )
679 {
680 msg = _( "There are symbol library names in the selected schematic that "
681 "are missing from the selected schematic project library table. "
682 "This may result in broken symbol library references.\n\n"
683 "Do you wish to continue?" );
684 KICAD_MESSAGE_DIALOG msgDlg5( this, msg, _( "Continue Load Schematic" ),
685 wxOK | wxCANCEL | wxCANCEL_DEFAULT |
686 wxCENTER | wxICON_QUESTION );
687 msgDlg5.SetOKCancelLabels( okButtonLabel, cancelButtonLabel );
688
689 if( msgDlg5.ShowModal() == wxID_CANCEL )
690 return false;
691 }
692 }
693
694 // The library name already exists in the current project. Check to see if the
695 // duplicate name is the same library in the current project. If it's not, it's
696 // most likely that the symbol library links will be broken.
697 if( !duplicateLibNames.IsEmpty() && !table.Rows().empty() )
698 {
699 bool libNameConflict = false;
700
701 for( const wxString& duplicateLibName : duplicateLibNames )
702 {
703 const LIBRARY_TABLE_ROW* thisRow = nullptr;
704 const LIBRARY_TABLE_ROW* otherRow = nullptr;
705
706 if( adapter->HasLibrary( duplicateLibName ) )
707 thisRow = *adapter->GetRow( duplicateLibName );
708
709 if( table.HasRow( duplicateLibName ) )
710 otherRow = *table.Row( duplicateLibName );
711
712 // It's in the global library table so there is no conflict.
713 if( thisRow && !otherRow )
714 continue;
715
716 if( !thisRow || !otherRow )
717 continue;
718
719 wxFileName otherUriFileName;
720 wxString thisURI = LIBRARY_MANAGER::GetFullURI( thisRow, true );;
721 wxString otherURI = LIBRARY_MANAGER::GetFullURI( otherRow, false );
722
723 if( otherURI.Contains( "${KIPRJMOD}" ) || otherURI.Contains( "$(KIPRJMOD)" ) )
724 {
725 // Cannot use relative paths here, "${KIPRJMOD}../path-to-cache-lib" does
726 // not expand to a valid symbol library path.
727 otherUriFileName.SetPath( fileName.GetPath() );
728 otherUriFileName.SetFullName( otherURI.AfterLast( '}' ) );
729 otherURI = otherUriFileName.GetFullPath();
730 }
731
732 if( thisURI != otherURI )
733 {
734 libNameConflict = true;
735 break;
736 }
737 }
738
739 if( libNameConflict )
740 {
741 msg = _( "A duplicate library name that references a different library exists "
742 "in the current library table. This conflict cannot be resolved and "
743 "may result in broken symbol library references.\n\n"
744 "Do you wish to continue?" );
745 KICAD_MESSAGE_DIALOG msgDlg6( this, msg, _( "Continue Load Schematic" ),
746 wxOK | wxCANCEL | wxCANCEL_DEFAULT |
747 wxCENTER | wxICON_QUESTION );
748 msgDlg6.SetOKCancelLabels( okButtonLabel, cancelButtonLabel );
749
750 if( msgDlg6.ShowModal() == wxID_CANCEL )
751 return false;
752 }
753 }
754
755 // All (most?) of the possible broken symbol library link cases are covered. Map the
756 // new appended schematic project symbol library table entries to the current project
757 // symbol library table.
758 if( !newLibNames.IsEmpty() && !table.Rows().empty() )
759 {
760 for( const wxString& libName : newLibNames )
761 {
762 if( !table.HasRow( libName ) || adapter->HasLibrary( libName ) )
763 {
764 continue;
765 }
766
767 LIBRARY_TABLE_ROW* row = *table.Row( libName );
768
769 // Don't expand environment variable because KIPRJMOD will not be correct
770 // for a different project.
771 wxString uri = LIBRARY_MANAGER::GetFullURI( row, false );
772 wxFileName newLib;
773
774 if( uri.Contains( "${KIPRJMOD}" ) || uri.Contains( "$(KIPRJMOD)" ) )
775 {
776 // Cannot use relative paths here, "${KIPRJMOD}../path-to-cache-lib" does
777 // not expand to a valid symbol library path.
778 newLib.SetPath( fileName.GetPath() );
779 newLib.SetFullName( uri.AfterLast( '}' ) );
780 uri = newLib.GetFullPath();
781 }
782 else
783 {
784 uri = LIBRARY_MANAGER::GetFullURI( row, true );
785 }
786
787 // Add the library from the imported project to the current project
788 // symbol library table.
789
790 LIBRARY_TABLE_ROW& newRow = projectTable->InsertRow();
791
792 newRow.SetNickname( libName );
793 newRow.SetURI( uri );
794 newRow.SetType( row->Type() );
795 newRow.SetDescription( row->Description() );
796 newRow.SetOptions( row->Options() );
797
798 libTableChanged = true;
799 }
800 }
801 }
802 }
803
804 SCH_SCREEN* newScreen = tmpSheet->GetScreen();
805 wxCHECK_MSG( newScreen, false, "No screen defined for sheet." );
806
807 if( libTableChanged && projectTable )
808 {
809 projectTable->Save().map_error(
810 [&]( const LIBRARY_ERROR& aError )
811 {
812 KICAD_MESSAGE_DIALOG dlg( this, _( "Error saving library table." ), _( "File Save Error" ),
813 wxOK | wxICON_ERROR );
814 dlg.SetExtendedMessage( aError.message );
815 dlg.ShowModal();
816 } );
817 }
818
819 // Make the best attempt to set the symbol instance data for the loaded schematic.
820 if( newScreen->GetFileFormatVersionAtLoad() < 20221002 )
821 {
822 if( !newScreen->GetSymbolInstances().empty() )
823 {
824 // If the loaded schematic is a root sheet for another project, update the symbol
825 // instances.
826 loadedSheets.UpdateSymbolInstanceData( newScreen->GetSymbolInstances());
827 }
828 }
829
830 newScreen->MigrateSimModels();
831
832 // Attempt to create new symbol instances using the instance data loaded above.
833 loadedSheets.AddNewSymbolInstances( *aCurrentSheet, Prj().GetProjectName() );
834
835 // Add new sheet instance data.
836 loadedSheets.AddNewSheetInstances( *aCurrentSheet, schematicSheets.GetLastVirtualPageNumber() );
837
838 // It is finally safe to add or append the imported schematic.
839 if( aSheet->GetScreen() == nullptr )
840 aSheet->SetScreen( newScreen );
841 else
842 aSheet->GetScreen()->Append( newScreen );
843
844 SCH_SCREENS allProjectScreens( &Schematic().Root() );
845 allProjectScreens.ReplaceDuplicateTimeStamps();
846
847 return true;
848}
849
850
852 bool* aIsUndoable, bool* aClearAnnotationNewItems,
853 bool* aUpdateHierarchyNavigator,
854 wxString* aSourceSheetFilename )
855{
856 if( aSheet == nullptr || aHierarchy == nullptr )
857 return false;
858
859 // Get the new texts
860 DIALOG_SHEET_PROPERTIES dlg( this, aSheet, aIsUndoable, aClearAnnotationNewItems,
861 aUpdateHierarchyNavigator, aSourceSheetFilename );
862
863 if( dlg.ShowModal() == wxID_CANCEL )
864 return false;
865
867
868 return true;
869}
870
871
873{
874 wxRect drawArea;
875 BASE_SCREEN* screen = GetScreen();
876
877 drawArea.SetSize( ToWxSize( GetPageSizeIU() ) );
878
879 // Calculate a reasonable dc size, in pixels, and the dc scale to fit
880 // the drawings into the dc size
881 // scale is the ratio resolution (in PPI) / internal units
882 double ppi = 300; // Use 300 pixels per inch to create bitmap images on start
883 double inch2Iu = 1000.0 * schIUScale.IU_PER_MILS;
884 double scale = ppi / inch2Iu;
885
886 wxSize dcsize = drawArea.GetSize();
887
888 int maxdim = std::max( dcsize.x, dcsize.y );
889
890 // the max size in pixels of the bitmap used to build the sheet copy
891 const int maxbitmapsize = 5600;
892
893 while( int( maxdim * scale ) > maxbitmapsize )
894 {
895 ppi = ppi / 1.5;
896 scale = ppi / inch2Iu;
897 }
898
899 dcsize.x *= scale;
900 dcsize.y *= scale;
901
902 // Set draw offset, zoom... to values needed to draw in the memory DC
903 // after saving initial values:
904 VECTOR2I tmp_startvisu = screen->m_StartVisu;
905 VECTOR2I old_org = screen->m_DrawOrg;
906 screen->m_DrawOrg.x = screen->m_DrawOrg.y = 0;
907 screen->m_StartVisu.x = screen->m_StartVisu.y = 0;
908
909 wxMemoryDC dc;
910 wxBitmap image( dcsize );
911 dc.SelectObject( image );
912 dc.Clear();
913
914 GRResetPenAndBrush( &dc );
915 GRForceBlackPen( false );
916 dc.SetUserScale( scale, scale );
917
919
920 cfg->SetPrintDC( &dc );
921
922 // Init the color of the layer actually used to print the drawing sheet:
924
925 cfg->SetDefaultFont( eeconfig()->m_Appearance.default_font );
926
927 try
928 {
929 dc.SetUserScale( 1.0, 1.0 );
930 SCH_PRINTOUT printout( this, wxEmptyString );
931 // Ensure title block will be when printed on clipboard, regardless
932 // the current Cairo print option
933 EESCHEMA_SETTINGS* eecfg = eeconfig();
934 bool print_tb_opt = eecfg->m_Printing.title_block;
935 eecfg->m_Printing.title_block = true;
936 bool success = printout.PrintPage( GetScreen(), cfg->GetPrintDC(), false );
937 eecfg->m_Printing.title_block = print_tb_opt;
938
939 if( !success )
940 wxLogMessage( _( "Cannot create the schematic image") );
941 }
942 catch( ... )
943 {
944 wxLogMessage( "printout internal error" );
945 }
946
947 // Deselect Bitmap from DC before using the bitmap
948 dc.SelectObject( wxNullBitmap );
949
950 {
951 wxLogNull doNotLog; // disable logging of failed clipboard actions
952
953 if( wxTheClipboard->Open() )
954 {
955 // This data objects are held by the clipboard, so do not delete them in the app.
956 wxBitmapDataObject* clipbrd_data = new wxBitmapDataObject( image );
957 wxTheClipboard->SetData( clipbrd_data );
958 wxTheClipboard->Flush(); // Allow data to be available after closing KiCad
959 wxTheClipboard->Close();
960 }
961 }
962
963 GRForceBlackPen( false );
964
965 screen->m_StartVisu = tmp_startvisu;
966 screen->m_DrawOrg = old_org;
967}
968
969
971 const wxString& aSchematicFileName )
972{
973 wxString msg;
975 wxFileName fn = aSchematicFileName;
976
977 wxCHECK( fn.IsAbsolute(), false );
978
979 auto can_cause_issues = [&]() -> bool
980 {
981 wxFileName lhs;
982 wxFileName rhs = aSchematicFileName;
983 wxFileName old = aOldName;
984 wxString oldLower = old.GetFullName().Lower();
985 wxString rhsLower = rhs.GetFullName().Lower();
986 wxString lhsLower;
987
988 size_t count = 0;
989
990 wxCHECK( rhs.IsAbsolute(), false );
991
992 for( SCH_SHEET_PATH& sheet : sheets )
993 {
994 lhs = sheet.LastScreen()->GetFileName();
995
996 if( lhs.GetPath() != rhs.GetPath() )
997 continue;
998
999 lhsLower = lhs.GetFullName().Lower();
1000
1001 if( lhsLower == rhsLower && lhs.GetFullName() != rhs.GetFullName() )
1002 count++;
1003 }
1004
1005 // If we are renaming a sheet that is only used once, then we are not going to cause
1006 // a case sensitivity issue.
1007 if( oldLower == rhsLower )
1008 return count > 1;
1009
1010 return count > 0;
1011 };
1012
1013 if( eeconfig()->m_Appearance.show_sheet_filename_case_sensitivity_dialog && can_cause_issues() )
1014 {
1015 msg.Printf( _( "The file name '%s' can cause issues with an existing file name\n"
1016 "already defined in the schematic on systems that support case\n"
1017 "insensitive file names. This will cause issues if you copy this\n"
1018 "project to an operating system that supports case insensitive file\n"
1019 "names.\n\nDo you wish to continue?" ),
1020 fn.GetName() );
1021
1022 wxRichMessageDialog dlg( this, msg, _( "Warning" ),
1023 wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION );
1024 dlg.ShowCheckBox( _( "Do not show this message again." ) );
1025 dlg.SetYesNoLabels( wxMessageDialog::ButtonLabel( _( "Create New Sheet" ) ),
1026 wxMessageDialog::ButtonLabel( _( "Cancel" ) ) );
1027
1028 if( dlg.ShowModal() == wxID_NO )
1029 return false;
1030
1032 !dlg.IsCheckBoxChecked();
1033 }
1034
1035 return true;
1036}
const char * name
constexpr EDA_IU_SCALE schIUScale
Definition base_units.h:123
Handles how to draw a screen (a board, a schematic ...)
Definition base_screen.h:37
VECTOR2I m_DrawOrg
offsets for drawing the circuit on the screen
Definition base_screen.h:84
VECTOR2I m_StartVisu
Coordinates in drawing units of the current view position (upper left corner of device)
Definition base_screen.h:89
void SetContentModified(bool aModified=true)
Definition base_screen.h:55
int ShowModal() override
void SetMsgPanel(const std::vector< MSG_PANEL_ITEM > &aList)
Clear the message panel and populates it with the contents of aList.
const KIID m_Uuid
Definition eda_item.h:597
PAGE_SETTINGS m_PageSettings
static const TOOL_EVENT SelectedItemsModified
Selected items were moved, this can be very high frequency on the canvas, use with care.
Definition actions.h:350
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
virtual const wxString What() const
A composite of Problem() and Where()
void SetLayerColor(int aLayer, const COLOR4D &aColor)
Change the color used to draw a layer.
void SetDefaultFont(const wxString &aFont)
const COLOR4D & GetLayerColor(int aLayer) const
Return the color used to draw a layer.
void SetPrintDC(wxDC *aDC)
Definition kiid.h:46
std::optional< LIBRARY_TABLE * > ProjectTable() const
Retrieves the project library table for this adapter type, or nullopt if one doesn't exist.
bool HasLibrary(const wxString &aNickname, bool aCheckEnabled=false) const
Test for the existence of aNickname in the library tables.
std::optional< LIBRARY_TABLE_ROW * > GetRow(const wxString &aNickname, LIBRARY_TABLE_SCOPE aScope=LIBRARY_TABLE_SCOPE::BOTH) const
Like LIBRARY_MANAGER::GetRow but filtered to the LIBRARY_TABLE_TYPE of this adapter.
std::optional< wxString > GetFullURI(LIBRARY_TABLE_TYPE aType, const wxString &aNickname, bool aSubstituted=false)
Return the full location specifying URI for the LIB, either in original UI form or in environment var...
void SetOptions(const wxString &aOptions)
void SetNickname(const wxString &aNickname)
void SetType(const wxString &aType)
void SetDescription(const wxString &aDescription)
const wxString & Type() const
void SetURI(const wxString &aUri)
const wxString & Description() const
const wxString & Options() const
LIBRARY_RESULT< void > Save()
LIBRARY_TABLE_ROW & InsertRow()
Builds a new row and inserts it at the end of the table; returning a reference to the row.
static SYMBOL_LIBRARY_ADAPTER * SymbolLibAdapter(PROJECT *aProject)
Accessor for project symbol library manager adapter.
virtual const wxString GetProjectPath() const
Return the full path of the project.
Definition project.cpp:183
Holds all the data relating to one schematic.
Definition schematic.h:148
SCH_SHEET_LIST Hierarchy() const
Return the full schematic flattened hierarchical sheet list.
PROJECT & Project() const
Return a reference to the project this schematic is part of.
Definition schematic.h:170
SCH_SHEET & Root() const
Definition schematic.h:199
void RefreshHierarchy()
SCH_RENDER_SETTINGS * GetRenderSettings()
const VECTOR2I GetPageSizeIU() const override
Works off of GetPageSettings() to return the size of the paper page in the internal units of this par...
EESCHEMA_SETTINGS * eeconfig() const
const PAGE_INFO & GetPageSettings() const override
void RecalculateConnections(SCH_COMMIT *aCommit, SCH_CLEANUP_FLAGS aCleanupFlags, PROGRESS_REPORTER *aProgressReporter=nullptr, bool aCleanupDone=false)
Generate the connection data for the entire schematic hierarchy.
bool AllowCaseSensitiveFileNameClashes(const wxString &aOldName, const wxString &aSchematicFileName)
Check aSchematicFileName for a potential file name case sensitivity clashes.
Definition sheet.cpp:970
SCH_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
void InitSheet(SCH_SHEET *aSheet, const wxString &aNewFilename)
Definition sheet.cpp:116
bool LoadSheetFromFile(SCH_SHEET *aSheet, SCH_SHEET_PATH *aCurrentSheet, const wxString &aFileName, bool aSkipRecursionCheck=false, bool aSkipLibCheck=false)
Load a the KiCad schematic file aFileName into the sheet aSheet.
Definition sheet.cpp:410
SCH_SHEET_PATH & GetCurrentSheet() const
SCHEMATIC & Schematic() const
void DrawCurrentSheetToClipboard()
Use the wxWidgets print code to draw an image of the current sheet onto the clipboard.
Definition sheet.cpp:872
bool checkForNoFullyDefinedLibIds(SCH_SHEET *aSheet)
Verify that the symbol library links aSheet and all of its child sheets have been remapped to the sym...
Definition sheet.cpp:94
bool EditSheetProperties(SCH_SHEET *aSheet, SCH_SHEET_PATH *aHierarchy, bool *aIsUndoable=nullptr, bool *aClearAnnotationNewItems=nullptr, bool *aUpdateHierarchyNavigator=nullptr, wxString *aSourceSheetFilename=nullptr)
Edit an existing sheet or add a new sheet to the schematic.
Definition sheet.cpp:851
bool CheckSheetForRecursion(SCH_SHEET *aSheet, SCH_SHEET_PATH *aCurrentSheet)
Verify that aSheet will not cause a recursion error in aCurrentSheet.
Definition sheet.cpp:60
bool ChangeSheetFile(SCH_SHEET *aSheet, const wxString &aNewFilename, bool *aClearAnnotationNewItems=nullptr, bool *aIsUndoable=nullptr, const wxString *aSourceSheetFilename=nullptr)
Change the file backing a schematic sheet.
Definition sheet.cpp:175
static SCH_FILE_T GuessPluginTypeFromSchPath(const wxString &aSchematicPath, int aCtl=0)
Return a plugin type given a schematic using the file extension of aSchematicPath.
Custom print out for printing schematics.
bool PrintPage(SCH_SCREEN *aScreen, wxDC *aDC, bool aForPrinting)
Print the current SCH_SCREEN using a given wxDC.
Container class that holds multiple SCH_SCREEN objects in a hierarchy.
Definition sch_screen.h:758
bool HasNoFullyDefinedLibIds()
Test all of the schematic symbols to see if all LIB_ID objects library nickname is not set.
int ReplaceDuplicateTimeStamps()
Test all sheet and symbol objects in the schematic for duplicate time stamps and replaces them as nec...
bool HasSchematic(const wxString &aSchematicFileName)
Check if one of the schematics in the list of screens is aSchematicFileName.
size_t GetLibNicknames(wxArrayString &aLibNicknames)
Fetch all of the symbol library nicknames into aLibNicknames.
void SetTitleBlock(const TITLE_BLOCK &aTitleBlock)
Definition sch_screen.h:167
void Append(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
void SetPageSettings(const PAGE_INFO &aPageSettings)
Definition sch_screen.h:141
const wxString & GetFileName() const
Definition sch_screen.h:153
void SetFileName(const wxString &aFileName)
Set the file name for this screen to aFileName.
const std::vector< SCH_SYMBOL_INSTANCE > & GetSymbolInstances() const
Definition sch_screen.h:530
bool Remove(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
Remove aItem from the schematic associated with this screen.
int GetFileFormatVersionAtLoad() const
Definition sch_screen.h:138
TITLE_BLOCK & GetTitleBlock()
Definition sch_screen.h:164
void MigrateSimModels()
Migrate any symbols having V6 simulation models to their V7 equivalents.
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
void AddNewSymbolInstances(const SCH_SHEET_PATH &aPrefixSheetPath, const wxString &aProjectName)
Attempt to add new symbol instances for all symbols in this list of sheet paths prefixed with aPrefix...
int GetLastVirtualPageNumber() const
void UpdateSymbolInstanceData(const std::vector< SCH_SYMBOL_INSTANCE > &aSymbolInstances)
Update all of the symbol instance information using aSymbolInstances.
void AddNewSheetInstances(const SCH_SHEET_PATH &aPrefixSheetPath, int aLastVirtualPageNumber)
void BuildSheetList(SCH_SHEET *aSheet, bool aCheckIntegrity)
Build the list of sheets and their sheet path from aSheet.
bool TestForRecursion(const SCH_SHEET_LIST &aSrcSheetHierarchy, const wxString &aDestFileName)
Test every SCH_SHEET_PATH in this SCH_SHEET_LIST to verify if adding the sheets stored in aSrcSheetHi...
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
SCH_SCREEN * LastScreen()
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition sch_sheet.h:48
void SetFileName(const wxString &aFilename)
Definition sch_sheet.h:390
wxString GetFileName() const
Return the filename corresponding to this sheet.
Definition sch_sheet.h:384
bool SearchHierarchy(const wxString &aFilename, SCH_SCREEN **aScreen)
Search the existing hierarchy for an instance of screen loaded from aFileName.
SCH_SCREEN * GetScreen() const
Definition sch_sheet.h:145
int GetScreenCount() const
Return the number of times the associated screen for the sheet is being used.
void SetScreen(SCH_SCREEN *aScreen)
Set the SCH_SCREEN associated with this sheet to aScreen.
An interface to the global shared library manager that is schematic-specific and linked to one projec...
Hold the information shown in the lower right corner of a plot, printout, or editing view.
Definition title_block.h:38
const wxString & GetCompany() const
Definition title_block.h:93
void SetRevision(const wxString &aRevision)
Definition title_block.h:78
void SetComment(int aIdx, const wxString &aComment)
Definition title_block.h:98
const wxString & GetRevision() const
Definition title_block.h:83
void SetTitle(const wxString &aTitle)
Definition title_block.h:55
const wxString & GetDate() const
Definition title_block.h:73
const wxString & GetComment(int aIdx) const
void SetCompany(const wxString &aCompany)
Definition title_block.h:88
const wxString & GetTitle() const
Definition title_block.h:60
void SetDate(const wxString &aDate)
Set the date field, and defaults to the current time and date.
Definition title_block.h:68
TOOL_MANAGER * m_toolManager
wxString ExpandTextVars(const wxString &aSource, const PROJECT *aProject, RESOLUTION_CONTEXT aContext)
Definition common.cpp:60
@ INTERNAL
Definition common.h:92
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition confirm.cpp:274
void DisplayInfoMessage(wxWindow *aParent, const wxString &aMessage, const wxString &aExtraInfo)
Display an informational message box with aMessage.
Definition confirm.cpp:245
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition confirm.cpp:217
void DisplayError(wxWindow *aParent, const wxString &aText)
Display an error or warning message box with aMessage.
Definition confirm.cpp:192
This file is part of the common library.
#define KICAD_MESSAGE_DIALOG
Definition confirm.h:48
#define _(s)
void GRForceBlackPen(bool flagforce)
Definition gr_basic.cpp:159
void GRResetPenAndBrush(wxDC *DC)
Definition gr_basic.cpp:73
static const std::string SymbolLibraryTableFileName
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:727
@ LAYER_DRAWINGSHEET
Sheet frame and title block.
Definition layer_ids.h:274
@ LAYER_SCHEMATIC_DRAWINGSHEET
Definition layer_ids.h:518
see class PGM_BASE
Definition of the SCH_SHEET_PATH and SCH_SHEET_LIST classes for Eeschema.
@ GLOBAL_CLEANUP
Definition schematic.h:94
const int scale
bool title_block
Whether or not to print title block.
wxString message
wxLogTrace helper definitions.
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683
wxSize ToWxSize(const VECTOR2I &aSize)
Definition vector2wx.h:51
Definition of file extensions used in Kicad.
#define FN_NORMALIZE_FLAGS
Default flags to pass to wxFileName::Normalize().
Definition wx_filename.h:35