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 (C) 2004-2024 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, you may find one here:
19 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20 * or you may search the http://www.gnu.org website for the version 2 license,
21 * or you may write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 */
24
25#include <sch_draw_panel.h>
26#include <confirm.h>
27#include <kiface_base.h>
28#include <project.h>
29#include <math/vector2wx.h>
31#include <tool/tool_manager.h>
32#include <project_sch.h>
33#include <sch_edit_frame.h>
35#include <sch_sheet.h>
36#include <sch_sheet_path.h>
37#include <sch_view.h>
38#include <sch_painter.h>
39#include <schematic.h>
40#include <symbol_lib_table.h>
42#include <tool/actions.h>
43
44#include <wx/clipbrd.h>
45#include <wx/dcmemory.h>
46#include <wx/log.h>
47#include <wx/msgdlg.h>
48#include <wx/richmsgdlg.h>
49
50
52{
53 wxASSERT( aSheet && aCurrentSheet );
54
55 wxString msg;
57 SCH_SHEET_LIST loadedSheets( aSheet ); // This is the schematicSheets of the loaded file.
58
59 wxString destFilePath = aCurrentSheet->LastScreen()->GetFileName();
60
61 if( destFilePath.IsEmpty() )
62 {
63 // If file is unsaved then there can't (yet) be any recursion.
64 return false;
65 }
66
67 // SCH_SCREEN object file paths are expected to be absolute. If this assert fires,
68 // something is seriously broken.
69 wxASSERT( wxFileName( destFilePath ).IsAbsolute() );
70
71 if( schematicSheets.TestForRecursion( loadedSheets, destFilePath ) )
72 {
73 msg.Printf( _( "The sheet changes cannot be made because the destination sheet already "
74 "has the sheet '%s' or one of its subsheets as a parent somewhere in the "
75 "schematic hierarchy." ),
76 destFilePath );
77 DisplayError( this, msg );
78 return true;
79 }
80
81 return false;
82}
83
84
86{
87 wxASSERT( aSheet && aSheet->GetScreen() );
88
89 wxString msg;
90 SCH_SCREENS newScreens( aSheet );
91
92 if( newScreens.HasNoFullyDefinedLibIds() )
93 {
94 msg.Printf( _( "The schematic '%s' has not had its symbol library links remapped "
95 "to the symbol library table. The project this schematic belongs to "
96 "must first be remapped before it can be imported into the current "
97 "project." ),
98 aSheet->GetScreen()->GetFileName() );
99 DisplayInfoMessage( this, msg );
100 return true;
101 }
102
103 return false;
104}
105
106
107void SCH_EDIT_FRAME::InitSheet( SCH_SHEET* aSheet, const wxString& aNewFilename )
108{
109 SCH_SCREEN* newScreen = new SCH_SCREEN( &Schematic() );
110 aSheet->SetScreen( newScreen );
111 aSheet->GetScreen()->SetContentModified();
112 aSheet->GetScreen()->SetFileName( aNewFilename );
113
115 wxCHECK( cfg, /* void */ );
116
118 newScreen->SetPageSettings( GetScreen()->GetPageSettings() );
119
120 const TITLE_BLOCK& tb1 = GetScreen()->GetTitleBlock();
121 TITLE_BLOCK tb2 = newScreen->GetTitleBlock();
122
124 tb2.SetRevision( tb1.GetRevision() );
125
126 if( cfg->m_PageSettings.export_date )
127 tb2.SetDate( tb1.GetDate() );
128
130 tb2.SetTitle( tb1.GetTitle() );
131
133 tb2.SetCompany( tb1.GetCompany() );
134
136 tb2.SetComment( 0, tb1.GetComment( 0 ) );
137
139 tb2.SetComment( 1, tb1.GetComment( 1 ) );
140
142 tb2.SetComment( 2, tb1.GetComment( 2 ) );
143
145 tb2.SetComment( 3, tb1.GetComment( 3 ) );
146
148 tb2.SetComment( 4, tb1.GetComment( 4 ) );
149
151 tb2.SetComment( 5, tb1.GetComment( 5 ) );
152
154 tb2.SetComment( 6, tb1.GetComment( 6 ) );
155
157 tb2.SetComment( 7, tb1.GetComment( 7 ) );
158
160 tb2.SetComment( 8, tb1.GetComment( 8 ) );
161
162 newScreen->SetTitleBlock( tb2 );
163}
164
165
167 const wxString& aFileName, bool aSkipRecursionCheck,
168 bool aSkipLibCheck )
169{
170 wxASSERT( aSheet && aCurrentSheet );
171
172 wxString msg;
173 wxFileName currentSheetFileName;
174 bool libTableChanged = false;
175
176 SCH_IO_MGR::SCH_FILE_T schFileType = SCH_IO_MGR::GuessPluginTypeFromSchPath( aFileName );
177
178 if( schFileType == SCH_IO_MGR::SCH_FILE_UNKNOWN )
179 schFileType = SCH_IO_MGR::SCH_KICAD;
180
181 IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( schFileType ) );
182 std::unique_ptr< SCH_SHEET> tmpSheet = std::make_unique<SCH_SHEET>( &Schematic() );
183
184 // This will cause the sheet UUID to be set to the UUID of the aSheet argument. This is
185 // required to ensure all of the sheet paths in any sub-sheets are correctly generated when
186 // using the temporary SCH_SHEET object that the file is loaded into..
187 const_cast<KIID&>( tmpSheet->m_Uuid ) = aSheet->m_Uuid;
188
189 wxFileName fileName( aFileName );
190
191 if( !fileName.IsAbsolute() && !fileName.MakeAbsolute() )
192 {
193 wxFAIL_MSG( wxString::Format( "Cannot make file name '%s' path absolute.", aFileName ) );
194 return false;
195 }
196
197 wxString fullFilename = fileName.GetFullPath();
198
199 try
200 {
201 if( aSheet->GetScreen() != nullptr )
202 {
203 tmpSheet.reset( pi->LoadSchematicFile( fullFilename, &Schematic() ) );
204 }
205 else
206 {
207 tmpSheet->SetFileName( fullFilename );
208 pi->LoadSchematicFile( fullFilename, &Schematic(), tmpSheet.get() );
209 }
210
211 if( !pi->GetError().IsEmpty() )
212 {
213 msg = _( "The entire schematic could not be loaded. Errors occurred attempting "
214 "to load hierarchical sheet schematics." );
215
216 wxMessageDialog msgDlg1( this, msg, _( "Schematic Load Error" ),
217 wxOK | wxCANCEL | wxCANCEL_DEFAULT |
218 wxCENTER | wxICON_QUESTION );
219 msgDlg1.SetOKLabel( wxMessageDialog::ButtonLabel( _( "Use partial schematic" ) ) );
220 msgDlg1.SetExtendedMessage( pi->GetError() );
221
222 if( msgDlg1.ShowModal() == wxID_CANCEL )
223 return false;
224 }
225 }
226 catch( const IO_ERROR& ioe )
227 {
228 msg.Printf( _( "Error loading schematic '%s'." ), fullFilename );
229 DisplayErrorMessage( this, msg, ioe.What() );
230
231 msg.Printf( _( "Failed to load '%s'." ), fullFilename );
232 SetMsgPanel( wxEmptyString, msg );
233
234 return false;
235 }
236
237 // If the loaded schematic is in a different folder from the current project and
238 // it contains hierarchical sheets, the hierarchical sheet paths need to be updated.
239 //
240 // Additionally, we need to make all backing screens absolute paths be in the current project
241 // path not the source path.
242 if( fileName.GetPathWithSep() != Prj().GetProjectPath() )
243 {
244 SCH_SHEET_LIST loadedSheets( tmpSheet.get() );
245
246 for( const SCH_SHEET_PATH& sheetPath : loadedSheets )
247 {
248 wxString lastSheetPath = Prj().GetProjectPath();
249
250 for( unsigned i = 0; i < sheetPath.size(); i++ )
251 {
252 SCH_SHEET* sheet = sheetPath.at( i );
253 wxCHECK2( sheet, continue );
254
255 SCH_SCREEN* screen = sheet->GetScreen();
256 wxCHECK2( screen, continue );
257
258 // Fix screen path to be based on the current project path.
259 // Basically, make an absolute screen path relative to the schematic file
260 // we started with, then make it absolute again using the current project path.
261 wxFileName screenFileName = screen->GetFileName();
262 screenFileName.MakeRelativeTo( fileName.GetPath() );
263 screenFileName.MakeAbsolute( Prj().GetProjectPath() );
264 screen->SetFileName( screenFileName.GetFullPath() );
265
266 // Use the screen file name which should always be absolute.
267 wxFileName loadedSheetFileName = screen->GetFileName();
268 wxCHECK2( loadedSheetFileName.IsAbsolute(), continue );
269
270 wxFileName tmp = loadedSheetFileName;
271 wxString sheetFileName;
272
273 if( tmp.MakeRelativeTo( lastSheetPath ) )
274 sheetFileName = tmp.GetFullPath();
275 else
276 sheetFileName = loadedSheetFileName.GetFullPath();
277
278 sheet->SetFileName( sheetFileName );
279 lastSheetPath = loadedSheetFileName.GetPath();
280 }
281 }
282 }
283
284 SCH_SHEET_LIST loadedSheets( tmpSheet.get() );
286
287 // Make sure any new sheet changes do not cause any recursion issues.
288 if( !aSkipRecursionCheck && CheckSheetForRecursion( tmpSheet.get(), aCurrentSheet ) )
289 return false;
290
291 if( checkForNoFullyDefinedLibIds( tmpSheet.get() ) )
292 return false;
293
294 // Make a valiant attempt to warn the user of all possible scenarios where there could
295 // be broken symbol library links.
296 wxArrayString names;
297 wxArrayString newLibNames;
298 SCH_SCREENS newScreens( tmpSheet.get() ); // All screens associated with the import.
299 SCH_SCREENS prjScreens( &Schematic().Root() );
300
301 newScreens.GetLibNicknames( names );
302
303 wxMessageDialog::ButtonLabel okButtonLabel( _( "Continue Load" ) );
304 wxMessageDialog::ButtonLabel cancelButtonLabel( _( "Cancel Load" ) );
305
306 // Prior to schematic file format 20221002, all symbol instance data was saved in the root
307 // sheet so loading a hierarchical sheet that is not the root sheet will have no symbol
308 // instance data. Give the user a chance to go back and save the project that contains this
309 // hierarchical sheet so the symbol instance data will be correct on load.
310 if( ( tmpSheet->GetScreen()->GetFileFormatVersionAtLoad() < 20221002 )
311 && tmpSheet->GetScreen()->GetSymbolInstances().empty() )
312 {
313 msg = _( "There are hierarchical sheets in the loaded schematic file from an older "
314 "file version resulting in missing symbol instance data. This will "
315 "result in all of the symbols in the loaded schematic to use either the "
316 "default instance setting or fall back to the library symbol settings. "
317 "Loading the project that uses this schematic file and saving to the "
318 "lastest file version will resolve this issue.\n\n"
319 "Do you wish to continue?" );
320 wxMessageDialog msgDlg7( this, msg, _( "Continue Load Schematic" ),
321 wxOK | wxCANCEL | wxCANCEL_DEFAULT | wxCENTER | wxICON_QUESTION );
322 msgDlg7.SetOKCancelLabels( okButtonLabel, cancelButtonLabel );
323
324 if( msgDlg7.ShowModal() == wxID_CANCEL )
325 return false;
326 }
327
328 if( !prjScreens.HasSchematic( fullFilename ) )
329 {
330 if( fileName.GetPathWithSep() == Prj().GetProjectPath() )
331 {
332 // A schematic in the current project path that isn't part of the current project.
333 // It's possible the user copied this schematic from another project so the library
334 // links may not be available. Even this is check is no guarantee that all symbol
335 // library links are valid but it's better than nothing.
336 for( const wxString& name : names )
337 {
338 if( !PROJECT_SCH::SchSymbolLibTable( &Prj() )->HasLibrary( name ) )
339 newLibNames.Add( name );
340 }
341
342 if( !newLibNames.IsEmpty() )
343 {
344 msg = _( "There are library names in the selected schematic that are missing "
345 "from the current project library table. This may result in broken "
346 "symbol library references for the loaded schematic.\n\n"
347 "Do you wish to continue?" );
348 wxMessageDialog msgDlg3( this, msg, _( "Continue Load Schematic" ),
349 wxOK | wxCANCEL | wxCANCEL_DEFAULT |
350 wxCENTER | wxICON_QUESTION );
351 msgDlg3.SetOKCancelLabels( okButtonLabel, cancelButtonLabel );
352
353 if( msgDlg3.ShowModal() == wxID_CANCEL )
354 return false;
355 }
356 }
357 else if( fileName.GetPathWithSep() != Prj().GetProjectPath() )
358 {
359 // A schematic loaded from a path other than the current project path.
360
361 // If there are symbol libraries in the imported schematic that are not in the
362 // symbol library table of this project, there could be a lot of broken symbol
363 // library links. Attempt to add the missing libraries to the project symbol
364 // library table.
365 wxArrayString duplicateLibNames;
366
367 for( const wxString& name : names )
368 {
369 if( !PROJECT_SCH::SchSymbolLibTable( &Prj() )->HasLibrary( name ) )
370 newLibNames.Add( name );
371 else
372 duplicateLibNames.Add( name );
373 }
374
375 SYMBOL_LIB_TABLE table;
376 wxFileName symLibTableFn( fileName.GetPath(),
378
379 // If there are any new or duplicate libraries, check to see if it's possible that
380 // there could be any missing libraries that would cause broken symbol library links.
381 if( !aSkipLibCheck && ( !newLibNames.IsEmpty() || !duplicateLibNames.IsEmpty() ) )
382 {
383 if( !symLibTableFn.Exists() || !symLibTableFn.IsFileReadable() )
384 {
385 msg = _( "The selected file was created as part of a different project. "
386 "Linking the file to this project may result in missing or "
387 "incorrect symbol library references.\n\n"
388 "Do you wish to continue?" );
389 wxMessageDialog msgDlg4( this, msg, _( "Continue Load Schematic" ),
390 wxOK | wxCANCEL | wxCANCEL_DEFAULT | wxCENTER
391 | wxICON_QUESTION );
392 msgDlg4.SetOKCancelLabels( okButtonLabel, cancelButtonLabel );
393
394 if( msgDlg4.ShowModal() == wxID_CANCEL )
395 return false;
396 }
397 else
398 {
399 try
400 {
401 table.Load( symLibTableFn.GetFullPath() );
402 }
403 catch( const IO_ERROR& ioe )
404 {
405 msg.Printf( _( "Error loading the symbol library table '%s'." ),
406 symLibTableFn.GetFullPath() );
407 DisplayErrorMessage( nullptr, msg, ioe.What() );
408 return false;
409 }
410 }
411 }
412
413 // Check to see if any of the symbol libraries found in the appended schematic do
414 // not exist in the current project are missing from the appended project symbol
415 // library table.
416 if( !newLibNames.IsEmpty() )
417 {
418 bool missingLibNames = table.IsEmpty();
419
420 if( !missingLibNames )
421 {
422 for( const wxString& newLibName : newLibNames )
423 {
424 if( !table.HasLibrary( newLibName ) )
425 {
426 missingLibNames = true;
427 break;
428 }
429 }
430 }
431
432 if( missingLibNames )
433 {
434 msg = _( "There are symbol library names in the selected schematic that "
435 "are missing from the selected schematic project library table. "
436 "This may result in broken symbol library references.\n\n"
437 "Do you wish to continue?" );
438 wxMessageDialog msgDlg5( this, msg, _( "Continue Load Schematic" ),
439 wxOK | wxCANCEL | wxCANCEL_DEFAULT |
440 wxCENTER | wxICON_QUESTION );
441 msgDlg5.SetOKCancelLabels( okButtonLabel, cancelButtonLabel );
442
443 if( msgDlg5.ShowModal() == wxID_CANCEL )
444 return false;
445 }
446 }
447
448 // The library name already exists in the current project. Check to see if the
449 // duplicate name is the same library in the current project. If it's not, it's
450 // most likely that the symbol library links will be broken.
451 if( !duplicateLibNames.IsEmpty() && !table.IsEmpty() )
452 {
453 bool libNameConflict = false;
454
455 for( const wxString& duplicateLibName : duplicateLibNames )
456 {
457 const SYMBOL_LIB_TABLE_ROW* thisRow = nullptr;
458 const SYMBOL_LIB_TABLE_ROW* otherRow = nullptr;
459
460 if( PROJECT_SCH::SchSymbolLibTable( &Prj() )->HasLibrary( duplicateLibName ) )
461 thisRow = PROJECT_SCH::SchSymbolLibTable( &Prj() )->FindRow( duplicateLibName );
462
463 if( table.HasLibrary( duplicateLibName ) )
464 otherRow = table.FindRow( duplicateLibName );
465
466 // It's in the global library table so there is no conflict.
467 if( thisRow && !otherRow )
468 continue;
469
470 if( !thisRow || !otherRow )
471 continue;
472
473 wxFileName otherUriFileName;
474 wxString thisURI = thisRow->GetFullURI( true );
475 wxString otherURI = otherRow->GetFullURI( false);
476
477 if( otherURI.Contains( "${KIPRJMOD}" ) || otherURI.Contains( "$(KIPRJMOD)" ) )
478 {
479 // Cannot use relative paths here, "${KIPRJMOD}../path-to-cache-lib" does
480 // not expand to a valid symbol library path.
481 otherUriFileName.SetPath( fileName.GetPath() );
482 otherUriFileName.SetFullName( otherURI.AfterLast( '}' ) );
483 otherURI = otherUriFileName.GetFullPath();
484 }
485
486 if( thisURI != otherURI )
487 {
488 libNameConflict = true;
489 break;
490 }
491 }
492
493 if( libNameConflict )
494 {
495 msg = _( "A duplicate library name that references a different library exists "
496 "in the current library table. This conflict cannot be resolved and "
497 "may result in broken symbol library references.\n\n"
498 "Do you wish to continue?" );
499 wxMessageDialog msgDlg6( this, msg, _( "Continue Load Schematic" ),
500 wxOK | wxCANCEL | wxCANCEL_DEFAULT |
501 wxCENTER | wxICON_QUESTION );
502 msgDlg6.SetOKCancelLabels( okButtonLabel, cancelButtonLabel );
503
504 if( msgDlg6.ShowModal() == wxID_CANCEL )
505 return false;
506 }
507 }
508
509 // All (most?) of the possible broken symbol library link cases are covered. Map the
510 // new appended schematic project symbol library table entries to the current project
511 // symbol library table.
512 if( !newLibNames.IsEmpty() && !table.IsEmpty() )
513 {
514 for( const wxString& libName : newLibNames )
515 {
516 if( !table.HasLibrary( libName )
517 || PROJECT_SCH::SchSymbolLibTable( &Prj() )->HasLibrary( libName ) )
518 {
519 continue;
520 }
521
522 // Don't expand environment variable because KIPRJMOD will not be correct
523 // for a different project.
524 wxString uri = table.GetFullURI( libName, false );
525 wxFileName newLib;
526
527 if( uri.Contains( "${KIPRJMOD}" ) || uri.Contains( "$(KIPRJMOD)" ) )
528 {
529 // Cannot use relative paths here, "${KIPRJMOD}../path-to-cache-lib" does
530 // not expand to a valid symbol library path.
531 newLib.SetPath( fileName.GetPath() );
532 newLib.SetFullName( uri.AfterLast( '}' ) );
533 uri = newLib.GetFullPath();
534 }
535 else
536 {
537 uri = table.GetFullURI( libName );
538 }
539
540 // Add the library from the imported project to the current project
541 // symbol library table.
542 const SYMBOL_LIB_TABLE_ROW* row = table.FindRow( libName );
543
544 wxCHECK( row, false );
545
546 SYMBOL_LIB_TABLE_ROW* newRow = new SYMBOL_LIB_TABLE_ROW( libName, uri,
547 row->GetType(),
548 row->GetOptions(),
549 row->GetDescr() );
550
552 libTableChanged = true;
553 }
554 }
555 }
556 }
557
558 SCH_SCREEN* newScreen = tmpSheet->GetScreen();
559 wxCHECK_MSG( newScreen, false, "No screen defined for sheet." );
560
561 if( libTableChanged )
562 {
563 PROJECT_SCH::SchSymbolLibTable( &Prj() )->Save( Prj().GetProjectPath() +
565 }
566
567 // Make the best attempt to set the symbol instance data for the loaded scheamtic.
568 if( newScreen->GetFileFormatVersionAtLoad() < 20221002 )
569 {
570 if( !newScreen->GetSymbolInstances().empty() )
571 {
572 // If the loaded schematic is a root sheet for another project, update the symbol
573 // instances.
574 loadedSheets.UpdateSymbolInstanceData( newScreen->GetSymbolInstances());
575 }
576 }
577
578 newScreen->MigrateSimModels();
579
580 // Attempt to create new symbol instances using the instance data loaded above.
581 loadedSheets.AddNewSymbolInstances( *aCurrentSheet, Prj().GetProjectName() );
582
583 // Add new sheet instance data.
584 loadedSheets.AddNewSheetInstances( *aCurrentSheet, schematicSheets.GetLastVirtualPageNumber() );
585
586 // It is finally safe to add or append the imported schematic.
587 if( aSheet->GetScreen() == nullptr )
588 aSheet->SetScreen( newScreen );
589 else
590 aSheet->GetScreen()->Append( newScreen );
591
592 SCH_SCREENS allLoadedScreens( aSheet );
593 allLoadedScreens.ReplaceDuplicateTimeStamps();
594
595 return true;
596}
597
598
600 bool* aIsUndoable, bool* aClearAnnotationNewItems,
601 bool* aUpdateHierarchyNavigator )
602{
603 if( aSheet == nullptr || aHierarchy == nullptr )
604 return false;
605
606 // Get the new texts
607 DIALOG_SHEET_PROPERTIES dlg( this, aSheet, aIsUndoable, aClearAnnotationNewItems,
608 aUpdateHierarchyNavigator );
609
610 if( dlg.ShowModal() == wxID_CANCEL )
611 return false;
612
614
615 return true;
616}
617
618
620{
621 wxRect drawArea;
622 BASE_SCREEN* screen = GetScreen();
623
624 drawArea.SetSize( ToWxSize( GetPageSizeIU() ) );
625
626 // Calculate a reasonable dc size, in pixels, and the dc scale to fit
627 // the drawings into the dc size
628 // scale is the ratio resolution (in PPI) / internal units
629 double ppi = 300; // Use 300 pixels per inch to create bitmap images on start
630 double inch2Iu = 1000.0 * schIUScale.IU_PER_MILS;
631 double scale = ppi / inch2Iu;
632
633 wxSize dcsize = drawArea.GetSize();
634
635 int maxdim = std::max( dcsize.x, dcsize.y );
636
637 // the max size in pixels of the bitmap used to build the sheet copy
638 const int maxbitmapsize = 5600;
639
640 while( int( maxdim * scale ) > maxbitmapsize )
641 {
642 ppi = ppi / 1.5;
643 scale = ppi / inch2Iu;
644 }
645
646 dcsize.x *= scale;
647 dcsize.y *= scale;
648
649 // Set draw offset, zoom... to values needed to draw in the memory DC
650 // after saving initial values:
651 VECTOR2I tmp_startvisu = screen->m_StartVisu;
652 VECTOR2I old_org = screen->m_DrawOrg;
653 screen->m_DrawOrg.x = screen->m_DrawOrg.y = 0;
654 screen->m_StartVisu.x = screen->m_StartVisu.y = 0;
655
656 wxMemoryDC dc;
657 wxBitmap image( dcsize );
658 dc.SelectObject( image );
659 dc.Clear();
660
661 GRResetPenAndBrush( &dc );
662 GRForceBlackPen( false );
663 dc.SetUserScale( scale, scale );
664
666
667 cfg->SetPrintDC( &dc );
668
669 // Init the color of the layer actually used to print the drawing sheet:
671
672 cfg->SetDefaultFont( eeconfig()->m_Appearance.default_font );
673
674 PrintPage( cfg );
675
676 // Deselect Bitmap from DC before using the bitmap
677 dc.SelectObject( wxNullBitmap );
678
679 {
680 wxLogNull doNotLog; // disable logging of failed clipboard actions
681
682 if( wxTheClipboard->Open() )
683 {
684 // This data objects are held by the clipboard, so do not delete them in the app.
685 wxBitmapDataObject* clipbrd_data = new wxBitmapDataObject( image );
686 wxTheClipboard->SetData( clipbrd_data );
687 wxTheClipboard->Flush(); // Allow data to be available after closing KiCad
688 wxTheClipboard->Close();
689 }
690 }
691
692 GRForceBlackPen( false );
693
694 screen->m_StartVisu = tmp_startvisu;
695 screen->m_DrawOrg = old_org;
696}
697
698
699bool SCH_EDIT_FRAME::AllowCaseSensitiveFileNameClashes( const wxString& aOldName, const wxString& aSchematicFileName )
700{
701 wxString msg;
703 wxFileName fn = aSchematicFileName;
704
705 wxCHECK( fn.IsAbsolute(), false );
706
707 auto can_cause_issues = [&]() -> bool
708 {
709 wxFileName lhs;
710 wxFileName rhs = aSchematicFileName;
711 wxFileName old = aOldName;
712 wxString oldLower = old.GetFullName().Lower();
713 wxString rhsLower = rhs.GetFullName().Lower();
714 wxString lhsLower;
715
716 size_t count = 0;
717
718 wxCHECK( rhs.IsAbsolute(), false );
719
720 for( SCH_SHEET_PATH& sheet : sheets )
721 {
722 lhs = sheet.LastScreen()->GetFileName();
723
724 if( lhs.GetPath() != rhs.GetPath() )
725 continue;
726
727 lhsLower = lhs.GetFullName().Lower();
728
729 if( lhsLower == rhsLower && lhs.GetFullName() != rhs.GetFullName() )
730 count++;
731 }
732
733 // If we are renaming a sheet that is only used once, then we are not going to cause
734 // a case sensitivity issue.
735 if( oldLower == rhsLower )
736 return count > 1;
737
738 return count > 0;
739 };
740
741 if( eeconfig()->m_Appearance.show_sheet_filename_case_sensitivity_dialog && can_cause_issues() )
742 {
743 msg.Printf( _( "The file name '%s' can cause issues with an existing file name\n"
744 "already defined in the schematic on systems that support case\n"
745 "insensitive file names. This will cause issues if you copy this\n"
746 "project to an operating system that supports case insensitive file\n"
747 "names.\n\nDo you wish to continue?" ),
748 fn.GetName() );
749
750 wxRichMessageDialog dlg( this, msg, _( "Warning" ),
751 wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION );
752 dlg.ShowCheckBox( _( "Do not show this message again." ) );
753 dlg.SetYesNoLabels( wxMessageDialog::ButtonLabel( _( "Create New Sheet" ) ),
754 wxMessageDialog::ButtonLabel( _( "Cancel" ) ) );
755
756 if( dlg.ShowModal() == wxID_NO )
757 return false;
758
760 !dlg.IsCheckBoxChecked();
761 }
762
763 return true;
764}
const char * name
Definition: DXF_plotter.cpp:57
constexpr EDA_IU_SCALE schIUScale
Definition: base_units.h:110
Handles how to draw a screen (a board, a schematic ...)
Definition: base_screen.h:41
VECTOR2I m_DrawOrg
offsets for drawing the circuit on the screen
Definition: base_screen.h:88
VECTOR2I m_StartVisu
Coordinates in drawing units of the current view position (upper left corner of device)
Definition: base_screen.h:93
void SetContentModified(bool aModified=true)
Definition: base_screen.h:59
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:489
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:278
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
Definition: ki_exception.h:77
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:30
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:49
const wxString & GetOptions() const
Return the options string, which may hold a password or anything else needed to instantiate the under...
const wxString & GetDescr() const
Return the description of the library referenced by this row.
const wxString GetFullURI(bool aSubstituted=false) const
Return the full location specifying URI for the LIB, either in original UI form or in environment var...
bool HasLibrary(const wxString &aNickname, bool aCheckEnabled=false) const
Test for the existence of aNickname in the library table.
bool InsertRow(LIB_TABLE_ROW *aRow, bool doReplace=false)
Adds aRow if it does not already exist or if doReplace is true.
void Load(const wxString &aFileName)
Load the library table using the path defined by aFileName aFallBackTable.
wxString GetFullURI(const wxString &aLibNickname, bool aExpandEnvVars=true) const
Return the full URI of the library mapped to aLibNickname.
bool IsEmpty(bool aIncludeFallback=true)
Return true if the table is empty.
void Save(const wxString &aFileName) const
Write this library table to aFileName in s-expression form.
static SYMBOL_LIB_TABLE * SchSymbolLibTable(PROJECT *aProject)
Accessor for project symbol library table.
virtual const wxString GetProjectPath() const
Return the full path of the project.
Definition: project.cpp:135
SCH_SHEET_LIST BuildUnorderedSheetList() const
Definition: schematic.h:101
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
bool AllowCaseSensitiveFileNameClashes(const wxString &aOldName, const wxString &aSchematicFileName)
Check aSchematicFileName for a potential file name case sensitivity clashes.
Definition: sheet.cpp:699
bool EditSheetProperties(SCH_SHEET *aSheet, SCH_SHEET_PATH *aHierarchy, bool *aIsUndoable=nullptr, bool *aClearAnnotationNewItems=nullptr, bool *aUpdateHierarchyNavigator=nullptr)
Edit an existing sheet or add a new sheet to the schematic.
Definition: sheet.cpp:599
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:107
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:166
SCHEMATIC & Schematic() const
void DrawCurrentSheetToClipboard()
Use the wxWidgets print code to draw an image of the current sheet onto the clipboard.
Definition: sheet.cpp:619
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:85
bool CheckSheetForRecursion(SCH_SHEET *aSheet, SCH_SHEET_PATH *aCurrentSheet)
Verify that aSheet will not cause a recursion error in aCurrentSheet.
Definition: sheet.cpp:51
virtual void PrintPage(const RENDER_SETTINGS *aSettings) override
Plot or print the current sheet to the clipboard.
static SCH_FILE_T GuessPluginTypeFromSchPath(const wxString &aSchematicPath, int aCtl=0)
Return a plugin type given a schematic using the file extension of aSchematicPath.
Definition: sch_io_mgr.cpp:165
Container class that holds multiple SCH_SCREEN objects in a hierarchy.
Definition: sch_screen.h:712
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:156
void Append(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
Definition: sch_screen.cpp:153
void SetPageSettings(const PAGE_INFO &aPageSettings)
Definition: sch_screen.h:131
const wxString & GetFileName() const
Definition: sch_screen.h:143
void SetFileName(const wxString &aFileName)
Set the file name for this screen to aFileName.
Definition: sch_screen.cpp:118
const std::vector< SCH_SYMBOL_INSTANCE > & GetSymbolInstances() const
Definition: sch_screen.h:521
int GetFileFormatVersionAtLoad() const
Definition: sch_screen.h:128
const TITLE_BLOCK & GetTitleBlock() const
Definition: sch_screen.h:154
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)
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:57
void SetFileName(const wxString &aFilename)
Definition: sch_sheet.h:312
SCH_SCREEN * GetScreen() const
Definition: sch_sheet.h:110
void SetScreen(SCH_SCREEN *aScreen)
Set the SCH_SCREEN associated with this sheet to aScreen.
Definition: sch_sheet.cpp:172
Hold a record identifying a symbol library accessed by the appropriate symbol library SCH_IO object i...
const wxString GetType() const override
Return the type of symbol library table represented by this row.
static const wxString & GetSymbolLibTableFileName()
SYMBOL_LIB_TABLE_ROW * FindRow(const wxString &aNickName, bool aCheckIfEnabled=false)
Return an SYMBOL_LIB_TABLE_ROW if aNickName is found in this table or in any chained fallBack table f...
Hold the information shown in the lower right corner of a plot, printout, or editing view.
Definition: title_block.h:41
const wxString & GetCompany() const
Definition: title_block.h:96
void SetRevision(const wxString &aRevision)
Definition: title_block.h:81
void SetComment(int aIdx, const wxString &aComment)
Definition: title_block.h:101
const wxString & GetRevision() const
Definition: title_block.h:86
void SetTitle(const wxString &aTitle)
Definition: title_block.h:58
const wxString & GetDate() const
Definition: title_block.h:76
const wxString & GetComment(int aIdx) const
Definition: title_block.h:107
void SetCompany(const wxString &aCompany)
Definition: title_block.h:91
const wxString & GetTitle() const
Definition: title_block.h:63
void SetDate(const wxString &aDate)
Set the date field, and defaults to the current time and date.
Definition: title_block.h:71
TOOL_MANAGER * m_toolManager
Definition: tools_holder.h:167
bool ProcessEvent(const TOOL_EVENT &aEvent)
Propagate an event to tools that requested events of matching type(s).
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:170
void DisplayInfoMessage(wxWindow *aParent, const wxString &aMessage, const wxString &aExtraInfo)
Display an informational message box with aMessage.
Definition: confirm.cpp:222
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition: confirm.cpp:195
This file is part of the common library.
#define _(s)
void GRForceBlackPen(bool flagforce)
Definition: gr_basic.cpp:159
void GRResetPenAndBrush(wxDC *DC)
Definition: gr_basic.cpp:73
std::unique_ptr< T > IO_RELEASER
Helper to hold and release an IO_BASE object when exceptions are thrown.
Definition: io_mgr.h:33
PROJECT & Prj()
Definition: kicad.cpp:595
@ LAYER_DRAWINGSHEET
drawingsheet frame and titleblock
Definition: layer_ids.h:219
@ LAYER_SCHEMATIC_DRAWINGSHEET
Definition: layer_ids.h:397
Definition of the SCH_SHEET_PATH and SCH_SHEET_LIST classes for Eeschema.
const int scale
const double IU_PER_MILS
Definition: base_units.h:77
wxSize ToWxSize(const VECTOR2I &aSize)
Definition: vector2wx.h:55
Definition of file extensions used in Kicad.