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