KiCad PCB EDA Suite
Loading...
Searching...
No Matches
pcbnew/files.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) 2004-2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
5 * Copyright (C) 2011 Wayne Stambaugh <[email protected]>
6 * Copyright (C) 2023 CERN (www.cern.ch)
7 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, you may find one here:
21 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
22 * or you may search the http://www.gnu.org website for the version 2 license,
23 * or you may write to the Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
25 */
26
27#include <string>
28#include <vector>
29
30#include <confirm.h>
31#include <kidialog.h>
32#include <core/arraydim.h>
33#include <core/profile.h>
34#include <thread_pool.h>
35#include <gestfich.h>
36#include <local_history.h>
37#include <pcb_edit_frame.h>
41#include <kiface_base.h>
42#include <macros.h>
43#include <trace_helpers.h>
45#include <lockfile.h>
46#include <wx/snglinst.h>
48#include <pcbnew_id.h>
50#include <tool/tool_manager.h>
51#include <board.h>
52#include <collectors.h>
54#include <kiplatform/app.h>
55#include <kiplatform/ui.h>
57#include <widgets/wx_infobar.h>
60#include <paths.h>
61#include <pgm_base.h>
63#include <project_pcb.h>
67#include <pcb_io/pcb_io_mgr.h>
75#include <tools/pcb_actions.h>
77#include <board_commit.h>
78#include <reporter.h>
79#include <zone_filler.h>
81#include <widgets/kistatusbar.h>
83#include <wx_filename.h> // For ::ResolvePossibleSymlinks()
84#include <kiplatform/io.h>
85
86#include <wx/stdpaths.h>
87#include <wx/ffile.h>
88#include <wx/filedlg.h>
89#include <wx/txtstrm.h>
90#include <wx/wfstream.h>
91#include <wx/zipstrm.h>
92#include <wx/dir.h>
93
95
96//#define USE_INSTRUMENTATION 1
97#define USE_INSTRUMENTATION 0
98
99static const wxChar* const traceAllegroPerf = wxT( "KICAD_ALLEGRO_PERF" );
100
101
111bool AskLoadBoardFileName( PCB_EDIT_FRAME* aParent, wxString* aFileName, int aCtl = 0 )
112{
113 std::vector<IO_BASE::IO_FILE_DESC> descriptions;
114
115 for( const auto& plugin : PCB_IO_MGR::PLUGIN_REGISTRY::Instance()->AllPlugins() )
116 {
117 bool isKiCad = plugin.m_type == PCB_IO_MGR::KICAD_SEXP || plugin.m_type == PCB_IO_MGR::LEGACY;
118
119 if( ( aCtl & KICTL_KICAD_ONLY ) && !isKiCad )
120 continue;
121
122 if( ( aCtl & KICTL_NONKICAD_ONLY ) && isKiCad )
123 continue;
124
125 IO_RELEASER<PCB_IO> pi( plugin.m_createFunc() );
126 wxCHECK( pi, false );
127
128 const IO_BASE::IO_FILE_DESC& desc = pi->GetBoardFileDesc();
129
130 if( desc.m_FileExtensions.empty() || !desc.m_CanRead )
131 continue;
132
133 descriptions.emplace_back( desc );
134 }
135
136 wxString fileFiltersStr;
137 std::vector<std::string> allExtensions;
138 std::set<wxString> allWildcardsSet;
139
140 for( const IO_BASE::IO_FILE_DESC& desc : descriptions )
141 {
142 if( !fileFiltersStr.IsEmpty() )
143 fileFiltersStr += wxChar( '|' );
144
145 fileFiltersStr += desc.FileFilter();
146
147 for( const std::string& ext : desc.m_FileExtensions )
148 {
149 allExtensions.emplace_back( ext );
150 allWildcardsSet.insert( wxT( "*." ) + formatWildcardExt( ext ) + wxT( ";" ) );
151 }
152 }
153
154 wxString allWildcardsStr;
155
156 for( const wxString& wildcard : allWildcardsSet )
157 allWildcardsStr << wildcard;
158
159 if( aCtl & KICTL_KICAD_ONLY )
160 {
161 fileFiltersStr = _( "All KiCad Board Files" ) + AddFileExtListToFilter( allExtensions );
162 }
163 else
164 {
165 fileFiltersStr = _( "All supported formats" ) + wxT( "|" ) + allWildcardsStr + wxT( "|" )
166 + fileFiltersStr;
167 }
168
169 wxFileName fileName( *aFileName );
170 wxString path;
171 wxString name;
172
173 if( fileName.FileExists() )
174 {
175 path = fileName.GetPath();
176 name = fileName.GetFullName();
177 }
178 else
179 {
180 path = aParent->GetMruPath();
181
182 if( path.IsEmpty() )
184 // leave name empty
185 }
186
187 bool kicadFormat = ( aCtl & KICTL_KICAD_ONLY );
188
189 wxFileDialog dlg( aParent, kicadFormat ? _( "Open Board File" ) : _( "Import Non KiCad Board File" ),
190 path, name, fileFiltersStr, wxFD_OPEN | wxFD_FILE_MUST_EXIST );
191
192 FILEDLG_IMPORT_NON_KICAD importOptions( aParent->config()->m_System.show_import_issues );
193
194 if( !kicadFormat )
195 dlg.SetCustomizeHook( importOptions );
196
198
199 if( dlg.ShowModal() == wxID_OK )
200 {
201 *aFileName = dlg.GetPath();
202 aParent->SetMruPath( wxFileName( dlg.GetPath() ).GetPath() );
203
204 if( !kicadFormat )
205 aParent->config()->m_System.show_import_issues = importOptions.GetShowIssues();
206
207 return true;
208 }
209 else
210 {
211 return false;
212 }
213}
214
215
225bool AskSaveBoardFileName( PCB_EDIT_FRAME* aParent, wxString* aFileName, bool* aCreateProject )
226{
227 wxString wildcard = FILEEXT::PcbFileWildcard();
228 wxFileName fn = *aFileName;
229
231
232 wxFileDialog dlg( aParent, _( "Save Board File As" ), fn.GetPath(), fn.GetFullName(), wildcard,
233 wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
234
235// Add a "Create a project" checkbox in standalone mode and one isn't loaded
236 FILEDLG_HOOK_SAVE_PROJECT newProjectHook;
237
238 if( Kiface().IsSingle() && aParent->Prj().IsNullProject() )
239 dlg.SetCustomizeHook( newProjectHook );
240
242
243 if( dlg.ShowModal() != wxID_OK )
244 return false;
245
246 *aFileName = dlg.GetPath();
247 *aFileName = EnsureFileExtension( *aFileName, FILEEXT::KiCadPcbFileExtension );
248
249 if( newProjectHook.IsAttachedToDialog() )
250 *aCreateProject = newProjectHook.GetCreateNewProject();
251 else if( !aParent->Prj().IsNullProject() )
252 *aCreateProject = true;
253
254 return true;
255}
256
257
258void PCB_EDIT_FRAME::OnFileHistory( wxCommandEvent& event )
259{
260 wxString filename = GetFileFromHistory( event.GetId(), _( "Printed circuit board" ) );
261
262 if( !filename.IsEmpty() )
263 {
264 if( !wxFileName::IsFileReadable( filename ) )
265 {
266 if( !AskLoadBoardFileName( this, &filename, KICTL_KICAD_ONLY ) )
267 return;
268 }
269
270 OpenProjectFiles( std::vector<wxString>( 1, filename ), KICTL_KICAD_ONLY );
271 }
272}
273
274
275void PCB_EDIT_FRAME::OnClearFileHistory( wxCommandEvent& aEvent )
276{
278}
279
280
282{
283 // Only standalone mode can directly load a new document
284 if( !Kiface().IsSingle() )
285 return false;
286
287 int open_ctl = KICTL_KICAD_ONLY;
288 wxString fileName = m_frame->Prj().AbsolutePath( m_frame->GetBoard()->GetFileName() );
289
290 if( AskLoadBoardFileName( m_frame, &fileName, open_ctl ) )
291 m_frame->OpenProjectFiles( std::vector<wxString>( 1, fileName ), open_ctl );
292
293 return 0;
294}
295
296
298{
299 // Note: we explicitly allow this even if not in standalone mode for now, even though it is dangerous.
300 int open_ctl = KICTL_NONKICAD_ONLY;
301 wxString fileName; // = Prj().AbsolutePath( GetBoard()->GetFileName() );
302
303 if( AskLoadBoardFileName( m_frame, &fileName, open_ctl ) )
304 m_frame->OpenProjectFiles( std::vector<wxString>( 1, fileName ), open_ctl );
305
306 return 0;
307}
308
309
311{
312 wxFileName fn = m_frame->Prj().AbsolutePath( m_frame->GetBoard()->GetFileName() );
313
314 if( !IsOK( m_frame, wxString::Format( _( "Revert '%s' to last version saved?" ), fn.GetFullPath() ) ) )
315 return false;
316
317 m_frame->GetScreen()->SetContentModified( false ); // do not prompt the user for changes
318
319 m_frame->ReleaseFile();
320
321 m_frame->OpenProjectFiles( std::vector<wxString>( 1, fn.GetFullPath() ), KICTL_REVERT );
322
323 return 0;
324}
325
326
328{
329 // Only standalone mode can directly load a new document
330 if( !Kiface().IsSingle() )
331 return false;
332
333 if( m_frame->IsContentModified() )
334 {
335 wxFileName fileName = m_frame->GetBoard()->GetFileName();
336 wxString saveMsg = _( "Current board will be closed, save changes to '%s' before "
337 "continuing?" );
338
339 if( !HandleUnsavedChanges( m_frame, wxString::Format( saveMsg, fileName.GetFullName() ),
340 [&]()->bool
341 {
342 return m_frame->SaveBoard();
343 } ) )
344 {
345 return false;
346 }
347 }
348 else if( !m_frame->GetBoard()->IsEmpty() )
349 {
350 if( !IsOK( m_frame, _( "Current Board will be closed. Continue?" ) ) )
351 return false;
352 }
353
354 m_frame->SaveProjectLocalSettings();
355
356 m_frame->GetBoard()->ClearProject();
357 m_frame->GetSettingsManager()->UnloadProject( &m_frame->Prj() );
358
359 if( !m_frame->Clear_Pcb( false ) )
360 return false;
361
362 m_frame->LoadProjectSettings();
363 m_frame->LoadDrawingSheet();
364
365 m_frame->OnBoardLoaded();
366 m_frame->OnModify();
367
368 return 0;
369}
370
371
372bool PCB_EDIT_FRAME::SaveBoard( bool aSaveAs, bool aSaveCopy )
373{
374 if( !aSaveAs )
375 {
376 if( !GetBoard()->GetFileName().IsEmpty() )
377 {
378 if( SavePcbFile( Prj().AbsolutePath( GetBoard()->GetFileName() ) ) )
379 {
380 m_autoSaveRequired = false;
381 return true;
382 }
383
384 return false;
385 }
386 }
387
388 wxString orig_name;
389
390 wxFileName::SplitPath( GetBoard()->GetFileName(), nullptr, nullptr, &orig_name, nullptr );
391
392 if( orig_name.IsEmpty() )
393 orig_name = NAMELESS_PROJECT;
394
395 wxFileName savePath( Prj().GetProjectFullName() );
396
397 if( !savePath.IsOk() || !savePath.IsDirWritable() )
398 {
399 savePath = GetMruPath();
400
401 if( !savePath.IsOk() || !savePath.IsDirWritable() )
403 }
404
405 wxFileName fn( savePath.GetPath(), orig_name, FILEEXT::KiCadPcbFileExtension );
406 wxString filename = fn.GetFullPath();
407 bool createProject = false;
408 bool success = false;
409
410 if( AskSaveBoardFileName( this, &filename, &createProject ) )
411 {
412 if( aSaveCopy )
413 {
414 success = SavePcbCopy( EnsureFileExtension( filename, FILEEXT::KiCadPcbFileExtension ), createProject );
415 }
416 else
417 {
418 success = SavePcbFile( filename, aSaveAs, createProject );
419
420 if( success )
421 m_autoSaveRequired = false;
422 }
423 }
424
425 return success;
426}
427
428
429int PCB_EDIT_FRAME::inferLegacyEdgeClearance( BOARD* aBoard, bool aShowUserMsg )
430{
431 PCB_LAYER_COLLECTOR collector;
432
433 collector.SetLayerId( Edge_Cuts );
434 collector.Collect( aBoard, GENERAL_COLLECTOR::AllBoardItems );
435
436 int edgeWidth = -1;
437 bool mixed = false;
438
439 for( int i = 0; i < collector.GetCount(); i++ )
440 {
441 if( collector[i]->Type() == PCB_SHAPE_T )
442 {
443 int itemWidth = static_cast<PCB_SHAPE*>( collector[i] )->GetWidth();
444
445 if( edgeWidth != -1 && edgeWidth != itemWidth )
446 {
447 mixed = true;
448 edgeWidth = std::max( edgeWidth, itemWidth );
449 }
450 else
451 {
452 edgeWidth = itemWidth;
453 }
454 }
455 }
456
457 if( mixed && aShowUserMsg )
458 {
459 // If they had different widths then we can't ensure that fills will be the same.
460 DisplayInfoMessage( this,
461 _( "If the zones on this board are refilled the Copper Edge "
462 "Clearance setting will be used (see Board Setup > Design "
463 "Rules > Constraints).\n This may result in different fills "
464 "from previous KiCad versions which used the line thicknesses "
465 "of the board boundary on the Edge Cuts layer." ) );
466 }
467
468 return std::max( 0, edgeWidth / 2 );
469}
470
471
472bool PCB_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, int aCtl )
473{
474 // This is for python:
475 if( aFileSet.size() != 1 )
476 {
477 DisplayError( this, wxString::Format( "Pcbnew:%s() takes a single filename", __func__ ) );
478 return false;
479 }
480
481 wxString fullFileName( aFileSet[0] );
482 wxFileName wx_filename( fullFileName );
483 Kiway().LocalHistory().Init( wx_filename.GetPath() );
484 wxString msg;
485
486 if( Kiface().IsSingle() )
488
489 // We insist on caller sending us an absolute path, if it does not, we say it's a bug.
490 wxASSERT_MSG( wx_filename.IsAbsolute(), wxT( "Path is not absolute!" ) );
491
492 std::unique_ptr<LOCKFILE> lock = std::make_unique<LOCKFILE>( fullFileName );
493
494 if( !lock->Valid() && lock->IsLockedByMe() )
495 {
496 // If we cannot acquire the lock but we appear to be the one who locked it, check to
497 // see if there is another KiCad instance running. If not, then we can override the
498 // lock. This could happen if KiCad crashed or was interrupted.
499
500 if( !Pgm().SingleInstance()->IsAnotherRunning() )
501 lock->OverrideLock();
502 }
503
504 if( !lock->Valid() )
505 {
506 // If project-level lock override was already granted, silently override this file's lock
507 if( Prj().IsLockOverrideGranted() )
508 {
509 lock->OverrideLock();
510 }
511 else
512 {
513 msg.Printf( _( "PCB '%s' is already open by '%s' at '%s'." ),
514 wx_filename.GetFullName(),
515 lock->GetUsername(),
516 lock->GetHostname() );
517
518 if( !AskOverrideLock( this, msg ) )
519 return false;
520
521 lock->OverrideLock();
522 }
523 }
524
525 if( IsContentModified() )
526 {
527 if( !HandleUnsavedChanges( this, _( "The current PCB has been modified. Save changes?" ),
528 [&]() -> bool
529 {
530 return SavePcbFile( GetBoard()->GetFileName() );
531 } ) )
532 {
533 return false;
534 }
535 }
536
537 wxFileName pro = fullFileName;
538 pro.SetExt( FILEEXT::ProjectFileExtension );
539
540 bool is_new = !wxFileName::IsFileReadable( fullFileName );
541
542 wxString previousBoardFileName = GetBoard() ? GetBoard()->GetFileName() : wxString();
543
544 // If its a non-existent PCB and caller thinks it exists
545 if( is_new && !( aCtl & KICTL_CREATE ) )
546 {
547 // notify user that fullFileName does not exist, ask if user wants to create it.
548 msg.Printf( _( "PCB '%s' does not exist. Do you wish to create it?" ), fullFileName );
549
550 if( !IsOK( this, msg ) )
551 return false;
552 }
553
554 // Get rid of any existing warnings about the old board
555 GetInfoBar()->Dismiss();
556
557 if( KISTATUSBAR* statusBar = dynamic_cast<KISTATUSBAR*>( GetStatusBar() ) )
558 statusBar->ClearLoadWarningMessages();
559
560 WX_PROGRESS_REPORTER progressReporter( this, is_new ? _( "Create PCB" ) : _( "Load PCB" ), 1,
561 PR_CAN_ABORT );
562 WX_STRING_REPORTER loadReporter;
563 LOAD_INFO_REPORTER_SCOPE loadReporterScope( &loadReporter );
564
565 // No save prompt (we already prompted above), and only reset to a new blank board if new
566 Clear_Pcb( false, !is_new );
567
569
570 if( !is_new )
571 pluginType = PCB_IO_MGR::FindPluginTypeFromBoardPath( fullFileName, aCtl );
572
573 if( pluginType == PCB_IO_MGR::FILE_TYPE_NONE )
574 {
575 progressReporter.Hide();
576 DisplayErrorMessage( this, _( "File format is not supported" ), wxEmptyString );
577 return false;
578 }
579
580 bool converted = pluginType != PCB_IO_MGR::LEGACY && pluginType != PCB_IO_MGR::KICAD_SEXP;
581
582 // Loading a project should only be done under carefully considered circumstances.
583
584 // The calling code should know not to ask me here to change projects unless
585 // it knows what consequences that will have on other KIFACEs running and using
586 // this same PROJECT. It can be very harmful if that calling code is stupid.
588 bool setProject;
589
590 if( Kiface().IsSingle() || !( aCtl & KICTL_NONKICAD_ONLY ) )
591 setProject = pro.GetFullPath() != mgr->Prj().GetProjectFullName();
592 else
593 setProject = Prj().GetProjectFullName().IsEmpty();
594
595 if( setProject )
596 {
597 // calls SaveProject
599
601 mgr->UnloadProject( &mgr->Prj() );
602
603 mgr->LoadProject( pro.GetFullPath() );
604
605 // Do not allow saving a project if one doesn't exist. This normally happens if we are
606 // opening a board that has been moved from its project folder.
607 // For converted projects, we don't want to set the read-only flag because we want a
608 // project to be saved for the new file in case things like netclasses got migrated.
609 Prj().SetReadOnly( !pro.Exists() && !converted );
610 }
611
612 if( is_new )
613 {
614 // Link the existing blank board to the new project
615 GetBoard()->SetProject( &Prj() );
616
617 GetBoard()->SetFileName( fullFileName );
618
619 OnModify();
620 }
621 else
622 {
623 BOARD* loadedBoard = nullptr; // it will be set to non-NULL if loaded OK
625
626 if( LAYER_MAPPABLE_PLUGIN* mappable_pi = dynamic_cast<LAYER_MAPPABLE_PLUGIN*>( pi.get() ) )
627 {
628 mappable_pi->RegisterCallback( std::bind( DIALOG_MAP_LAYERS::RunModal,
629 this, std::placeholders::_1 ) );
630 }
631
632 if( PROJECT_CHOOSER_PLUGIN* chooser_pi = dynamic_cast<PROJECT_CHOOSER_PLUGIN*>( pi.get() ) )
633 {
634 chooser_pi->RegisterCallback( std::bind( DIALOG_IMPORT_CHOOSE_PROJECT::RunModal,
635 this,
636 std::placeholders::_1 ) );
637 }
638
639 bool failedLoad = false;
640
641 try
642 {
643 if( pi == nullptr )
644 {
645 // There was no plugin found, e.g. due to invalid file extension, file header,...
646 THROW_IO_ERROR( _( "File format is not supported" ) );
647 }
648
649 std::map<std::string, UTF8> props;
650
652 props.insert( m_importProperties->begin(), m_importProperties->end() );
653
654 // PCB_IO_EAGLE can use this info to center the BOARD, but it does not yet.
655 props["page_width"] = std::to_string( GetPageSizeIU().x );
656 props["page_height"] = std::to_string( GetPageSizeIU().y );
657
658 pi->SetQueryUserCallback(
659 [&]( wxString aTitle, int aIcon, wxString aMessage, wxString aAction ) -> bool
660 {
661 KIDIALOG dlg( nullptr, aMessage, aTitle, wxOK | wxCANCEL | aIcon );
662
663 if( !aAction.IsEmpty() )
664 dlg.SetOKLabel( aAction );
665
666 dlg.DoNotShowCheckbox( aMessage, 0 );
667
668 return dlg.ShowModal() == wxID_OK;
669 } );
670
671#if USE_INSTRUMENTATION
672 // measure the time to load a BOARD.
673 int64_t startTime = GetRunningMicroSecs();
674#endif
675 // Use loadReporter for import issues - they will be shown in the status bar
676 // warning icon instead of a modal dialog
677 if( config()->m_System.show_import_issues )
678 pi->SetReporter( &loadReporter );
679 else
680 pi->SetReporter( &NULL_REPORTER::GetInstance() );
681
682 pi->SetProgressReporter( &progressReporter );
683 loadedBoard = pi->LoadBoard( fullFileName, nullptr, &props, &Prj() );
684
685#if USE_INSTRUMENTATION
686 int64_t stopTime = GetRunningMicroSecs();
687 printf( "PCB_IO::Load(): %u usecs\n", stopTime - startTime );
688#endif
689 }
690 catch( const FUTURE_FORMAT_ERROR& ffe )
691 {
692 msg.Printf( _( "Error loading PCB '%s'." ), fullFileName );
693 progressReporter.Hide();
694 DisplayErrorMessage( this, msg, ffe.Problem() );
695
696 failedLoad = true;
697 }
698 catch( const IO_ERROR& ioe )
699 {
700 if( ioe.Problem() != wxT( "CANCEL" ) )
701 {
702 msg.Printf( _( "Error loading PCB '%s'." ), fullFileName );
703 progressReporter.Hide();
704 DisplayErrorMessage( this, msg, ioe.What() );
705 }
706
707 failedLoad = true;
708 }
709 catch( const std::bad_alloc& )
710 {
711 msg.Printf( _( "Memory exhausted loading PCB '%s'" ), fullFileName );
712 progressReporter.Hide();
713 DisplayErrorMessage( this, msg, wxEmptyString );
714
715 failedLoad = true;
716 }
717
718 if( failedLoad || !loadedBoard )
719 {
720 // We didn't create a new blank board above, so do that now
721 Clear_Pcb( false );
722
723 // Show any messages collected before the failure
724 if( KISTATUSBAR* statusBar = dynamic_cast<KISTATUSBAR*>( GetStatusBar() ) )
725 statusBar->SetLoadWarningMessages( loadReporter.GetMessages() );
726
727 return false;
728 }
729
730 // This fixes a focus issue after the progress reporter is done on GTK. It shouldn't
731 // cause any issues on macOS and Windows. If it does, it will have to be conditionally
732 // compiled.
733 Raise();
734
735 // Skip (possibly expensive) connectivity build here; we build it below after load
736 progressReporter.AddPhases( 1 );
737 progressReporter.AdvancePhase( _( "Finalizing board" ) );
738 progressReporter.KeepRefreshing();
739
740 PROF_TIMER postLoadTimer;
741 SetBoard( loadedBoard, false, &progressReporter );
742 wxLogTrace( traceAllegroPerf, wxT( "Post-load SetBoard: %.3f ms" ),
743 postLoadTimer.msecs( true ) );
744
745 if( loadedBoard->m_LegacyDesignSettingsLoaded )
746 {
747 Prj().SetReadOnly( false );
748
749 // Before we had a copper edge clearance setting, the edge line widths could be used
750 // as a kludge to control them. So if there's no setting then infer it from the
751 // edge widths.
752 if( !loadedBoard->m_LegacyCopperEdgeClearanceLoaded )
753 {
754 // Do not show the inferred edge clearance warning dialog when loading third
755 // party boards. For some reason the dialog completely hangs all of KiCad and
756 // the imported board cannot be saved.
757 int edgeClearance = inferLegacyEdgeClearance( loadedBoard, !converted );
758 loadedBoard->GetDesignSettings().m_CopperEdgeClearance = edgeClearance;
759 }
760
761 // On save; design settings will be removed from the board
762 loadedBoard->SetModified();
763 }
764
765 // Move legacy view settings to local project settings
766 if( !loadedBoard->m_LegacyVisibleLayers.test( Rescue ) )
767 {
769 loadedBoard->SetModified();
770 }
771
773 {
775 loadedBoard->SetModified();
776 }
777
778 if( !loadedBoard->SynchronizeComponentClasses( std::unordered_set<wxString>() ) )
779 {
780 m_infoBar->RemoveAllButtons();
781 m_infoBar->AddCloseButton();
782 m_infoBar->ShowMessage( _( "Could not load component class assignment rules" ),
783 wxICON_WARNING, WX_INFOBAR::MESSAGE_TYPE::GENERIC );
784 }
785
786 // we should not ask PCB_IOs to do these items:
787 loadedBoard->BuildListOfNets();
788 wxLogTrace( traceAllegroPerf, wxT( "Post-load BuildListOfNets: %.3f ms" ),
789 postLoadTimer.msecs( true ) );
790
791 progressReporter.KeepRefreshing();
792
793 m_toolManager->RunAction( PCB_ACTIONS::repairBoard, true);
794 wxLogTrace( traceAllegroPerf, wxT( "Post-load repairBoard: %.3f ms" ),
795 postLoadTimer.msecs( true ) );
796
797 progressReporter.KeepRefreshing();
798
800 wxLogTrace( traceAllegroPerf, wxT( "Post-load rehatchShapes: %.3f ms" ),
801 postLoadTimer.msecs( true ) );
802
803 progressReporter.KeepRefreshing();
804
805 if( loadedBoard->IsModified() )
806 OnModify();
807 else
808 GetScreen()->SetContentModified( false );
809
810 if( ( pluginType == PCB_IO_MGR::LEGACY )
811 || ( pluginType == PCB_IO_MGR::KICAD_SEXP
813 && loadedBoard->GetGenerator().Lower() != wxT( "gerbview" ) ) )
814 {
815 m_infoBar->RemoveAllButtons();
816 m_infoBar->AddCloseButton();
817 m_infoBar->ShowMessage( _( "This file was created by an older version of KiCad. "
818 "It will be converted to the new format when saved." ),
819 wxICON_WARNING, WX_INFOBAR::MESSAGE_TYPE::OUTDATED_SAVE );
820 }
821
822 // TODO(JE) library tables -- I think this functionality should be deleted
823#if 0
824
825 // Import footprints into a project-specific library
826 //==================================================
827 // TODO: This should be refactored out of here into somewhere specific to the Project Import
828 // E.g. KICAD_MANAGER_FRAME::ImportNonKiCadProject
829 if( aCtl & KICTL_IMPORT_LIB )
830 {
831 wxFileName loadedBoardFn( fullFileName );
832 wxString libNickName = loadedBoardFn.GetName();
833
834 // Extract a footprint library from the design and add it to the fp-lib-table
835 // The footprints are saved in a new .pretty library.
836 // If this library already exists, all previous footprints will be deleted
837 std::vector<FOOTPRINT*> loadedFootprints = pi->GetImportedCachedLibraryFootprints();
838 wxString newLibPath = CreateNewProjectLibrary( _( "New Footprint Library" ),
839 libNickName );
840
841 // Only create the new library if CreateNewLibrary succeeded (note that this fails if
842 // the library already exists and the user aborts after seeing the warning message
843 // which prompts the user to continue with overwrite or abort)
844 if( newLibPath.Length() > 0 )
845 {
847
848 for( FOOTPRINT* footprint : loadedFootprints )
849 {
850 try
851 {
852 if( !footprint->GetFPID().GetLibItemName().empty() ) // Handle old boards.
853 {
854 footprint->SetReference( "REF**" );
855 piSexpr->FootprintSave( newLibPath, footprint );
856 delete footprint;
857 }
858 }
859 catch( const IO_ERROR& ioe )
860 {
861 wxLogError( _( "Error saving footprint %s to project specific library." )
862 + wxS( "\n%s" ),
863 footprint->GetFPID().GetUniStringLibItemName(),
864 ioe.What() );
865 }
866 }
867
868 FP_LIB_TABLE* prjlibtable = PROJECT_PCB::PcbFootprintLibs( &Prj() );
869 const wxString& project_env = PROJECT_VAR_NAME;
870 wxString rel_path, env_path;
871
872 wxASSERT_MSG( wxGetEnv( project_env, &env_path ),
873 wxT( "There is no project variable?" ) );
874
875 wxString result( newLibPath );
876
877 if( result.Replace( env_path, wxT( "$(" ) + project_env + wxT( ")" ) ) )
878 rel_path = result;
879
880 FP_LIB_TABLE_ROW* row = new FP_LIB_TABLE_ROW( libNickName, rel_path,
881 wxT( "KiCad" ), wxEmptyString );
882 prjlibtable->InsertRow( row );
883
884 wxString tblName = Prj().FootprintLibTblName();
885
886 try
887 {
888 PROJECT_PCB::PcbFootprintLibs( &Prj() )->Save( tblName );
889 }
890 catch( const IO_ERROR& ioe )
891 {
892 wxLogError( _( "Error saving project specific footprint library table." )
893 + wxS( "\n%s" ),
894 ioe.What() );
895 }
896
897 // Update footprint LIB_IDs to point to the just imported library
898 for( FOOTPRINT* footprint : GetBoard()->Footprints() )
899 {
900 LIB_ID libId = footprint->GetFPID();
901
902 if( libId.GetLibItemName().empty() )
903 continue;
904
905 libId.SetLibNickname( libNickName );
906 footprint->SetFPID( libId );
907 }
908 }
909 }
910#endif
911 }
912
913 {
914 wxString fname;
915
916 if( !previousBoardFileName.IsEmpty() && ( aCtl & KICTL_NONKICAD_ONLY ) && !setProject )
917 {
918 fname = previousBoardFileName;
919 }
920 else
921 {
922 wxFileName fn;
923
924 fn.SetPath( Prj().GetProjectPath() );
925 fn.SetName( Prj().GetProjectName() );
927
928 fname = fn.GetFullPath();
929
930 fname.Replace( WIN_STRING_DIR_SEP, UNIX_STRING_DIR_SEP );
931 }
932
933 GetBoard()->SetFileName( fname );
934 }
935
936 // Lock the file newly opened:
937 m_file_checker.reset( lock.release() );
938
939 if( !converted )
940 UpdateFileHistory( GetBoard()->GetFileName() );
941
942 std::vector<ZONE*> toFill;
943
944 // Rebuild list of nets (full ratsnest rebuild)
945 PROF_TIMER connectivityTimer;
946 GetBoard()->BuildConnectivity( &progressReporter );
947 wxLogTrace( traceAllegroPerf, wxT( "Post-load BuildConnectivity: %.3f ms" ),
948 connectivityTimer.msecs( true ) );
949
950 // Load project settings after setting up board; some of them depend on the nets list
953 wxLogTrace( traceAllegroPerf, wxT( "Post-load LoadProjectSettings+DrawingSheet: %.3f ms" ),
954 connectivityTimer.msecs( true ) );
955
956 // Resolve DRC exclusions after project settings are loaded
957 ResolveDRCExclusions( true );
958
959 // Initialise caches used by component classes
961
962 // Initialise time domain tuning caches
964 wxLogTrace( traceAllegroPerf, wxT( "Post-load DRC+ComponentClass+Tuning caches: %.3f ms" ),
965 connectivityTimer.msecs( true ) );
966
967 // Syncs the UI (appearance panel, etc) with the loaded board and project
969 wxLogTrace( traceAllegroPerf, wxT( "Post-load OnBoardLoaded: %.3f ms" ),
970 connectivityTimer.msecs( true ) );
971 wxLogTrace( traceAllegroPerf, wxT( "=== Post-load pipeline total: %.3f ms ===" ),
972 connectivityTimer.msecs() );
973
974 // Refresh the 3D view, if any
975 EDA_3D_VIEWER_FRAME* draw3DFrame = Get3DViewerFrame();
976
977 if( draw3DFrame )
978 draw3DFrame->NewDisplay();
979#if 0 && defined(DEBUG)
980 // Output the board object tree to stdout, but please run from command prompt:
981 GetBoard()->Show( 0, std::cout );
982#endif
983
984 // from EDA_APPL which was first loaded BOARD only:
985 {
986 /* For an obscure reason the focus is lost after loading a board file
987 * when starting up the process.
988 * (seems due to the recreation of the layer manager after loading the file)
989 * Give focus to main window and Drawpanel
990 * must be done for these 2 windows (for an obscure reason ...)
991 * Linux specific
992 * This is more a workaround than a fix.
993 */
994 SetFocus();
995 GetCanvas()->SetFocus();
996 }
997
998 if( !setProject )
999 {
1000 // If we didn't reload the project, we still need to call ProjectChanged() to ensure
1001 // frame-specific initialization happens (like registering the autosave saver).
1002 // When running under the project manager, KIWAY::ProjectChanged() was called before
1003 // this frame existed, so we need to call our own ProjectChanged() now.
1005 }
1006
1007 if( KISTATUSBAR* statusBar = dynamic_cast<KISTATUSBAR*>( GetStatusBar() ) )
1008 statusBar->SetLoadWarningMessages( loadReporter.GetMessages() );
1009
1010 return true;
1011}
1012
1013
1014bool PCB_EDIT_FRAME::SavePcbFile( const wxString& aFileName, bool addToHistory,
1015 bool aChangeProject )
1016{
1017 // please, keep it simple. prompting goes elsewhere.
1018 wxFileName pcbFileName = aFileName;
1019
1020 if( pcbFileName.GetExt() == FILEEXT::LegacyPcbFileExtension )
1021 pcbFileName.SetExt( FILEEXT::KiCadPcbFileExtension );
1022
1023 // Write through symlinks, don't replace them
1025
1026 if( !IsWritable( pcbFileName ) )
1027 {
1028 wxString msg = wxString::Format( _( "Insufficient permissions to write file '%s'." ),
1029 pcbFileName.GetFullPath() );
1030
1031 DisplayError( this, msg );
1032 return false;
1033 }
1034
1035 // TODO: these will break if we ever go multi-board
1036 wxFileName projectFile( pcbFileName );
1037 wxFileName rulesFile( pcbFileName );
1038 wxString msg;
1039
1040 projectFile.SetExt( FILEEXT::ProjectFileExtension );
1041 rulesFile.SetExt( FILEEXT::DesignRulesFileExtension );
1042
1043 if( projectFile.FileExists() )
1044 {
1046 }
1047 else if( aChangeProject )
1048 {
1049 Prj().SetReadOnly( false );
1050 GetSettingsManager()->SaveProjectAs( projectFile.GetFullPath() );
1051 }
1052
1053 wxFileName currentRules( GetDesignRulesPath() );
1054
1055 if( currentRules.FileExists() && !rulesFile.FileExists() && aChangeProject )
1056 KiCopyFile( currentRules.GetFullPath(), rulesFile.GetFullPath(), msg );
1057
1058 if( !msg.IsEmpty() )
1059 {
1060 DisplayError( this, wxString::Format( _( "Error saving custom rules file '%s'." ),
1061 rulesFile.GetFullPath() ) );
1062 }
1063
1064 if( projectFile.FileExists() )
1065 {
1066 // Save various DRC parameters, such as violation severities (which may have been
1067 // edited via the DRC dialog as well as the Board Setup dialog), DRC exclusions, etc.
1069
1072 }
1073
1074 wxString upperTxt;
1075 wxString lowerTxt;
1076
1077 // On Windows, ensure the target file is writeable by clearing problematic attributes like
1078 // hidden or read-only. This can happen when files are synced via cloud services.
1079 if( pcbFileName.FileExists() )
1080 KIPLATFORM::IO::MakeWriteable( pcbFileName.GetFullPath() );
1081
1082 try
1083 {
1085
1086 pi->SaveBoard( pcbFileName.GetFullPath(), GetBoard(), nullptr );
1087 }
1088 catch( const IO_ERROR& ioe )
1089 {
1090 DisplayError( this, wxString::Format( _( "Error saving board file '%s'.\n%s" ),
1091 pcbFileName.GetFullPath(),
1092 ioe.What() ) );
1093 return false;
1094 }
1095
1096 if( !Kiface().IsSingle() )
1097 {
1098 WX_STRING_REPORTER backupReporter;
1099
1100 if( !GetSettingsManager()->TriggerBackupIfNeeded( backupReporter ) )
1101 {
1102 upperTxt = backupReporter.GetMessages();
1103 SetStatusText( upperTxt, 1 );
1104 }
1105 }
1106
1107 GetBoard()->SetFileName( pcbFileName.GetFullPath() );
1108
1109 // Update the lock in case it was a Save As
1110 LockFile( pcbFileName.GetFullPath() );
1111
1112 // Put the saved file in File History if requested
1113 if( addToHistory )
1114 UpdateFileHistory( GetBoard()->GetFileName() );
1115
1116 lowerTxt.Printf( _( "File '%s' saved." ), pcbFileName.GetFullPath() );
1117
1118 SetStatusText( lowerTxt, 0 );
1119
1120 // Get rid of the old version conversion warning, or any other dismissable warning :)
1121 if( m_infoBar->GetMessageType() == WX_INFOBAR::MESSAGE_TYPE::OUTDATED_SAVE )
1122 m_infoBar->Dismiss();
1123
1124 if( m_infoBar->IsShownOnScreen() && m_infoBar->HasCloseButton() )
1125 m_infoBar->Dismiss();
1126
1127 GetScreen()->SetContentModified( false );
1128 UpdateTitle();
1130
1131 // Capture entire project state for PCB save events.
1132 Kiway().LocalHistory().CommitFullProjectSnapshot( pcbFileName.GetPath(), wxS( "PCB Save" ) );
1133 Kiway().LocalHistory().TagSave( pcbFileName.GetPath(), wxS( "pcb" ) );
1134
1135 if( m_autoSaveTimer )
1136 m_autoSaveTimer->Stop();
1137
1138 m_autoSavePending = false;
1139 m_autoSaveRequired = false;
1140 return true;
1141}
1142
1143
1144bool PCB_EDIT_FRAME::SavePcbCopy( const wxString& aFileName, bool aCreateProject, bool aHeadless )
1145{
1146 wxFileName pcbFileName( aFileName );
1147
1148 if( !IsWritable( pcbFileName ) )
1149 {
1150 if( !aHeadless )
1151 {
1152 DisplayError( this, wxString::Format( _( "Insufficient permissions to write file '%s'." ),
1153 pcbFileName.GetFullPath() ) );
1154 }
1155 return false;
1156 }
1157
1158 // Save various DRC parameters, such as violation severities (which may have been
1159 // edited via the DRC dialog as well as the Board Setup dialog), DRC exclusions, etc.
1161
1163
1164 // On Windows, ensure the target file is writeable by clearing problematic attributes like
1165 // hidden or read-only. This can happen when files are synced via cloud services.
1166 if( pcbFileName.FileExists() )
1167 KIPLATFORM::IO::MakeWriteable( pcbFileName.GetFullPath() );
1168
1169 try
1170 {
1172
1173 wxASSERT( pcbFileName.IsAbsolute() );
1174
1175 pi->SaveBoard( pcbFileName.GetFullPath(), GetBoard(), nullptr );
1176 }
1177 catch( const IO_ERROR& ioe )
1178 {
1179 if( !aHeadless )
1180 {
1181 DisplayError( this, wxString::Format( _( "Error saving board file '%s'.\n%s" ),
1182 pcbFileName.GetFullPath(),
1183 ioe.What() ) );
1184 }
1185
1186 return false;
1187 }
1188
1189 wxFileName projectFile( pcbFileName );
1190 wxFileName rulesFile( pcbFileName );
1191 wxString msg;
1192
1193 projectFile.SetExt( FILEEXT::ProjectFileExtension );
1194 rulesFile.SetExt( FILEEXT::DesignRulesFileExtension );
1195
1196 if( aCreateProject && !projectFile.FileExists() )
1197 GetSettingsManager()->SaveProjectCopy( projectFile.GetFullPath() );
1198
1199 wxFileName currentRules( GetDesignRulesPath() );
1200
1201 if( aCreateProject && currentRules.FileExists() && !rulesFile.FileExists() )
1202 KiCopyFile( currentRules.GetFullPath(), rulesFile.GetFullPath(), msg );
1203
1204 if( !msg.IsEmpty() && !aHeadless )
1205 {
1206 DisplayError( this, wxString::Format( _( "Error saving custom rules file '%s'." ),
1207 rulesFile.GetFullPath() ) );
1208 }
1209
1210 return true;
1211}
1212
1213
1214bool PCB_EDIT_FRAME::importFile( const wxString& aFileName, int aFileType,
1215 const std::map<std::string, UTF8>* aProperties )
1216{
1217 NULLER raiiNuller( (void*&) m_importProperties );
1218
1219 m_importProperties = aProperties;
1220
1221 switch( (PCB_IO_MGR::PCB_FILE_T) aFileType )
1222 {
1224 case PCB_IO_MGR::EAGLE:
1228 return OpenProjectFiles( std::vector<wxString>( 1, aFileName ), KICTL_NONKICAD_ONLY | KICTL_IMPORT_LIB );
1229
1234 case PCB_IO_MGR::PADS:
1235 return OpenProjectFiles( std::vector<wxString>( 1, aFileName ), KICTL_NONKICAD_ONLY );
1236
1237 default:
1238 return false;
1239 }
1240}
1241
1242
1244{
1246
1247 dlg.ShowModal();
1248
1249 return 0;
1250}
1251
1252
1254{
1256
1257 if( dlg.ShowModal() != wxID_OK )
1258 return 0;
1259
1261
1263 job.m_filename = m_frame->GetBoard()->GetFileName();
1265
1266 job.m_precision = dlg.GetPrecision();
1269
1270 WX_PROGRESS_REPORTER progressReporter( m_frame, _( "Generate ODB++ Files" ), 3, PR_CAN_ABORT );
1271 WX_STRING_REPORTER reporter;
1272
1273 DIALOG_EXPORT_ODBPP::GenerateODBPPFiles( job, m_frame->GetBoard(), m_frame, &progressReporter, &reporter );
1274
1275 if( reporter.HasMessage() )
1276 DisplayError( m_frame, reporter.GetMessages() );
1277
1278 return 0;
1279}
const char * name
KIFACE_BASE & Kiface()
Global KIFACE_BASE "get" accessor.
void SetContentModified(bool aModified=true)
Definition base_screen.h:59
int GenerateODBPPFiles(const TOOL_EVENT &aEvent)
int New(const TOOL_EVENT &aEvent)
int Revert(const TOOL_EVENT &aEvent)
int GenIPC2581File(const TOOL_EVENT &aEvent)
int Open(const TOOL_EVENT &aEvent)
int OpenNonKicadBoard(const TOOL_EVENT &aEvent)
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:322
bool m_LegacyDesignSettingsLoaded
True if the legacy board design settings were loaded from a file.
Definition board.h:436
GAL_SET m_LegacyVisibleItems
Definition board.h:433
LENGTH_DELAY_CALCULATION * GetLengthCalculation() const
Returns the track length calculator.
Definition board.h:1402
void BuildListOfNets()
Definition board.h:959
void SetFileName(const wxString &aFileName)
Definition board.h:357
bool BuildConnectivity(PROGRESS_REPORTER *aReporter=nullptr)
Build or rebuild the board connectivity database for the board, especially the list of connected item...
Definition board.cpp:190
void SynchronizeNetsAndNetClasses(bool aResetTrackAndViaSizes)
Copy NETCLASS info to each NET, based on NET membership in a NETCLASS.
Definition board.cpp:2677
LSET m_LegacyVisibleLayers
Visibility settings stored in board prior to 6.0, only used for loading legacy files.
Definition board.h:432
void SetProject(PROJECT *aProject, bool aReferenceOnly=false)
Link a board to a given project.
Definition board.cpp:200
const wxString & GetFileName() const
Definition board.h:359
int GetFileFormatVersionAtLoad() const
Definition board.h:456
const wxString & GetGenerator() const
Adds an item to the container.
Definition board.h:459
void ClearProject()
Definition board.cpp:238
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition board.cpp:1082
void SynchronizeProperties()
Copy the current project's text variables into the boards property cache.
Definition board.cpp:2491
COMPONENT_CLASS_MANAGER & GetComponentClassManager()
Gets the component class manager.
Definition board.h:1407
bool SynchronizeComponentClasses(const std::unordered_set< wxString > &aNewSheetPaths) const
Copy component class / component class generator information from the project settings.
Definition board.cpp:2707
bool m_LegacyCopperEdgeClearanceLoaded
Definition board.h:437
int GetCount() const
Return the number of objects in the list.
Definition collector.h:83
void RebuildRequiredCaches(FOOTPRINT *aFootprint=nullptr) const
Rebuilds any caches that may be required by custom assignment rules.
static void GenerateODBPPFiles(const JOB_EXPORT_PCB_ODB &aJob, BOARD *aBoard, PCB_EDIT_FRAME *aParentFrame=nullptr, PROGRESS_REPORTER *aProgressReporter=nullptr, REPORTER *aErrorReporter=nullptr)
wxString GetOutputPath() const
wxString GetUnitsString() const
static std::vector< IMPORT_PROJECT_DESC > RunModal(wxWindow *aParent, const std::vector< IMPORT_PROJECT_DESC > &aProjectDesc)
Create and show a dialog (modal) and returns the data from it after completion.
static std::map< wxString, PCB_LAYER_ID > RunModal(wxWindow *aParent, const std::vector< INPUT_LAYER_DESC > &aLayerDesc)
Create and show a dialog (modal) and returns the data from it after completion.
int ShowModal() override
Create and handle a window for the 3d viewer connected to a Kiway and a pcbboard.
void NewDisplay(bool aForceImmediateRedraw=false)
Reload and refresh (rebuild) the 3D scene.
virtual APP_SETTINGS_BASE * config() const
Return the settings object used in SaveSettings(), and is overloaded in KICAD_MANAGER_FRAME.
WX_INFOBAR * m_infoBar
wxTimer * m_autoSaveTimer
void UpdateFileHistory(const wxString &FullFileName, FILE_HISTORY *aFileHistory=nullptr)
Update the list of recently opened files.
wxString GetMruPath() const
bool IsWritable(const wxFileName &aFileName, bool aVerbose=true)
Check if aFileName can be written.
virtual void ClearFileHistory()
Remove all files from the file history.
wxString GetFileFromHistory(int cmdId, const wxString &type, FILE_HISTORY *aFileHistory=nullptr)
Fetch the file name from the file history list.
void SetMruPath(const wxString &aPath)
WX_INFOBAR * GetInfoBar()
std::unique_ptr< LOCKFILE > m_file_checker
bool LockFile(const wxString &aFileName)
Mark a schematic file as being in use.
void SetFocus() override
void SetModified()
Definition eda_item.cpp:110
bool IsModified() const
Definition eda_item.h:124
bool GetCreateNewProject() const
Gets the selected state of the copy subsheets option.
static const std::vector< KICAD_T > AllBoardItems
A scan list for all editable board items.
Definition collectors.h:41
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()
virtual const wxString Problem() const
what was the problem?
ODB_COMPRESSION m_compressionMode
void SetConfiguredOutputPath(const wxString &aPath)
Sets the configured output path for the job, this path is always saved to file.
Definition job.cpp:157
Helper class to create more flexible dialogs, including 'do not show again' checkbox handling.
Definition kidialog.h:42
void DoNotShowCheckbox(wxString file, int line)
Shows the 'do not show again' checkbox.
Definition kidialog.cpp:55
int ShowModal() override
Definition kidialog.cpp:93
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
LOCAL_HISTORY & LocalHistory()
Return the LOCAL_HISTORY associated with this KIWAY.
Definition kiway.h:407
Plugin class for import plugins that support remappable layers.
void SynchronizeTuningProfileProperties() const
Ensure time domain properties provider is synced with board / project settings if required.
A logical library item identifier and consists of various portions much like a URI.
Definition lib_id.h:49
int SetLibNickname(const UTF8 &aLibNickname)
Override the logical library name portion of the LIB_ID to aLibNickname.
Definition lib_id.cpp:100
const UTF8 & GetLibItemName() const
Definition lib_id.h:102
bool TagSave(const wxString &aProjectPath, const wxString &aFileType)
Tag a manual save in the local history repository.
bool Init(const wxString &aProjectPath)
Initialize the local history repository for the given project path.
bool CommitFullProjectSnapshot(const wxString &aProjectPath, const wxString &aTitle)
Commit a snapshot of the entire project directory (excluding the .history directory and ignored trans...
Definition raii.h:38
static REPORTER & GetInstance()
Definition reporter.cpp:97
static wxString GetDefaultUserProjectsPath()
Gets the default path we point users to create projects.
Definition paths.cpp:137
static TOOL_ACTION repairBoard
static TOOL_ACTION rehatchShapes
wxString GetDesignRulesPath()
Return the absolute path to the design rules file for the currently-loaded board.
wxString CreateNewProjectLibrary(const wxString &aDialogTitle, const wxString &aLibName)
const VECTOR2I GetPageSizeIU() const override
Works off of GetPageSettings() to return the size of the paper page in the internal units of this par...
PCB_DRAW_PANEL_GAL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
PCB_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
BOARD * GetBoard() const
EDA_3D_VIEWER_FRAME * Get3DViewerFrame()
virtual void UpdateStatusBar() override
Update the status bar information.
The main frame for Pcbnew.
void LoadDrawingSheet()
Load the drawing sheet file.
void ResolveDRCExclusions(bool aCreateMarkers)
If aCreateMarkers then create DRC exclusion markers from the serialized data.
void SetBoard(BOARD *aBoard, PROGRESS_REPORTER *aReporter=nullptr) override
Set the #m_Pcb member in such as way as to ensure deleting any previous BOARD.
void OnModify() override
Must be called after a board change to set the modified flag.
void OnClearFileHistory(wxCommandEvent &aEvent)
bool SaveBoard(bool aSaveAs=false, bool aSaveCopy=false)
bool OpenProjectFiles(const std::vector< wxString > &aFileSet, int aCtl=0) override
Load a KiCad board (.kicad_pcb) from aFileName.
void ProjectChanged() override
Notification event that the project has changed.
void SaveProjectLocalSettings() override
Save changes to the project local settings.
bool SavePcbCopy(const wxString &aFileName, bool aCreateProject=false, bool aHeadless=false)
Write the board data structures to aFileName.
bool IsContentModified() const override
Get if the current board has been modified but not saved.
bool LoadProjectSettings()
Load the current project's file configuration settings which are pertinent to this PCB_EDIT_FRAME ins...
bool Clear_Pcb(bool doAskAboutUnsavedChanges, bool aFinal=false)
Delete all and reinitialize the current board.
Definition initpcb.cpp:42
void OnBoardLoaded()
Update the state of the GUI after a new board is loaded or created.
void UpdateTitle()
Set the main window title bar text.
int inferLegacyEdgeClearance(BOARD *aBoard, bool aShowUserMsg=true)
const std::map< std::string, UTF8 > * m_importProperties
bool SavePcbFile(const wxString &aFileName, bool addToHistory=true, bool aChangeProject=true)
Write the board data structures to a aFileName.
bool importFile(const wxString &aFileName, int aFileType, const std::map< std::string, UTF8 > *aProperties=nullptr)
Load the given filename but sets the path to the current project path.
void saveProjectSettings() override
Save any design-related project settings associated with this frame.
void OnFileHistory(wxCommandEvent &event)
static PLUGIN_REGISTRY * Instance()
Definition pcb_io_mgr.h:97
PCB_FILE_T
The set of file types that the PCB_IO_MGR knows about, and for which there has been a plugin written,...
Definition pcb_io_mgr.h:56
@ KICAD_SEXP
S-expression Pcbnew file format.
Definition pcb_io_mgr.h:58
@ GEDA_PCB
Geda PCB file formats.
Definition pcb_io_mgr.h:69
@ ALTIUM_DESIGNER
Definition pcb_io_mgr.h:63
@ LEGACY
Legacy Pcbnew file formats prior to s-expression.
Definition pcb_io_mgr.h:59
@ ALTIUM_CIRCUIT_MAKER
Definition pcb_io_mgr.h:61
@ ALTIUM_CIRCUIT_STUDIO
Definition pcb_io_mgr.h:62
@ CADSTAR_PCB_ARCHIVE
Definition pcb_io_mgr.h:64
static PCB_IO * FindPlugin(PCB_FILE_T aFileType)
Return a #PLUGIN which the caller can use to import, export, save, or load design documents.
static PCB_FILE_T FindPluginTypeFromBoardPath(const wxString &aFileName, int aCtl=0)
Return a plugin type given a path for a board file.
Collect all BOARD_ITEM objects on a given layer.
Definition collectors.h:549
void Collect(BOARD_ITEM *aBoard, const std::vector< KICAD_T > &aTypes)
Test a BOARD_ITEM using this class's Inspector method, which does the collection.
void SetLayerId(PCB_LAYER_ID aLayerId)
Definition collectors.h:555
A small class to help profiling.
Definition profile.h:49
double msecs(bool aSinceLast=false)
Definition profile.h:149
virtual void AdvancePhase() override
Use the next available virtual zone of the dialog progress bar.
void AddPhases(int aNumPhases) override
bool KeepRefreshing(bool aWait=false) override
Update the UI dialog.
Plugin class for import plugins that support choosing a project.
LSET m_VisibleLayers
Board settings.
GAL_SET m_VisibleItems
The GAL layers (aka items) that are turned on for viewing (.
virtual void SetReadOnly(bool aReadOnly=true)
Definition project.h:163
virtual const wxString GetProjectFullName() const
Return the full path and name of the project.
Definition project.cpp:171
virtual PROJECT_LOCAL_SETTINGS & GetLocalSettings() const
Definition project.h:209
virtual const wxString FootprintLibTblName() const
Returns the path and filename of this project's footprint library table.
Definition project.cpp:207
virtual bool IsNullProject() const
Check if this project is a null project (i.e.
Definition project.cpp:195
virtual bool HasMessage() const
Returns true if any messages were reported.
Definition reporter.h:134
void SaveProjectAs(const wxString &aFullPath, PROJECT *aProject=nullptr)
Set the currently loaded project path and saves it (pointers remain valid).
void SaveProjectCopy(const wxString &aFullPath, PROJECT *aProject=nullptr)
Save a copy of the current project under the given path.
bool SaveProject(const wxString &aFullPath=wxEmptyString, PROJECT *aProject=nullptr)
Save a loaded project.
bool LoadProject(const wxString &aFullPath, bool aSetActive=true)
Load a project or sets up a new project with a specified path.
bool UnloadProject(PROJECT *aProject, bool aSave=true)
Save, unload and unregister the given PROJECT.
PROJECT & Prj() const
A helper while we are not MDI-capable – return the one and only project.
TOOL_MANAGER * m_toolManager
Generic, UI-independent tool event.
Definition tool_event.h:171
bool empty() const
Definition utf8.h:109
static void ResolvePossibleSymlinks(wxFileName &aFilename)
void Dismiss() override
Dismisses the infobar and updates the containing layout and AUI manager (if one is provided).
Multi-thread safe progress reporter dialog, intended for use of tasks that parallel reporting back of...
A wrapper for reporting to a wxString object.
Definition reporter.h:191
const wxString & GetMessages() const
Definition reporter.cpp:78
wxString EnsureFileExtension(const wxString &aFilename, const wxString &aExtension)
It's annoying to throw up nag dialogs when the extension isn't right.
Definition common.cpp:629
bool AskOverrideLock(wxWindow *aParent, const wxString &aMessage)
Display a dialog indicating the file is already open, with an option to reset the lock.
Definition confirm.cpp:42
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition confirm.cpp:259
void DisplayInfoMessage(wxWindow *aParent, const wxString &aMessage, const wxString &aExtraInfo)
Display an informational message box with aMessage.
Definition confirm.cpp:230
bool HandleUnsavedChanges(wxWindow *aParent, const wxString &aMessage, const std::function< bool()> &aSaveFunction)
Display a dialog with Save, Cancel and Discard Changes buttons.
Definition confirm.cpp:131
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)
Declaration of the eda_3d_viewer class.
void KiCopyFile(const wxString &aSrcPath, const wxString &aDestPath, wxString &aErrors)
Definition gestfich.cpp:293
#define WIN_STRING_DIR_SEP
Definition gestfich.h:38
#define UNIX_STRING_DIR_SEP
Definition gestfich.h:37
static const std::string ProjectFileExtension
static const std::string LegacyPcbFileExtension
static const std::string DesignRulesFileExtension
static const std::string KiCadPcbFileExtension
static wxString PcbFileWildcard()
std::unique_ptr< T > IO_RELEASER
Helper to hold and release an IO_BASE object when exceptions are thrown.
Definition io_mgr.h:33
#define THROW_IO_ERROR(msg)
macro which captures the "call site" values of FILE_, __FUNCTION & LINE
PROJECT & Prj()
Definition kicad.cpp:642
#define KICTL_CREATE
caller thinks requested project files may not exist.
#define KICTL_REVERT
reverting to a previously-saved (KiCad) file.
#define KICTL_IMPORT_LIB
import all footprints into a project library.
#define KICTL_KICAD_ONLY
chosen file is from KiCad according to user
#define KICTL_NONKICAD_ONLY
chosen file is non-KiCad according to user
@ GAL_LAYER_ID_BITMASK_END
This is the end of the layers used for visibility bit masks in legacy board files.
Definition layer_ids.h:287
@ Edge_Cuts
Definition layer_ids.h:112
@ Rescue
Definition layer_ids.h:121
#define GAL_LAYER_INDEX(x)
Use this macro to convert a GAL layer to a 0-indexed offset from LAYER_VIAS.
Definition layer_ids.h:364
File locking utilities.
This file contains miscellaneous commonly used macros and functions.
bool RegisterApplicationRestart(const wxString &aCommandLine)
Registers the application for restart with the OS with the given command line string to pass as args.
Definition unix/app.cpp:65
bool MakeWriteable(const wxString &aFilePath)
Ensures that a file has write permissions.
Definition unix/io.cpp:75
void AllowNetworkFileSystems(wxDialog *aDialog)
Configure a file dialog to show network and virtual file systems.
Definition wxgtk/ui.cpp:435
#define SEXPR_BOARD_FILE_VERSION
Current s-expression file format version. 2 was the last legacy format version.
bool AskLoadBoardFileName(PCB_EDIT_FRAME *aParent, wxString *aFileName, int aCtl=0)
Show a wxFileDialog asking for a BOARD filename to open.
bool AskSaveBoardFileName(PCB_EDIT_FRAME *aParent, wxString *aFileName, bool *aCreateProject)
Put up a wxFileDialog asking for a BOARD filename to save.
static const wxChar *const traceAllegroPerf
SETTINGS_MANAGER * GetSettingsManager()
PGM_BASE & Pgm()
The global program "get" accessor.
see class PGM_BASE
int64_t GetRunningMicroSecs()
An alternate way to calculate an elapsed time (in microsecondes) to class PROF_COUNTER.
#define PROJECT_VAR_NAME
A variable name whose value holds the current project directory.
Definition project.h:41
#define NAMELESS_PROJECT
default name for nameless projects
Definition project.h:44
KIWAY Kiway(KFCTL_STANDALONE)
bool show_import_issues
Stored value for "show import issues" when importing non-KiCad designs to this application.
Variant of PARSE_ERROR indicating that a syntax or related error was likely caused by a file generate...
Container that describes file type info.
Definition io_base.h:43
std::vector< std::string > m_FileExtensions
Filter used for file pickers if m_IsFile is true.
Definition io_base.h:47
bool m_CanRead
Whether the IO can read this file type.
Definition io_base.h:52
std::string path
wxString result
Test unit parsing edge cases and error handling.
wxLogTrace helper definitions.
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
Definition typeinfo.h:88
wxString AddFileExtListToFilter(const std::vector< std::string > &aExts)
Build the wildcard extension file dialog wildcard filter to add to the base message dialog.
wxString formatWildcardExt(const wxString &aWildcard)
Format wildcard extension to support case sensitive file dialogs.
Definition of file extensions used in Kicad.
#define PR_CAN_ABORT