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