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