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