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