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, see <https://www.gnu.org/licenses/>.
21 */
22
23#include <string>
24#include <vector>
25
26#include <advanced_config.h>
27#include <confirm.h>
28#include <kidialog.h>
29#include <core/arraydim.h>
30#include <core/profile.h>
31#include <thread_pool.h>
32#include <gestfich.h>
33#include <local_history.h>
34#include <pcb_edit_frame.h>
36#include <board_loader.h>
39#include <kiface_base.h>
40#include <macros.h>
41#include <trace_helpers.h>
43#include <lockfile.h>
44#include <wx/snglinst.h>
46#include <pcbnew_id.h>
48#include <tool/tool_manager.h>
49#include <board.h>
50#include <collectors.h>
52#include <kiplatform/app.h>
53#include <kiplatform/ui.h>
55#include <widgets/wx_infobar.h>
58#include <paths.h>
59#include <pgm_base.h>
61#include <project_pcb.h>
65#include <pcb_io/pcb_io_mgr.h>
73#include <tools/pcb_actions.h>
75#include <board_commit.h>
76#include <reporter.h>
77#include <zone_filler.h>
79#include <widgets/kistatusbar.h>
81#include <wx_filename.h> // For ::ResolvePossibleSymlinks()
82#include <kiplatform/io.h>
83
84#include <wx/stdpaths.h>
85#include <wx/ffile.h>
86#include <wx/filedlg.h>
87#include <wx/txtstrm.h>
88#include <wx/wfstream.h>
89#include <wx/zipstrm.h>
90#include <wx/dir.h>
91
93
94//#define USE_INSTRUMENTATION 1
95#define USE_INSTRUMENTATION 0
96
97static const wxChar* const traceAllegroPerf = wxT( "KICAD_ALLEGRO_PERF" );
98
99
109bool AskLoadBoardFileName( PCB_EDIT_FRAME* aParent, wxString* aFileName, int aCtl = 0 )
110{
111 std::vector<IO_BASE::IO_FILE_DESC> descriptions;
112
113 for( const auto& plugin : PCB_IO_MGR::PLUGIN_REGISTRY::Instance()->AllPlugins() )
114 {
115 bool isKiCad = plugin.m_type == PCB_IO_MGR::KICAD_SEXP || plugin.m_type == PCB_IO_MGR::LEGACY;
116
117 if( ( aCtl & KICTL_KICAD_ONLY ) && !isKiCad )
118 continue;
119
120 if( ( aCtl & KICTL_NONKICAD_ONLY ) && isKiCad )
121 continue;
122
123 IO_RELEASER<PCB_IO> pi( plugin.m_createFunc() );
124 wxCHECK( pi, false );
125
126 const IO_BASE::IO_FILE_DESC& desc = pi->GetBoardFileDesc();
127
128 if( desc.m_FileExtensions.empty() || !desc.m_CanRead )
129 continue;
130
131 descriptions.emplace_back( desc );
132 }
133
134 wxString fileFiltersStr;
135 std::vector<std::string> allExtensions;
136 std::set<wxString> allWildcardsSet;
137
138 for( const IO_BASE::IO_FILE_DESC& desc : descriptions )
139 {
140 if( !fileFiltersStr.IsEmpty() )
141 fileFiltersStr += wxChar( '|' );
142
143 fileFiltersStr += desc.FileFilter();
144
145 for( const std::string& ext : desc.m_FileExtensions )
146 {
147 allExtensions.emplace_back( ext );
148 allWildcardsSet.insert( wxT( "*." ) + formatWildcardExt( ext ) + wxT( ";" ) );
149 }
150 }
151
152 wxString allWildcardsStr;
153
154 for( const wxString& wildcard : allWildcardsSet )
155 allWildcardsStr << wildcard;
156
157 if( aCtl & KICTL_KICAD_ONLY )
158 {
159 fileFiltersStr = _( "All KiCad Board Files" ) + AddFileExtListToFilter( allExtensions );
160 }
161 else
162 {
163 fileFiltersStr = _( "All supported formats" ) + wxT( "|" ) + allWildcardsStr + wxT( "|" )
164 + fileFiltersStr;
165 }
166
167 wxFileName fileName( *aFileName );
168 wxString path;
169 wxString name;
170
171 if( fileName.FileExists() )
172 {
173 path = fileName.GetPath();
174 name = fileName.GetFullName();
175 }
176 else
177 {
178 path = aParent->GetMruPath();
179
180 if( path.IsEmpty() )
182 // leave name empty
183 }
184
185 bool kicadFormat = ( aCtl & KICTL_KICAD_ONLY );
186
187 wxFileDialog dlg( aParent, kicadFormat ? _( "Open Board File" ) : _( "Import Non KiCad Board File" ),
188 path, name, fileFiltersStr, wxFD_OPEN | wxFD_FILE_MUST_EXIST );
189
190 FILEDLG_IMPORT_NON_KICAD importOptions( aParent->config()->m_System.show_import_issues );
191
192 if( !kicadFormat )
193 dlg.SetCustomizeHook( importOptions );
194
196
197 if( dlg.ShowModal() == wxID_OK )
198 {
199 *aFileName = dlg.GetPath();
200 aParent->SetMruPath( wxFileName( dlg.GetPath() ).GetPath() );
201
202 if( !kicadFormat )
203 aParent->config()->m_System.show_import_issues = importOptions.GetShowIssues();
204
205 return true;
206 }
207 else
208 {
209 return false;
210 }
211}
212
213
223bool AskSaveBoardFileName( PCB_EDIT_FRAME* aParent, wxString* aFileName, bool* aCreateProject )
224{
225 wxString wildcard = FILEEXT::PcbFileWildcard();
226 wxFileName fn = *aFileName;
227
229
230 wxFileDialog dlg( aParent, _( "Save Board File As" ), fn.GetPath(), fn.GetFullName(), wildcard,
231 wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
232
233// Add a "Create a project" checkbox in standalone mode and one isn't loaded
234 FILEDLG_HOOK_SAVE_PROJECT newProjectHook;
235
236 if( Kiface().IsSingle() && aParent->Prj().IsNullProject() )
237 dlg.SetCustomizeHook( newProjectHook );
238
240
241 if( dlg.ShowModal() != wxID_OK )
242 return false;
243
244 *aFileName = dlg.GetPath();
245 *aFileName = EnsureFileExtension( *aFileName, FILEEXT::KiCadPcbFileExtension );
246
247 if( newProjectHook.IsAttachedToDialog() )
248 *aCreateProject = newProjectHook.GetCreateNewProject();
249 else if( !aParent->Prj().IsNullProject() )
250 *aCreateProject = true;
251
252 return true;
253}
254
255
256void PCB_EDIT_FRAME::OnFileHistory( wxCommandEvent& event )
257{
258 wxString filename = GetFileFromHistory( event.GetId(), _( "Printed circuit board" ) );
259
260 if( !filename.IsEmpty() )
261 {
262 if( !wxFileName::IsFileReadable( filename ) )
263 {
264 if( !AskLoadBoardFileName( this, &filename, KICTL_KICAD_ONLY ) )
265 return;
266 }
267
268 OpenProjectFiles( std::vector<wxString>( 1, filename ), KICTL_KICAD_ONLY );
269 }
270}
271
272
273void PCB_EDIT_FRAME::OnClearFileHistory( wxCommandEvent& aEvent )
274{
276}
277
278
280{
281 // Only standalone mode can directly load a new document
282 if( !Kiface().IsSingle() )
283 return false;
284
285 int open_ctl = KICTL_KICAD_ONLY;
286 wxString fileName = m_frame->Prj().AbsolutePath( m_frame->GetBoard()->GetFileName() );
287
288 if( AskLoadBoardFileName( m_frame, &fileName, open_ctl ) )
289 m_frame->OpenProjectFiles( std::vector<wxString>( 1, fileName ), open_ctl );
290
291 return 0;
292}
293
294
296{
297 // Note: we explicitly allow this even if not in standalone mode for now, even though it is dangerous.
298 int open_ctl = KICTL_NONKICAD_ONLY;
299 wxString fileName; // = Prj().AbsolutePath( GetBoard()->GetFileName() );
300
301 if( AskLoadBoardFileName( m_frame, &fileName, open_ctl ) )
302 m_frame->OpenProjectFiles( std::vector<wxString>( 1, fileName ), open_ctl );
303
304 return 0;
305}
306
307
309{
310 wxFileName fn = m_frame->Prj().AbsolutePath( m_frame->GetBoard()->GetFileName() );
311
312 if( !IsOK( m_frame, wxString::Format( _( "Revert '%s' to last version saved?" ), fn.GetFullPath() ) ) )
313 return false;
314
315 m_frame->GetScreen()->SetContentModified( false ); // do not prompt the user for changes
316
317 m_frame->ReleaseFile();
318
319 m_frame->OpenProjectFiles( std::vector<wxString>( 1, fn.GetFullPath() ), KICTL_REVERT );
320
321 return 0;
322}
323
324
326{
327 // Only standalone mode can directly load a new document
328 if( !Kiface().IsSingle() )
329 return false;
330
331 if( m_frame->IsContentModified() )
332 {
333 wxFileName fileName = m_frame->GetBoard()->GetFileName();
334 wxString saveMsg = _( "Current board will be closed, save changes to '%s' before "
335 "continuing?" );
336
337 if( !HandleUnsavedChanges( m_frame, wxString::Format( saveMsg, fileName.GetFullName() ),
338 [&]()->bool
339 {
340 return m_frame->SaveBoard();
341 } ) )
342 {
343 return false;
344 }
345 }
346 else if( !m_frame->GetBoard()->IsEmpty() )
347 {
348 if( !IsOK( m_frame, _( "Current Board will be closed. Continue?" ) ) )
349 return false;
350 }
351
352 m_frame->SaveProjectLocalSettings();
353
354 m_frame->GetBoard()->ClearProject();
355 m_frame->GetSettingsManager()->UnloadProject( &m_frame->Prj() );
356
357 if( !m_frame->Clear_Pcb( false ) )
358 return false;
359
360 m_frame->LoadProjectSettings();
361 m_frame->LoadDrawingSheet();
362
363 m_frame->OnBoardLoaded();
364 m_frame->OnModify();
365
366 return 0;
367}
368
369
370bool PCB_EDIT_FRAME::SaveBoard( bool aSaveAs, bool aSaveCopy )
371{
372 if( !aSaveAs )
373 {
374 if( !GetBoard()->GetFileName().IsEmpty() )
375 {
376 if( SavePcbFile( Prj().AbsolutePath( GetBoard()->GetFileName() ) ) )
377 {
378 m_autoSaveRequired = false;
379 return true;
380 }
381
382 return false;
383 }
384 }
385
386 wxString orig_name;
387
388 wxFileName::SplitPath( GetBoard()->GetFileName(), nullptr, nullptr, &orig_name, nullptr );
389
390 if( orig_name.IsEmpty() )
391 orig_name = NAMELESS_PROJECT;
392
393 wxFileName savePath( Prj().GetProjectFullName() );
394
395 if( !savePath.IsOk() || !savePath.IsDirWritable() )
396 {
397 savePath = GetMruPath();
398
399 if( !savePath.IsOk() || !savePath.IsDirWritable() )
401 }
402
403 wxFileName fn( savePath.GetPath(), orig_name, FILEEXT::KiCadPcbFileExtension );
404 wxString filename = fn.GetFullPath();
405 bool createProject = false;
406 bool success = false;
407
408 if( AskSaveBoardFileName( this, &filename, &createProject ) )
409 {
410 if( aSaveCopy )
411 {
412 success = SavePcbCopy( EnsureFileExtension( filename, FILEEXT::KiCadPcbFileExtension ), createProject );
413 }
414 else
415 {
416 success = SavePcbFile( filename, aSaveAs, createProject );
417
418 if( success )
419 m_autoSaveRequired = false;
420 }
421 }
422
423 return success;
424}
425
426
427int PCB_EDIT_FRAME::inferLegacyEdgeClearance( BOARD* aBoard, bool aShowUserMsg )
428{
429 PCB_LAYER_COLLECTOR collector;
430
431 collector.SetLayerId( Edge_Cuts );
432 collector.Collect( aBoard, GENERAL_COLLECTOR::AllBoardItems );
433
434 int edgeWidth = -1;
435 bool mixed = false;
436
437 for( int i = 0; i < collector.GetCount(); i++ )
438 {
439 if( collector[i]->Type() == PCB_SHAPE_T )
440 {
441 int itemWidth = static_cast<PCB_SHAPE*>( collector[i] )->GetWidth();
442
443 if( edgeWidth != -1 && edgeWidth != itemWidth )
444 {
445 mixed = true;
446 edgeWidth = std::max( edgeWidth, itemWidth );
447 }
448 else
449 {
450 edgeWidth = itemWidth;
451 }
452 }
453 }
454
455 if( mixed && aShowUserMsg )
456 {
457 // If they had different widths then we can't ensure that fills will be the same.
458 DisplayInfoMessage( this,
459 _( "If the zones on this board are refilled the Copper Edge "
460 "Clearance setting will be used (see Board Setup > Design "
461 "Rules > Constraints).\n This may result in different fills "
462 "from previous KiCad versions which used the line thicknesses "
463 "of the board boundary on the Edge Cuts layer." ) );
464 }
465
466 return std::max( 0, edgeWidth / 2 );
467}
468
469
470bool PCB_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, int aCtl )
471{
472 // This is for python:
473 if( aFileSet.size() != 1 )
474 {
475 DisplayError( this, wxString::Format( "Pcbnew:%s() takes a single filename", __func__ ) );
476 return false;
477 }
478
479 wxString fullFileName( aFileSet[0] );
480 wxFileName wx_filename( fullFileName );
481 Kiway().LocalHistory().Init( wx_filename.GetPath() );
482 wxString msg;
483
484 if( Kiface().IsSingle() )
486
487 // We insist on caller sending us an absolute path, if it does not, we say it's a bug.
488 wxASSERT_MSG( wx_filename.IsAbsolute(), wxT( "Path is not absolute!" ) );
489
490 std::unique_ptr<LOCKFILE> lock = std::make_unique<LOCKFILE>( fullFileName );
491
492 if( !lock->Valid() && lock->IsLockedByMe() )
493 {
494 // If we cannot acquire the lock but we appear to be the one who locked it, check to
495 // see if there is another KiCad instance running. If not, then we can override the
496 // lock. This could happen if KiCad crashed or was interrupted.
497
498 if( !Pgm().SingleInstance()->IsAnotherRunning() )
499 lock->OverrideLock();
500 }
501
502 if( !lock->Valid() )
503 {
504 // If project-level lock override was already granted, silently override this file's lock
505 if( Prj().IsLockOverrideGranted() )
506 {
507 lock->OverrideLock();
508 }
509 else
510 {
511 msg.Printf( _( "PCB '%s' is already open by '%s' at '%s'." ),
512 wx_filename.GetFullName(),
513 lock->GetUsername(),
514 lock->GetHostname() );
515
516 if( !AskOverrideLock( this, msg ) )
517 return false;
518
519 lock->OverrideLock();
520 }
521 }
522
523 if( IsContentModified() )
524 {
525 if( !HandleUnsavedChanges( this, _( "The current PCB has been modified. Save changes?" ),
526 [&]() -> bool
527 {
528 return SavePcbFile( GetBoard()->GetFileName() );
529 } ) )
530 {
531 return false;
532 }
533 }
534
535 wxFileName pro = fullFileName;
536 pro.SetExt( FILEEXT::ProjectFileExtension );
537
538 bool is_new = !wxFileName::IsFileReadable( fullFileName );
539
540 wxString previousBoardFileName = GetBoard() ? GetBoard()->GetFileName() : wxString();
541
542 // If its a non-existent PCB and caller thinks it exists
543 if( is_new && !( aCtl & KICTL_CREATE ) )
544 {
545 // notify user that fullFileName does not exist, ask if user wants to create it.
546 msg.Printf( _( "PCB '%s' does not exist. Do you wish to create it?" ), fullFileName );
547
548 if( !IsOK( this, msg ) )
549 return false;
550 }
551
552 // Get rid of any existing warnings about the old board
553 GetInfoBar()->Dismiss();
554
555 if( KISTATUSBAR* statusBar = dynamic_cast<KISTATUSBAR*>( GetStatusBar() ) )
556 statusBar->ClearWarningMessages( "load" );
557
558 WX_PROGRESS_REPORTER progressReporter( this, is_new ? _( "Create PCB" ) : _( "Load PCB" ), 1,
559 PR_CAN_ABORT );
560 WX_STRING_REPORTER loadReporter;
561 LOAD_INFO_REPORTER_SCOPE loadReporterScope( &loadReporter );
562
563 // No save prompt (we already prompted above), and only reset to a new blank board if new
564 Clear_Pcb( false, !is_new );
565
567
568 if( !is_new )
569 pluginType = PCB_IO_MGR::FindPluginTypeFromBoardPath( fullFileName, aCtl );
570
571 if( pluginType == PCB_IO_MGR::FILE_TYPE_NONE )
572 {
573 progressReporter.Hide();
574 DisplayErrorMessage( this, _( "File format is not supported" ), wxEmptyString );
575 return false;
576 }
577
578 bool converted = pluginType != PCB_IO_MGR::LEGACY && pluginType != PCB_IO_MGR::KICAD_SEXP;
579
580 // Loading a project should only be done under carefully considered circumstances.
581
582 // The calling code should know not to ask me here to change projects unless
583 // it knows what consequences that will have on other KIFACEs running and using
584 // this same PROJECT. It can be very harmful if that calling code is stupid.
586 bool setProject;
587
588 if( Kiface().IsSingle() || !( aCtl & KICTL_NONKICAD_ONLY ) )
589 setProject = pro.GetFullPath() != mgr->Prj().GetProjectFullName();
590 else
591 setProject = Prj().GetProjectFullName().IsEmpty();
592
593 if( setProject )
594 {
595 // calls SaveProject
597
599 mgr->UnloadProject( &mgr->Prj() );
600
601 mgr->LoadProject( pro.GetFullPath() );
602
603 if( Kiface().IsSingle() )
604 {
605 // Standalone opens can switch to a different project. Preload libraries after the
606 // project switch so the board load sees project-local library tables.
609 }
610
611 // Do not allow saving a project if one doesn't exist. This normally happens if we are
612 // opening a board that has been moved from its project folder.
613 // For converted projects, we don't want to set the read-only flag because we want a
614 // project to be saved for the new file in case things like netclasses got migrated.
615 Prj().SetReadOnly( !pro.Exists() && !converted );
616 }
617
618 // Crash-recovery: when zip-format autosave is active, look for autosave files newer than
619 // the saved board and offer to recover them before the load happens.
620 if( !is_new )
621 CheckForAutosaveFiles( wx_filename.GetPath(), { FILEEXT::KiCadPcbFileExtension } );
622
623 if( is_new )
624 {
625 // Link the existing blank board to the new project
626 GetBoard()->SetProject( &Prj() );
627
628 GetBoard()->SetFileName( fullFileName );
629
630 OnModify();
631 }
632 else
633 {
634 BOARD* loadedBoard = nullptr; // it will be set to non-NULL if loaded OK
635 bool failedLoad = false;
636
637 try
638 {
639 std::map<std::string, UTF8> props;
640
642 props.insert( m_importProperties->begin(), m_importProperties->end() );
643
644 // PCB_IO_EAGLE can use this info to center the BOARD, but it does not yet.
645 props["page_width"] = std::to_string( GetPageSizeIU().x );
646 props["page_height"] = std::to_string( GetPageSizeIU().y );
647
648#if USE_INSTRUMENTATION
649 // measure the time to load a BOARD.
650 int64_t startTime = GetRunningMicroSecs();
651#endif
652 BOARD_LOADER::OPTIONS loaderOptions;
653 loaderOptions.properties = &props;
654 loaderOptions.progress_reporter = &progressReporter;
655 loaderOptions.reporter = config()->m_System.show_import_issues
656 ? static_cast<REPORTER*>( &loadReporter )
657 : static_cast<REPORTER*>( &NULL_REPORTER::GetInstance() );
658 loaderOptions.initialize_after_load = false;
659 loaderOptions.plugin_configurator =
660 [&]( PCB_IO& aPlugin )
661 {
662 if( LAYER_MAPPABLE_PLUGIN* mappable_pi =
663 dynamic_cast<LAYER_MAPPABLE_PLUGIN*>( &aPlugin ) )
664 {
665 if( !ADVANCED_CFG::GetCfg().m_ImportSkipLayerMapping )
666 {
667 mappable_pi->RegisterCallback( std::bind( DIALOG_MAP_LAYERS::RunModal,
668 this,
669 std::placeholders::_1 ) );
670 }
671 }
672
673 if( PROJECT_CHOOSER_PLUGIN* chooser_pi =
674 dynamic_cast<PROJECT_CHOOSER_PLUGIN*>( &aPlugin ) )
675 {
676 chooser_pi->RegisterCallback(
678 this,
679 std::placeholders::_1 ) );
680 }
681
682 aPlugin.SetQueryUserCallback(
683 [&]( wxString aTitle, int aIcon, wxString aMessage,
684 wxString aAction ) -> bool
685 {
686 KIDIALOG dlg( nullptr, aMessage, aTitle,
687 wxOK | wxCANCEL | aIcon );
688
689 if( !aAction.IsEmpty() )
690 dlg.SetOKLabel( aAction );
691
692 dlg.DoNotShowCheckbox( aMessage, 0 );
693
694 return dlg.ShowModal() == wxID_OK;
695 } );
696 };
697
698 std::unique_ptr<BOARD> loaded =
699 BOARD_LOADER::Load( fullFileName, pluginType, &Prj(), loaderOptions );
700 loadedBoard = loaded.release();
701
702#if USE_INSTRUMENTATION
703 int64_t stopTime = GetRunningMicroSecs();
704 printf( "PCB_IO::Load(): %u usecs\n", stopTime - startTime );
705#endif
706 }
707 catch( const FUTURE_FORMAT_ERROR& ffe )
708 {
709 msg.Printf( _( "Error loading PCB '%s'." ), fullFileName );
710 progressReporter.Hide();
711 DisplayErrorMessage( this, msg, ffe.Problem() );
712
713 failedLoad = true;
714 }
715 catch( const IO_ERROR& ioe )
716 {
717 if( ioe.Problem() != wxT( "CANCEL" ) )
718 {
719 msg.Printf( _( "Error loading PCB '%s'." ), fullFileName );
720 progressReporter.Hide();
721 DisplayErrorMessage( this, msg, ioe.What() );
722 }
723
724 failedLoad = true;
725 }
726 catch( const std::bad_alloc& )
727 {
728 msg.Printf( _( "Memory exhausted loading PCB '%s'" ), fullFileName );
729 progressReporter.Hide();
730 DisplayErrorMessage( this, msg, wxEmptyString );
731
732 failedLoad = true;
733 }
734
735 if( failedLoad || !loadedBoard )
736 {
737 // We didn't create a new blank board above, so do that now
738 Clear_Pcb( false );
739
740 // Show any messages collected before the failure
741 if( KISTATUSBAR* statusBar = dynamic_cast<KISTATUSBAR*>( GetStatusBar() ) )
742 statusBar->AddWarningMessages( "load", loadReporter.GetMessages() );
743
744 return false;
745 }
746
747 if( converted && GetPcbNewSettings()->m_ImportKeepKiCadLayerNames )
748 {
749 for( PCB_LAYER_ID layer : loadedBoard->GetEnabledLayers().Seq() )
750 loadedBoard->SetLayerName( layer, wxEmptyString );
751 }
752
753 // This fixes a focus issue after the progress reporter is done on GTK. It shouldn't
754 // cause any issues on macOS and Windows. If it does, it will have to be conditionally
755 // compiled.
756 Raise();
757
758 // Skip (possibly expensive) connectivity build here; we build it below after load
759 progressReporter.AddPhases( 1 );
760 progressReporter.AdvancePhase( _( "Finalizing board" ) );
761 progressReporter.KeepRefreshing();
762
763 PROF_TIMER postLoadTimer;
764 SetBoard( loadedBoard, false, &progressReporter );
765 wxLogTrace( traceAllegroPerf, wxT( "Post-load SetBoard: %.3f ms" ),
766 postLoadTimer.msecs( true ) );
767
768 if( loadedBoard->m_LegacyDesignSettingsLoaded )
769 {
770 Prj().SetReadOnly( false );
771
772 // Before we had a copper edge clearance setting, the edge line widths could be used
773 // as a kludge to control them. So if there's no setting then infer it from the
774 // edge widths.
775 if( !loadedBoard->m_LegacyCopperEdgeClearanceLoaded )
776 {
777 // Do not show the inferred edge clearance warning dialog when loading third
778 // party boards. For some reason the dialog completely hangs all of KiCad and
779 // the imported board cannot be saved.
780 int edgeClearance = inferLegacyEdgeClearance( loadedBoard, !converted );
781 loadedBoard->GetDesignSettings().m_CopperEdgeClearance = edgeClearance;
782 }
783
784 // On save; design settings will be removed from the board
785 loadedBoard->SetModified();
786 }
787
788 // Move legacy view settings to local project settings
789 if( !loadedBoard->m_LegacyVisibleLayers.test( Rescue ) )
790 {
792 loadedBoard->SetModified();
793 }
794
796 {
798 loadedBoard->SetModified();
799 }
800
801 if( !loadedBoard->SynchronizeComponentClasses( std::unordered_set<wxString>() ) )
802 {
803 m_infoBar->RemoveAllButtons();
804 m_infoBar->AddCloseButton();
805 m_infoBar->ShowMessage( _( "Could not load component class assignment rules" ),
806 wxICON_WARNING, WX_INFOBAR::MESSAGE_TYPE::GENERIC );
807 }
808
809 // we should not ask PCB_IOs to do these items:
810 loadedBoard->BuildListOfNets();
811 wxLogTrace( traceAllegroPerf, wxT( "Post-load BuildListOfNets: %.3f ms" ),
812 postLoadTimer.msecs( true ) );
813
814 progressReporter.KeepRefreshing();
815
816 m_toolManager->RunAction( PCB_ACTIONS::repairBoard, true);
817 wxLogTrace( traceAllegroPerf, wxT( "Post-load repairBoard: %.3f ms" ),
818 postLoadTimer.msecs( true ) );
819
820 progressReporter.KeepRefreshing();
821
823 wxLogTrace( traceAllegroPerf, wxT( "Post-load rehatchShapes: %.3f ms" ),
824 postLoadTimer.msecs( true ) );
825
826 progressReporter.KeepRefreshing();
827
828 if( loadedBoard->IsModified() )
829 OnModify();
830 else
831 GetScreen()->SetContentModified( false );
832
833 if( ( pluginType == PCB_IO_MGR::LEGACY )
834 || ( pluginType == PCB_IO_MGR::KICAD_SEXP
836 && loadedBoard->GetGenerator().Lower() != wxT( "gerbview" ) ) )
837 {
838 m_infoBar->RemoveAllButtons();
839 m_infoBar->AddCloseButton();
840 m_infoBar->ShowMessage( _( "This file was created by an older version of KiCad. "
841 "It will be converted to the new format when saved." ),
842 wxICON_WARNING, WX_INFOBAR::MESSAGE_TYPE::OUTDATED_SAVE );
843 }
844
845 // TODO(JE) library tables -- I think this functionality should be deleted
846#if 0
847
848 // Import footprints into a project-specific library
849 //==================================================
850 // TODO: This should be refactored out of here into somewhere specific to the Project Import
851 // E.g. KICAD_MANAGER_FRAME::ImportNonKiCadProject
852 if( aCtl & KICTL_IMPORT_LIB )
853 {
854 wxFileName loadedBoardFn( fullFileName );
855 wxString libNickName = loadedBoardFn.GetName();
856
857 // Extract a footprint library from the design and add it to the fp-lib-table
858 // The footprints are saved in a new .pretty library.
859 // If this library already exists, all previous footprints will be deleted
860 std::vector<FOOTPRINT*> loadedFootprints = pi->GetImportedCachedLibraryFootprints();
861 wxString newLibPath = CreateNewProjectLibrary( _( "New Footprint Library" ),
862 libNickName );
863
864 // Only create the new library if CreateNewLibrary succeeded (note that this fails if
865 // the library already exists and the user aborts after seeing the warning message
866 // which prompts the user to continue with overwrite or abort)
867 if( newLibPath.Length() > 0 )
868 {
870
871 for( FOOTPRINT* footprint : loadedFootprints )
872 {
873 try
874 {
875 if( !footprint->GetFPID().GetLibItemName().empty() ) // Handle old boards.
876 {
877 footprint->SetReference( "REF**" );
878 piSexpr->FootprintSave( newLibPath, footprint );
879 delete footprint;
880 }
881 }
882 catch( const IO_ERROR& ioe )
883 {
884 wxLogError( _( "Error saving footprint %s to project specific library." )
885 + wxS( "\n%s" ),
886 footprint->GetFPID().GetUniStringLibItemName(),
887 ioe.What() );
888 }
889 }
890
891 FP_LIB_TABLE* prjlibtable = PROJECT_PCB::PcbFootprintLibs( &Prj() );
892 const wxString& project_env = PROJECT_VAR_NAME;
893 wxString rel_path, env_path;
894
895 wxASSERT_MSG( wxGetEnv( project_env, &env_path ),
896 wxT( "There is no project variable?" ) );
897
898 wxString result( newLibPath );
899
900 if( result.Replace( env_path, wxT( "$(" ) + project_env + wxT( ")" ) ) )
901 rel_path = result;
902
903 FP_LIB_TABLE_ROW* row = new FP_LIB_TABLE_ROW( libNickName, rel_path,
904 wxT( "KiCad" ), wxEmptyString );
905 prjlibtable->InsertRow( row );
906
907 wxString tblName = Prj().FootprintLibTblName();
908
909 try
910 {
911 PROJECT_PCB::PcbFootprintLibs( &Prj() )->Save( tblName );
912 }
913 catch( const IO_ERROR& ioe )
914 {
915 wxLogError( _( "Error saving project specific footprint library table." )
916 + wxS( "\n%s" ),
917 ioe.What() );
918 }
919
920 // Update footprint LIB_IDs to point to the just imported library
921 for( FOOTPRINT* footprint : GetBoard()->Footprints() )
922 {
923 LIB_ID libId = footprint->GetFPID();
924
925 if( libId.GetLibItemName().empty() )
926 continue;
927
928 libId.SetLibNickname( libNickName );
929 footprint->SetFPID( libId );
930 }
931 }
932 }
933#endif
934 }
935
936 {
937 wxString fname;
938
939 if( !previousBoardFileName.IsEmpty() && ( aCtl & KICTL_NONKICAD_ONLY ) && !setProject )
940 {
941 fname = previousBoardFileName;
942 }
943 else
944 {
945 wxFileName fn;
946
947 fn.SetPath( Prj().GetProjectPath() );
948 fn.SetName( Prj().GetProjectName() );
950
951 fname = fn.GetFullPath();
952
953 fname.Replace( WIN_STRING_DIR_SEP, UNIX_STRING_DIR_SEP );
954 }
955
956 GetBoard()->SetFileName( fname );
957 }
958
959 // Lock the file newly opened:
960 m_file_checker.reset( lock.release() );
961
962 if( !converted )
963 UpdateFileHistory( GetBoard()->GetFileName() );
964
965 std::vector<ZONE*> toFill;
966
967 // Rebuild list of nets (full ratsnest rebuild)
968 PROF_TIMER connectivityTimer;
969 GetBoard()->BuildConnectivity( &progressReporter );
970 wxLogTrace( traceAllegroPerf, wxT( "Post-load BuildConnectivity: %.3f ms" ),
971 connectivityTimer.msecs( true ) );
972
973 // Load project settings after setting up board; some of them depend on the nets list
976 wxLogTrace( traceAllegroPerf, wxT( "Post-load LoadProjectSettings+DrawingSheet: %.3f ms" ),
977 connectivityTimer.msecs( true ) );
978
979 // Resolve DRC exclusions after project settings are loaded
980 ResolveDRCExclusions( true );
981
982 // Initialise caches used by component classes
984
985 // Initialise time domain tuning caches
987 wxLogTrace( traceAllegroPerf, wxT( "Post-load DRC+ComponentClass+Tuning caches: %.3f ms" ),
988 connectivityTimer.msecs( true ) );
989
990 // Syncs the UI (appearance panel, etc) with the loaded board and project
992 wxLogTrace( traceAllegroPerf, wxT( "Post-load OnBoardLoaded: %.3f ms" ),
993 connectivityTimer.msecs( true ) );
994 wxLogTrace( traceAllegroPerf, wxT( "=== Post-load pipeline total: %.3f ms ===" ),
995 connectivityTimer.msecs() );
996
997 // Refresh the 3D view, if any
998 EDA_3D_VIEWER_FRAME* draw3DFrame = Get3DViewerFrame();
999
1000 if( draw3DFrame )
1001 draw3DFrame->NewDisplay();
1002#if 0 && defined(DEBUG)
1003 // Output the board object tree to stdout, but please run from command prompt:
1004 GetBoard()->Show( 0, std::cout );
1005#endif
1006
1007 // from EDA_APPL which was first loaded BOARD only:
1008 {
1009 /* For an obscure reason the focus is lost after loading a board file
1010 * when starting up the process.
1011 * (seems due to the recreation of the layer manager after loading the file)
1012 * Give focus to main window and Drawpanel
1013 * must be done for these 2 windows (for an obscure reason ...)
1014 * Linux specific
1015 * This is more a workaround than a fix.
1016 */
1017 SetFocus();
1018 GetCanvas()->SetFocus();
1019 }
1020
1021 if( !setProject )
1022 {
1023 // If we didn't reload the project, we still need to call ProjectChanged() to ensure
1024 // frame-specific initialization happens (like registering the autosave saver).
1025 // When running under the project manager, KIWAY::ProjectChanged() was called before
1026 // this frame existed, so we need to call our own ProjectChanged() now.
1028 }
1029
1030 if( KISTATUSBAR* statusBar = dynamic_cast<KISTATUSBAR*>( GetStatusBar() ) )
1031 statusBar->AddWarningMessages( "load", loadReporter.GetMessages() );
1032
1033 return true;
1034}
1035
1036
1037bool PCB_EDIT_FRAME::SavePcbFile( const wxString& aFileName, bool addToHistory,
1038 bool aChangeProject )
1039{
1040 // please, keep it simple. prompting goes elsewhere.
1041 wxFileName pcbFileName = aFileName;
1042
1043 if( pcbFileName.GetExt() == FILEEXT::LegacyPcbFileExtension )
1044 pcbFileName.SetExt( FILEEXT::KiCadPcbFileExtension );
1045
1046 // Write through symlinks, don't replace them
1048
1049 if( !IsWritable( pcbFileName ) )
1050 {
1051 wxString msg = wxString::Format( _( "Insufficient permissions to write file '%s'." ),
1052 pcbFileName.GetFullPath() );
1053
1054 DisplayError( this, msg );
1055 return false;
1056 }
1057
1058 // TODO: these will break if we ever go multi-board
1059 wxFileName projectFile( pcbFileName );
1060 wxFileName rulesFile( pcbFileName );
1061 wxString msg;
1062
1063 projectFile.SetExt( FILEEXT::ProjectFileExtension );
1064 rulesFile.SetExt( FILEEXT::DesignRulesFileExtension );
1065
1066 if( projectFile.FileExists() )
1067 {
1069 }
1070 else if( aChangeProject )
1071 {
1072 Prj().SetReadOnly( false );
1073 GetSettingsManager()->SaveProjectAs( projectFile.GetFullPath() );
1074 }
1075
1076 wxFileName currentRules( GetBoard()->GetDesignRulesPath() );
1077
1078 if( currentRules.FileExists() && !rulesFile.FileExists() && aChangeProject )
1079 KiCopyFile( currentRules.GetFullPath(), rulesFile.GetFullPath(), msg );
1080
1081 if( !msg.IsEmpty() )
1082 {
1083 DisplayError( this, wxString::Format( _( "Error saving custom rules file '%s'." ),
1084 rulesFile.GetFullPath() ) );
1085 }
1086
1087 if( projectFile.FileExists() )
1088 {
1089 // Save various DRC parameters, such as violation severities (which may have been
1090 // edited via the DRC dialog as well as the Board Setup dialog), DRC exclusions, etc.
1092
1095 }
1096
1097 wxString upperTxt;
1098 wxString lowerTxt;
1099
1100 // On Windows, ensure the target file is writeable by clearing problematic attributes like
1101 // hidden or read-only. This can happen when files are synced via cloud services.
1102 if( pcbFileName.FileExists() )
1103 KIPLATFORM::IO::MakeWriteable( pcbFileName.GetFullPath() );
1104
1105 try
1106 {
1108
1109 pi->SaveBoard( pcbFileName.GetFullPath(), GetBoard(), nullptr );
1110 }
1111 catch( const IO_ERROR& ioe )
1112 {
1113 DisplayError( this, wxString::Format( _( "Error saving board file '%s'.\n%s" ),
1114 pcbFileName.GetFullPath(),
1115 ioe.What() ) );
1116 return false;
1117 }
1118
1119 if( !Kiface().IsSingle() )
1120 {
1121 WX_STRING_REPORTER backupReporter;
1122
1123 if( !GetSettingsManager()->TriggerBackupIfNeeded( backupReporter ) )
1124 {
1125 upperTxt = backupReporter.GetMessages();
1126 SetStatusText( upperTxt, 1 );
1127 }
1128 }
1129
1130 GetBoard()->SetFileName( pcbFileName.GetFullPath() );
1131
1132 // Update the lock in case it was a Save As
1133 LockFile( pcbFileName.GetFullPath() );
1134
1135 // Put the saved file in File History if requested
1136 if( addToHistory )
1137 UpdateFileHistory( GetBoard()->GetFileName() );
1138
1139 lowerTxt.Printf( _( "File '%s' saved." ), pcbFileName.GetFullPath() );
1140
1141 SetStatusText( lowerTxt, 0 );
1142
1143 // Get rid of the old version conversion warning, or any other dismissable warning :)
1144 if( m_infoBar->GetMessageType() == WX_INFOBAR::MESSAGE_TYPE::OUTDATED_SAVE )
1145 m_infoBar->Dismiss();
1146
1147 if( m_infoBar->IsShownOnScreen() && m_infoBar->HasCloseButton() )
1148 m_infoBar->Dismiss();
1149
1150 GetScreen()->SetContentModified( false );
1151 UpdateTitle();
1153
1154 // Capture entire project state for PCB save events. Skip when running standalone
1155 // without a project loaded - the save path can land anywhere on the filesystem and
1156 // there is no project context for a snapshot to live under.
1157 if( !Prj().IsNullProject() )
1158 {
1159 Kiway().LocalHistory().RunRegisteredSaversAndCommit( Prj().GetProjectPath(), wxS( "PCB Save" ), wxS( "pcb" ) );
1160
1161 // Drop the autosave file for the board we just persisted. Scope to the PCB
1162 // source so a concurrent open eeschema does not lose recovery data for an
1163 // unsaved schematic sheet. RunRegisteredSaversAndCommit above is a no-op when
1164 // format is ZIP; this call is conversely a no-op in INCREMENTAL mode.
1165 Kiway().LocalHistory().RemoveAutosaveFiles( Prj().GetProjectPath(), { pcbFileName.GetFullPath() } );
1166 }
1167
1168 if( m_autoSaveTimer )
1169 m_autoSaveTimer->Stop();
1170
1171 m_autoSavePending = false;
1172 m_autoSaveRequired = false;
1173 return true;
1174}
1175
1176
1177bool PCB_EDIT_FRAME::SavePcbCopy( const wxString& aFileName, bool aCreateProject, bool aHeadless )
1178{
1179 wxFileName pcbFileName( aFileName );
1180
1181 if( !IsWritable( pcbFileName ) )
1182 {
1183 if( !aHeadless )
1184 {
1185 DisplayError( this, wxString::Format( _( "Insufficient permissions to write file '%s'." ),
1186 pcbFileName.GetFullPath() ) );
1187 }
1188 return false;
1189 }
1190
1191 // Save various DRC parameters, such as violation severities (which may have been
1192 // edited via the DRC dialog as well as the Board Setup dialog), DRC exclusions, etc.
1194
1196
1197 // On Windows, ensure the target file is writeable by clearing problematic attributes like
1198 // hidden or read-only. This can happen when files are synced via cloud services.
1199 if( pcbFileName.FileExists() )
1200 KIPLATFORM::IO::MakeWriteable( pcbFileName.GetFullPath() );
1201
1202 try
1203 {
1205
1206 wxASSERT( pcbFileName.IsAbsolute() );
1207
1208 pi->SaveBoard( pcbFileName.GetFullPath(), GetBoard(), nullptr );
1209 }
1210 catch( const IO_ERROR& ioe )
1211 {
1212 if( !aHeadless )
1213 {
1214 DisplayError( this, wxString::Format( _( "Error saving board file '%s'.\n%s" ),
1215 pcbFileName.GetFullPath(),
1216 ioe.What() ) );
1217 }
1218
1219 return false;
1220 }
1221
1222 wxFileName projectFile( pcbFileName );
1223 wxFileName rulesFile( pcbFileName );
1224 wxString msg;
1225
1226 projectFile.SetExt( FILEEXT::ProjectFileExtension );
1227 rulesFile.SetExt( FILEEXT::DesignRulesFileExtension );
1228
1229 if( aCreateProject && !projectFile.FileExists() )
1230 GetSettingsManager()->SaveProjectCopy( projectFile.GetFullPath() );
1231
1232 wxFileName currentRules( GetBoard()->GetDesignRulesPath() );
1233
1234 if( aCreateProject && currentRules.FileExists() && !rulesFile.FileExists() )
1235 KiCopyFile( currentRules.GetFullPath(), rulesFile.GetFullPath(), msg );
1236
1237 if( !msg.IsEmpty() && !aHeadless )
1238 {
1239 DisplayError( this, wxString::Format( _( "Error saving custom rules file '%s'." ),
1240 rulesFile.GetFullPath() ) );
1241 }
1242
1243 return true;
1244}
1245
1246
1247bool PCB_EDIT_FRAME::importFile( const wxString& aFileName, int aFileType,
1248 const std::map<std::string, UTF8>* aProperties )
1249{
1250 NULLER raiiNuller( (void*&) m_importProperties );
1251
1252 m_importProperties = aProperties;
1253
1254 switch( (PCB_IO_MGR::PCB_FILE_T) aFileType )
1255 {
1257 case PCB_IO_MGR::EAGLE:
1261 return OpenProjectFiles( std::vector<wxString>( 1, aFileName ), KICTL_NONKICAD_ONLY | KICTL_IMPORT_LIB );
1262
1267 case PCB_IO_MGR::PADS:
1268 return OpenProjectFiles( std::vector<wxString>( 1, aFileName ), KICTL_NONKICAD_ONLY );
1269
1270 default:
1271 return false;
1272 }
1273}
1274
1275
1277{
1279
1280 dlg.ShowModal();
1281
1282 return 0;
1283}
1284
1285
1287{
1289
1290 if( dlg.ShowModal() != wxID_OK )
1291 return 0;
1292
1294
1296 job.m_filename = m_frame->GetBoard()->GetFileName();
1298
1299 job.m_precision = dlg.GetPrecision();
1302
1303 WX_PROGRESS_REPORTER progressReporter( m_frame, _( "Generate ODB++ Files" ), 3, PR_CAN_ABORT );
1305
1306 DIALOG_EXPORT_ODBPP::GenerateODBPPFiles( job, m_frame->GetBoard(), m_frame, &progressReporter, &reporter );
1307
1308 if( reporter.HasMessage() )
1309 DisplayError( m_frame, reporter.GetMessages() );
1310
1311 return 0;
1312}
const char * name
KIFACE_BASE & Kiface()
Global KIFACE_BASE "get" accessor.
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
void SetContentModified(bool aModified=true)
Definition base_screen.h:55
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)
static std::unique_ptr< BOARD > Load(const wxString &aFileName, PCB_IO_MGR::PCB_FILE_T aFormat, PROJECT *aProject, const OPTIONS &aOptions)
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:372
bool m_LegacyDesignSettingsLoaded
True if the legacy board design settings were loaded from a file.
Definition board.h:493
GAL_SET m_LegacyVisibleItems
Definition board.h:490
LENGTH_DELAY_CALCULATION * GetLengthCalculation() const
Returns the track length calculator.
Definition board.h:1516
void BuildListOfNets()
Definition board.h:1049
void SetFileName(const wxString &aFileName)
Definition board.h:407
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:201
void SynchronizeNetsAndNetClasses(bool aResetTrackAndViaSizes)
Copy NETCLASS info to each NET, based on NET membership in a NETCLASS.
Definition board.cpp:3004
bool SetLayerName(PCB_LAYER_ID aLayer, const wxString &aLayerName)
Changes the name of the layer given by aLayer.
Definition board.cpp:811
LSET m_LegacyVisibleLayers
Visibility settings stored in board prior to 6.0, only used for loading legacy files.
Definition board.h:489
void SetProject(PROJECT *aProject, bool aReferenceOnly=false)
Link a board to a given project.
Definition board.cpp:211
const wxString & GetFileName() const
Definition board.h:409
int GetFileFormatVersionAtLoad() const
Definition board.h:513
const wxString & GetGenerator() const
Adds an item to the container.
Definition board.h:516
void ClearProject()
Definition board.cpp:252
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition board.cpp:1149
const LSET & GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
Definition board.cpp:1034
void SynchronizeProperties()
Copy the current project's text variables into the boards property cache.
Definition board.cpp:2809
COMPONENT_CLASS_MANAGER & GetComponentClassManager()
Gets the component class manager.
Definition board.h:1521
bool SynchronizeComponentClasses(const std::unordered_set< wxString > &aNewSheetPaths) const
Copy component class / component class generator information from the project settings.
Definition board.cpp:3034
bool m_LegacyCopperEdgeClearanceLoaded
Definition board.h:494
int GetCount() const
Return the number of objects in the list.
Definition collector.h:79
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.
void CheckForAutosaveFiles(const wxString &aProjectPath, const std::vector< wxString > &aExtensions)
Check for autosave files newer than their source files for the given project.
SETTINGS_MANAGER * GetSettingsManager() const
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:125
bool IsModified() const
Definition eda_item.h:128
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:37
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:163
Helper class to create more flexible dialogs, including 'do not show again' checkbox handling.
Definition kidialog.h:38
void DoNotShowCheckbox(wxString file, int line)
Shows the 'do not show again' checkbox.
Definition kidialog.cpp:51
int ShowModal() override
Definition kidialog.cpp:89
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:422
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:45
int SetLibNickname(const UTF8 &aLibNickname)
Override the logical library name portion of the LIB_ID to aLibNickname.
Definition lib_id.cpp:96
const UTF8 & GetLibItemName() const
Definition lib_id.h:98
bool RunRegisteredSaversAndCommit(const wxString &aProjectPath, const wxString &aTitle, const wxString &aTagFileType=wxEmptyString)
Run all registered savers and, if any staged changes differ from HEAD, create a commit.
bool Init(const wxString &aProjectPath)
Initialize the local history repository for the given project path.
void RemoveAutosaveFiles(const wxString &aProjectPath) const
Remove every autosave file under the project at aProjectPath regardless of which source it shadowed.
LSEQ Seq(const LSEQ &aSequence) const
Return an LSEQ from the union of this LSET and a desired sequence.
Definition lset.cpp:309
Definition raii.h:34
static REPORTER & GetInstance()
Definition reporter.cpp:120
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 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...
PCBNEW_SETTINGS * GetPcbNewSettings() const
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:38
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:96
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:52
@ KICAD_SEXP
S-expression Pcbnew file format.
Definition pcb_io_mgr.h:54
@ GEDA_PCB
Geda PCB file formats.
Definition pcb_io_mgr.h:65
@ ALTIUM_DESIGNER
Definition pcb_io_mgr.h:59
@ LEGACY
Legacy Pcbnew file formats prior to s-expression.
Definition pcb_io_mgr.h:55
@ ALTIUM_CIRCUIT_MAKER
Definition pcb_io_mgr.h:57
@ ALTIUM_CIRCUIT_STUDIO
Definition pcb_io_mgr.h:58
@ CADSTAR_PCB_ARCHIVE
Definition pcb_io_mgr.h:60
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.
A base class that BOARD loading and saving plugins should derive from.
Definition pcb_io.h:75
Collect all BOARD_ITEM objects on a given layer.
Definition collectors.h:545
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:551
void PreloadDesignBlockLibraries(KIWAY *aKiway)
Starts a background job to preload the global and project design block libraries.
Definition pgm_base.cpp:874
A small class to help profiling.
Definition profile.h:46
double msecs(bool aSinceLast=false)
Definition profile.h:147
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:160
virtual const wxString GetProjectFullName() const
Return the full path and name of the project.
Definition project.cpp:177
virtual PROJECT_LOCAL_SETTINGS & GetLocalSettings() const
Definition project.h:206
virtual const wxString FootprintLibTblName() const
Returns the path and filename of this project's footprint library table.
Definition project.cpp:213
virtual bool IsNullProject() const
Check if this project is a null project (i.e.
Definition project.cpp:201
A pure virtual class used to derive REPORTER objects from.
Definition reporter.h:71
void SaveProjectAs(const wxString &aFullPath, PROJECT *aProject=nullptr)
Set the currently loaded project path and saves it (pointers remain valid).
bool SaveProject(const wxString &aFullPath=wxEmptyString, PROJECT *aProject=nullptr)
Save a loaded project.
bool SaveProjectCopy(const wxString &aFullPath, PROJECT *aProject=nullptr)
Save a copy of the current project under the given path.
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:167
bool empty() const
Definition utf8.h:105
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:189
const wxString & GetMessages() const
Definition reporter.cpp:101
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:775
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:38
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition confirm.cpp:274
void DisplayInfoMessage(wxWindow *aParent, const wxString &aMessage, const wxString &aExtraInfo)
Display an informational message box with aMessage.
Definition confirm.cpp:245
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:146
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition confirm.cpp:217
void DisplayError(wxWindow *aParent, const wxString &aText)
Display an error or warning message box with aMessage.
Definition confirm.cpp:192
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:307
#define WIN_STRING_DIR_SEP
Definition gestfich.h:36
#define UNIX_STRING_DIR_SEP
Definition gestfich.h:35
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
PROJECT & Prj()
Definition kicad.cpp:730
#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:283
PCB_LAYER_ID
A quick note on layer IDs:
Definition layer_ids.h:56
@ Edge_Cuts
Definition layer_ids.h:108
@ Rescue
Definition layer_ids.h:117
#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:362
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:77
bool MakeWriteable(const wxString &aFilePath)
Ensures that a file has write permissions.
Definition unix/io.cpp:78
void AllowNetworkFileSystems(wxDialog *aDialog)
Configure a file dialog to show network and virtual file systems.
Definition wxgtk/ui.cpp:448
#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
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:37
#define NAMELESS_PROJECT
default name for nameless projects
Definition project.h:40
KIWAY Kiway(KFCTL_STANDALONE)
bool show_import_issues
Stored value for "show import issues" when importing non-KiCad designs to this application.
std::function< void(PCB_IO &)> plugin_configurator
const std::map< std::string, UTF8 > * properties
PROGRESS_REPORTER * progress_reporter
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
virtual void PreloadLibraries(KIWAY *aKiway)
Definition kiway.h:275
std::string path
IbisParser parser & reporter
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:81
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