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 wxString thisURI = LIBRARY_MANAGER::GetFullURI( thisRow, true );
720 wxString otherURI = LIBRARY_MANAGER::GetFullURI( otherRow, false );
721
722 if( otherURI.Contains( "${KIPRJMOD}" ) || otherURI.Contains( "$(KIPRJMOD)" ) )
723 {
724 // Resolve KIPRJMOD against the imported schematic's directory.
725 otherURI.Replace( wxS( "${KIPRJMOD}" ), fileName.GetPath() );
726 otherURI.Replace( wxS( "$(KIPRJMOD)" ), fileName.GetPath() );
727 wxFileName otherUriFileName( otherURI );
728 otherURI = otherUriFileName.GetFullPath();
729 }
730
731 if( !LIBRARY_MANAGER::UrisAreEquivalent( thisURI, otherURI ) )
732 {
733 libNameConflict = true;
734 break;
735 }
736 }
737
738 if( libNameConflict )
739 {
740 msg = _( "A duplicate library name that references a different library exists "
741 "in the current library table. This conflict cannot be resolved and "
742 "may result in broken symbol library references.\n\n"
743 "Do you wish to continue?" );
744 KICAD_MESSAGE_DIALOG msgDlg6( this, msg, _( "Continue Load Schematic" ),
745 wxOK | wxCANCEL | wxCANCEL_DEFAULT |
746 wxCENTER | wxICON_QUESTION );
747 msgDlg6.SetOKCancelLabels( okButtonLabel, cancelButtonLabel );
748
749 if( msgDlg6.ShowModal() == wxID_CANCEL )
750 return false;
751 }
752 }
753
754 // All (most?) of the possible broken symbol library link cases are covered. Map the
755 // new appended schematic project symbol library table entries to the current project
756 // symbol library table.
757 if( !newLibNames.IsEmpty() && !table.Rows().empty() )
758 {
759 for( const wxString& libName : newLibNames )
760 {
761 if( !table.HasRow( libName ) || adapter->HasLibrary( libName ) )
762 {
763 continue;
764 }
765
766 LIBRARY_TABLE_ROW* row = *table.Row( libName );
767
768 // Don't expand environment variable because KIPRJMOD will not be correct
769 // for a different project.
770 wxString uri = LIBRARY_MANAGER::GetFullURI( row, false );
771
772 if( uri.Contains( "${KIPRJMOD}" ) || uri.Contains( "$(KIPRJMOD)" ) )
773 {
774 uri.Replace( wxS( "${KIPRJMOD}" ), fileName.GetPath() );
775 uri.Replace( wxS( "$(KIPRJMOD)" ), fileName.GetPath() );
776 wxFileName newLib( uri );
777 uri = newLib.GetFullPath();
778 }
779 else
780 {
781 uri = LIBRARY_MANAGER::GetFullURI( row, true );
782 }
783
784 // Add the library from the imported project to the current project
785 // symbol library table.
786
787 LIBRARY_TABLE_ROW& newRow = projectTable->InsertRow();
788
789 newRow.SetNickname( libName );
790 newRow.SetURI( uri );
791 newRow.SetType( row->Type() );
792 newRow.SetDescription( row->Description() );
793 newRow.SetOptions( row->Options() );
794
795 libTableChanged = true;
796 }
797 }
798 }
799 }
800
801 SCH_SCREEN* newScreen = tmpSheet->GetScreen();
802 wxCHECK_MSG( newScreen, false, "No screen defined for sheet." );
803
804 if( libTableChanged && projectTable )
805 {
806 projectTable->Save().map_error(
807 [&]( const LIBRARY_ERROR& aError )
808 {
809 KICAD_MESSAGE_DIALOG dlg( this, _( "Error saving library table." ), _( "File Save Error" ),
810 wxOK | wxICON_ERROR );
811 dlg.SetExtendedMessage( aError.message );
812 dlg.ShowModal();
813 } );
814 }
815
816 // Make the best attempt to set the symbol instance data for the loaded schematic.
817 if( newScreen->GetFileFormatVersionAtLoad() < 20221002 )
818 {
819 if( !newScreen->GetSymbolInstances().empty() )
820 {
821 // If the loaded schematic is a root sheet for another project, update the symbol
822 // instances.
823 loadedSheets.UpdateSymbolInstanceData( newScreen->GetSymbolInstances());
824 }
825 }
826
827 newScreen->MigrateSimModels();
828
829 // Attempt to create new symbol instances using the instance data loaded above.
830 loadedSheets.AddNewSymbolInstances( *aCurrentSheet, Prj().GetProjectName() );
831
832 // Add new sheet instance data.
833 loadedSheets.AddNewSheetInstances( *aCurrentSheet, schematicSheets.GetLastVirtualPageNumber() );
834
835 // It is finally safe to add or append the imported schematic.
836 if( aSheet->GetScreen() == nullptr )
837 aSheet->SetScreen( newScreen );
838 else
839 aSheet->GetScreen()->Append( newScreen );
840
841 SCH_SCREENS allProjectScreens( &Schematic().Root() );
842 allProjectScreens.ReplaceDuplicateTimeStamps();
843
844 return true;
845}
846
847
849 bool* aIsUndoable, bool* aClearAnnotationNewItems,
850 bool* aUpdateHierarchyNavigator,
851 wxString* aSourceSheetFilename )
852{
853 if( aSheet == nullptr || aHierarchy == nullptr )
854 return false;
855
856 // Get the new texts
857 DIALOG_SHEET_PROPERTIES dlg( this, aSheet, aIsUndoable, aClearAnnotationNewItems,
858 aUpdateHierarchyNavigator, aSourceSheetFilename );
859
860 if( dlg.ShowModal() == wxID_CANCEL )
861 return false;
862
864
865 return true;
866}
867
868
870{
871public:
872 PRINT_TITLEBLOCK_CONTEXT( SCH_EDIT_FRAME* aFrame, bool aPrintTitleBlock ) :
873 m_frame( aFrame )
874 {
875 m_originalValue = m_frame->eeconfig()->m_Printing.title_block;
876 m_frame->eeconfig()->m_Printing.title_block = aPrintTitleBlock;
877 }
878
880 {
881 m_frame->eeconfig()->m_Printing.title_block = m_originalValue;
882 }
883
884private:
887};
888
889
891{
892 wxRect drawArea;
893 BASE_SCREEN* screen = GetScreen();
894
895 drawArea.SetSize( ToWxSize( GetPageSizeIU() ) );
896
897 // Calculate a reasonable dc size, in pixels, and the dc scale to fit
898 // the drawings into the dc size
899 // scale is the ratio resolution (in PPI) / internal units
900 double ppi = 300; // Use 300 pixels per inch to create bitmap images on start
901 double inch2Iu = 1000.0 * schIUScale.IU_PER_MILS;
902 double scale = ppi / inch2Iu;
903
904 wxSize dcsize = drawArea.GetSize();
905
906 int maxdim = std::max( dcsize.x, dcsize.y );
907
908 // the max size in pixels of the bitmap used to build the sheet copy
909 const int maxbitmapsize = 5600;
910
911 while( int( maxdim * scale ) > maxbitmapsize )
912 {
913 ppi = ppi / 1.5;
914 scale = ppi / inch2Iu;
915 }
916
917 dcsize.x *= scale;
918 dcsize.y *= scale;
919
920 // Set draw offset, zoom... to values needed to draw in the memory DC
921 // after saving initial values:
922 VECTOR2I tmp_startvisu = screen->m_StartVisu;
923 VECTOR2I old_org = screen->m_DrawOrg;
924 screen->m_DrawOrg.x = screen->m_DrawOrg.y = 0;
925 screen->m_StartVisu.x = screen->m_StartVisu.y = 0;
926
927 wxMemoryDC dc;
928 wxBitmap image( dcsize );
929 dc.SelectObject( image );
930 dc.Clear();
931
932 GRResetPenAndBrush( &dc );
933 GRForceBlackPen( false );
934 dc.SetUserScale( scale, scale );
935
937
938 cfg->SetPrintDC( &dc );
939
940 // Init the color of the layer actually used to print the drawing sheet:
942
943 cfg->SetDefaultFont( eeconfig()->m_Appearance.default_font );
944
945 try
946 {
947 dc.SetUserScale( 1.0, 1.0 );
948 SCH_PRINTOUT printout( this, wxEmptyString );
949
950 // Ensure title block will be when printed on clipboard, regardless of the current Cairo print option
951 PRINT_TITLEBLOCK_CONTEXT raii( this, true );
952
953 if( !printout.PrintPage( GetScreen(), cfg->GetPrintDC(), false ) )
954 wxLogMessage( _( "Cannot create the schematic image") );
955 }
956 catch( ... )
957 {
958 wxLogMessage( "printout internal error" );
959 }
960
961 // Deselect Bitmap from DC before using the bitmap
962 dc.SelectObject( wxNullBitmap );
963
964 {
965 wxLogNull doNotLog; // disable logging of failed clipboard actions
966
967 if( wxTheClipboard->Open() )
968 {
969 // This data objects are held by the clipboard, so do not delete them in the app.
970 wxBitmapDataObject* clipbrd_data = new wxBitmapDataObject( image );
971 wxTheClipboard->SetData( clipbrd_data );
972 wxTheClipboard->Flush(); // Allow data to be available after closing KiCad
973 wxTheClipboard->Close();
974 }
975 }
976
977 GRForceBlackPen( false );
978
979 screen->m_StartVisu = tmp_startvisu;
980 screen->m_DrawOrg = old_org;
981}
982
983
985 const wxString& aSchematicFileName )
986{
987 wxString msg;
989 wxFileName fn = aSchematicFileName;
990
991 wxCHECK( fn.IsAbsolute(), false );
992
993 auto can_cause_issues = [&]() -> bool
994 {
995 wxFileName lhs;
996 wxFileName rhs = aSchematicFileName;
997 wxFileName old = aOldName;
998 wxString oldLower = old.GetFullName().Lower();
999 wxString rhsLower = rhs.GetFullName().Lower();
1000 wxString lhsLower;
1001
1002 size_t count = 0;
1003
1004 wxCHECK( rhs.IsAbsolute(), false );
1005
1006 for( SCH_SHEET_PATH& sheet : sheets )
1007 {
1008 lhs = sheet.LastScreen()->GetFileName();
1009
1010 if( lhs.GetPath() != rhs.GetPath() )
1011 continue;
1012
1013 lhsLower = lhs.GetFullName().Lower();
1014
1015 if( lhsLower == rhsLower && lhs.GetFullName() != rhs.GetFullName() )
1016 count++;
1017 }
1018
1019 // If we are renaming a sheet that is only used once, then we are not going to cause
1020 // a case sensitivity issue.
1021 if( oldLower == rhsLower )
1022 return count > 1;
1023
1024 return count > 0;
1025 };
1026
1027 if( eeconfig()->m_Appearance.show_sheet_filename_case_sensitivity_dialog && can_cause_issues() )
1028 {
1029 msg.Printf( _( "The file name '%s' can cause issues with an existing file name\n"
1030 "already defined in the schematic on systems that support case\n"
1031 "insensitive file names. This will cause issues if you copy this\n"
1032 "project to an operating system that supports case insensitive file\n"
1033 "names.\n\nDo you wish to continue?" ),
1034 fn.GetName() );
1035
1036 wxRichMessageDialog dlg( this, msg, _( "Warning" ),
1037 wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION );
1038 dlg.ShowCheckBox( _( "Do not show this message again." ) );
1039 dlg.SetYesNoLabels( wxMessageDialog::ButtonLabel( _( "Create New Sheet" ) ),
1040 wxMessageDialog::ButtonLabel( _( "Cancel" ) ) );
1041
1042 if( dlg.ShowModal() == wxID_NO )
1043 return false;
1044
1046 !dlg.IsCheckBoxChecked();
1047 }
1048
1049 return true;
1050}
const char * name
constexpr EDA_IU_SCALE schIUScale
Definition base_units.h:130
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:599
PAGE_SETTINGS m_PageSettings
static const TOOL_EVENT SelectedItemsModified
Selected item had a property changed (except movement)
Definition actions.h:353
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.
static bool UrisAreEquivalent(const wxString &aURI1, const wxString &aURI2)
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.
PRINT_TITLEBLOCK_CONTEXT(SCH_EDIT_FRAME *aFrame, bool aPrintTitleBlock)
Definition sheet.cpp:872
SCH_EDIT_FRAME * m_frame
Definition sheet.cpp:885
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:276
Holds all the data relating to one schematic.
Definition schematic.h:149
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:171
SCH_SHEET & Root() const
Definition schematic.h:208
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
Schematic editor (Eeschema) main window.
bool AllowCaseSensitiveFileNameClashes(const wxString &aOldName, const wxString &aSchematicFileName)
Check aSchematicFileName for a potential file name case sensitivity clashes.
Definition sheet.cpp:984
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
bool RecalculateConnections(SCH_COMMIT *aCommit, SCH_CLEANUP_FLAGS aCleanupFlags, PROGRESS_REPORTER *aProgressReporter=nullptr, bool aCleanupDone=false)
Generate the connection data for the entire schematic hierarchy.
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:890
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:848
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:826
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:171
void Append(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
void SetPageSettings(const PAGE_INFO &aPageSettings)
Definition sch_screen.h:145
const wxString & GetFileName() const
Definition sch_screen.h:157
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:592
bool Remove(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
Remove aItem from the schematic associated with this screen.
int GetFileFormatVersionAtLoad() const
Definition sch_screen.h:142
TITLE_BLOCK & GetTitleBlock()
Definition sch_screen.h:168
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:398
wxString GetFileName() const
Return the filename corresponding to this sheet.
Definition sch_sheet.h:392
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:151
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:96
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:737
@ LAYER_DRAWINGSHEET
Sheet frame and title block.
Definition layer_ids.h:274
@ LAYER_SCHEMATIC_DRAWINGSHEET
Definition layer_ids.h:524
see class PGM_BASE
Definition of the SCH_SHEET_PATH and SCH_SHEET_LIST classes for Eeschema.
@ GLOBAL_CLEANUP
Definition schematic.h:95
const int scale
wxString message
wxLogTrace helper definitions.
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:708
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