KiCad PCB EDA Suite
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
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 <stambaughw@gmail.com>
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
29#include <confirm.h>
30#include <kidialog.h>
31#include <core/arraydim.h>
32#include <thread_pool.h>
34#include <gestfich.h>
35#include <pcb_edit_frame.h>
38#include <fp_lib_table.h>
39#include <kiface_base.h>
40#include <macros.h>
41#include <trace_helpers.h>
42#include <lockfile.h>
43#include <wx/snglinst.h>
45#include <pcbnew_id.h>
47#include <tool/tool_manager.h>
48#include <board.h>
49#include <kiplatform/app.h>
51#include <widgets/wx_infobar.h>
54#include <paths.h>
55#include <pgm_base.h>
57#include <project_pcb.h>
61#include <pcb_io/pcb_io_mgr.h>
69#include <tools/pcb_actions.h>
70#include "footprint_info_impl.h"
71#include <board_commit.h>
72#include <zone_filler.h>
75#include <wx_filename.h> // For ::ResolvePossibleSymlinks()
76
77#include <kiplatform/io.h>
78
79#include <wx/stdpaths.h>
80#include <wx/ffile.h>
81#include <wx/filedlg.h>
82#include <wx/txtstrm.h>
83#include <wx/wfstream.h>
84#include <wx/zipstrm.h>
85#include <wx/dir.h>
86
87#include "widgets/filedlg_hook_save_project.h"
88
89//#define USE_INSTRUMENTATION 1
90#define USE_INSTRUMENTATION 0
91
92
102bool AskLoadBoardFileName( PCB_EDIT_FRAME* aParent, wxString* aFileName, int aCtl = 0 )
103{
104 std::vector<IO_BASE::IO_FILE_DESC> descriptions;
105
106 for( const auto& plugin : PCB_IO_MGR::PLUGIN_REGISTRY::Instance()->AllPlugins() )
107 {
108 bool isKiCad = plugin.m_type == PCB_IO_MGR::KICAD_SEXP || plugin.m_type == PCB_IO_MGR::LEGACY;
109
110 if( ( aCtl & KICTL_KICAD_ONLY ) && !isKiCad )
111 continue;
112
113 if( ( aCtl & KICTL_NONKICAD_ONLY ) && isKiCad )
114 continue;
115
116 IO_RELEASER<PCB_IO> pi( plugin.m_createFunc() );
117 wxCHECK( pi, false );
118
119 const IO_BASE::IO_FILE_DESC& desc = pi->GetBoardFileDesc();
120
121 if( desc.m_FileExtensions.empty() || !desc.m_CanRead )
122 continue;
123
124 descriptions.emplace_back( desc );
125 }
126
127 wxString fileFiltersStr;
128 std::vector<std::string> allExtensions;
129 std::set<wxString> allWildcardsSet;
130
131 for( const IO_BASE::IO_FILE_DESC& desc : descriptions )
132 {
133 if( !fileFiltersStr.IsEmpty() )
134 fileFiltersStr += wxChar( '|' );
135
136 fileFiltersStr += desc.FileFilter();
137
138 for( const std::string& ext : desc.m_FileExtensions )
139 {
140 allExtensions.emplace_back( ext );
141 allWildcardsSet.insert( wxT( "*." ) + formatWildcardExt( ext ) + wxT( ";" ) );
142 }
143 }
144
145 wxString allWildcardsStr;
146
147 for( const wxString& wildcard : allWildcardsSet )
148 allWildcardsStr << wildcard;
149
150 if( aCtl & KICTL_KICAD_ONLY )
151 {
152 fileFiltersStr = _( "All KiCad Board Files" ) + AddFileExtListToFilter( allExtensions );
153 }
154 else
155 {
156 fileFiltersStr = _( "All supported formats" ) + wxT( "|" ) + allWildcardsStr + wxT( "|" )
157 + fileFiltersStr;
158 }
159
160 wxFileName fileName( *aFileName );
161 wxString path;
162 wxString name;
163
164 if( fileName.FileExists() )
165 {
166 path = fileName.GetPath();
167 name = fileName.GetFullName();
168 }
169 else
170 {
171 path = aParent->GetMruPath();
172
173 if( path.IsEmpty() )
175 // leave name empty
176 }
177
178 bool kicadFormat = ( aCtl & KICTL_KICAD_ONLY );
179
180 wxFileDialog dlg( aParent,
181 kicadFormat ? _( "Open Board File" ) : _( "Import Non KiCad Board File" ),
182 path, name, fileFiltersStr, wxFD_OPEN | wxFD_FILE_MUST_EXIST );
183
184 FILEDLG_IMPORT_NON_KICAD importOptions( aParent->config()->m_System.show_import_issues );
185
186 if( !kicadFormat )
187 dlg.SetCustomizeHook( importOptions );
188
189 if( dlg.ShowModal() == wxID_OK )
190 {
191 *aFileName = dlg.GetPath();
192 aParent->SetMruPath( wxFileName( dlg.GetPath() ).GetPath() );
193
194 if( !kicadFormat )
195 aParent->config()->m_System.show_import_issues = importOptions.GetShowIssues();
196
197 return true;
198 }
199 else
200 {
201 return false;
202 }
203}
204
205
215bool AskSaveBoardFileName( PCB_EDIT_FRAME* aParent, wxString* aFileName, bool* aCreateProject )
216{
217 wxString wildcard = FILEEXT::PcbFileWildcard();
218 wxFileName fn = *aFileName;
219
221
222 wxFileDialog dlg( aParent, _( "Save Board File As" ), fn.GetPath(), fn.GetFullName(), wildcard,
223 wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
224
225// Add a "Create a project" checkbox in standalone mode and one isn't loaded
226 FILEDLG_HOOK_SAVE_PROJECT newProjectHook;
227
228 if( Kiface().IsSingle() && aParent->Prj().IsNullProject() )
229 dlg.SetCustomizeHook( newProjectHook );
230
231 if( dlg.ShowModal() != wxID_OK )
232 return false;
233
234 *aFileName = dlg.GetPath();
235 *aFileName = EnsureFileExtension( *aFileName, FILEEXT::KiCadPcbFileExtension );
236
237 if( newProjectHook.IsAttachedToDialog() )
238 *aCreateProject = newProjectHook.GetCreateNewProject();
239 else if( !aParent->Prj().IsNullProject() )
240 *aCreateProject = true;
241
242 return true;
243}
244
245
246void PCB_EDIT_FRAME::OnFileHistory( wxCommandEvent& event )
247{
248 wxString fn = GetFileFromHistory( event.GetId(), _( "Printed circuit board" ) );
249
250 if( !!fn )
251 {
252 if( !wxFileName::IsFileReadable( fn ) )
253 {
254 if( !AskLoadBoardFileName( this, &fn, KICTL_KICAD_ONLY ) )
255 return;
256 }
257
258 OpenProjectFiles( std::vector<wxString>( 1, fn ), KICTL_KICAD_ONLY );
259 }
260}
261
262
263void PCB_EDIT_FRAME::OnClearFileHistory( wxCommandEvent& aEvent )
264{
266}
267
268
269void PCB_EDIT_FRAME::Files_io( wxCommandEvent& event )
270{
271 int id = event.GetId();
272 Files_io_from_id( id );
273}
274
275
277{
278 wxString msg;
279
280 switch( id )
281 {
282 case ID_LOAD_FILE:
283 {
284 // Only standalone mode can directly load a new document
285 if( !Kiface().IsSingle() )
286 return false;
287
288 int open_ctl = KICTL_KICAD_ONLY;
289 wxString fileName = Prj().AbsolutePath( GetBoard()->GetFileName() );
290
291 return AskLoadBoardFileName( this, &fileName, open_ctl )
292 && OpenProjectFiles( std::vector<wxString>( 1, fileName ), open_ctl );
293 }
294
296 {
297 // Note: we explicitly allow this even if not in standalone mode for now, even though it is dangerous.
298 int open_ctl = KICTL_NONKICAD_ONLY;
299 wxString fileName; // = Prj().AbsolutePath( GetBoard()->GetFileName() );
300
301 return AskLoadBoardFileName( this, &fileName, open_ctl )
302 && OpenProjectFiles( std::vector<wxString>( 1, fileName ), open_ctl );
303 }
304
306 {
307 wxFileName currfn = Prj().AbsolutePath( GetBoard()->GetFileName() );
308 wxFileName fn = currfn;
309
310 wxString rec_name = FILEEXT::AutoSaveFilePrefix + fn.GetName();
311 fn.SetName( rec_name );
312
313 if( !fn.FileExists() )
314 {
315 msg.Printf( _( "Recovery file '%s' not found." ), fn.GetFullPath() );
316 DisplayInfoMessage( this, msg );
317 return false;
318 }
319
320 msg.Printf( _( "OK to load recovery file '%s'?" ), fn.GetFullPath() );
321
322 if( !IsOK( this, msg ) )
323 return false;
324
325 GetScreen()->SetContentModified( false ); // do not prompt the user for changes
326
327 if( OpenProjectFiles( std::vector<wxString>( 1, fn.GetFullPath() ) ) )
328 {
329 // Re-set the name since name or extension was changed
330 GetBoard()->SetFileName( currfn.GetFullPath() );
331 UpdateTitle();
332 return true;
333 }
334
335 return false;
336 }
337
338 case ID_REVERT_BOARD:
339 {
340 wxFileName fn = Prj().AbsolutePath( GetBoard()->GetFileName() );
341
342 msg.Printf( _( "Revert '%s' to last version saved?" ), fn.GetFullPath() );
343
344 if( !IsOK( this, msg ) )
345 return false;
346
347 GetScreen()->SetContentModified( false ); // do not prompt the user for changes
348
349 ReleaseFile();
350
351 return OpenProjectFiles( std::vector<wxString>( 1, fn.GetFullPath() ), KICTL_REVERT );
352 }
353
354 case ID_NEW_BOARD:
355 {
356 // Only standalone mode can directly load a new document
357 if( !Kiface().IsSingle() )
358 return false;
359
360 if( IsContentModified() )
361 {
362 wxFileName fileName = GetBoard()->GetFileName();
363 wxString saveMsg = _( "Current board will be closed, save changes to '%s' before "
364 "continuing?" );
365
366 if( !HandleUnsavedChanges( this, wxString::Format( saveMsg, fileName.GetFullName() ),
367 [&]()->bool
368 {
369 return Files_io_from_id( ID_SAVE_BOARD );
370 } ) )
371 {
372 return false;
373 }
374 }
375 else if( !GetBoard()->IsEmpty() )
376 {
377 if( !IsOK( this, _( "Current Board will be closed. Continue?" ) ) )
378 return false;
379 }
380
382
384
386 mgr->UnloadProject( &mgr->Prj() );
387
388 if( !Clear_Pcb( false ) )
389 return false;
390
393
395
396 OnModify();
397 return true;
398 }
399
400 case ID_SAVE_BOARD:
401 if( !GetBoard()->GetFileName().IsEmpty() )
402 {
403 if( SavePcbFile( Prj().AbsolutePath( GetBoard()->GetFileName() ) ) )
404 {
405 m_autoSaveRequired = false;
406 return true;
407 }
408
409 return false;
410 }
411
413
414 case ID_COPY_BOARD_AS:
415 case ID_SAVE_BOARD_AS:
416 {
417 bool addToHistory = ( id == ID_SAVE_BOARD_AS );
418 wxString orig_name;
419
420 wxFileName::SplitPath( GetBoard()->GetFileName(), nullptr, nullptr, &orig_name, nullptr );
421
422 if( orig_name.IsEmpty() )
423 orig_name = NAMELESS_PROJECT;
424
425 wxFileName savePath( Prj().GetProjectFullName() );
426
427 if( !savePath.IsOk() || !savePath.IsDirWritable() )
428 {
429 savePath = GetMruPath();
430
431 if( !savePath.IsOk() || !savePath.IsDirWritable() )
433 }
434
435 wxFileName fn( savePath.GetPath(), orig_name, FILEEXT::KiCadPcbFileExtension );
436 wxString filename = fn.GetFullPath();
437 bool createProject = false;
438 bool success = false;
439
440 if( AskSaveBoardFileName( this, &filename, &createProject ) )
441 {
442 if( id == ID_COPY_BOARD_AS )
443 {
444 success = SavePcbCopy( EnsureFileExtension( filename, FILEEXT::KiCadPcbFileExtension ), createProject );
445 }
446 else
447 {
448 success = SavePcbFile( filename, addToHistory, createProject );
449
450 if( success )
451 m_autoSaveRequired = false;
452 }
453 }
454
455 return success;
456 }
457
458 default:
459 return false;
460 }
461}
462
463
464int PCB_EDIT_FRAME::inferLegacyEdgeClearance( BOARD* aBoard, bool aShowUserMsg )
465{
466 PCB_LAYER_COLLECTOR collector;
467
468 collector.SetLayerId( Edge_Cuts );
469 collector.Collect( aBoard, GENERAL_COLLECTOR::AllBoardItems );
470
471 int edgeWidth = -1;
472 bool mixed = false;
473
474 for( int i = 0; i < collector.GetCount(); i++ )
475 {
476 if( collector[i]->Type() == PCB_SHAPE_T )
477 {
478 int itemWidth = static_cast<PCB_SHAPE*>( collector[i] )->GetWidth();
479
480 if( edgeWidth != -1 && edgeWidth != itemWidth )
481 {
482 mixed = true;
483 edgeWidth = std::max( edgeWidth, itemWidth );
484 }
485 else
486 {
487 edgeWidth = itemWidth;
488 }
489 }
490 }
491
492 if( mixed && aShowUserMsg )
493 {
494 // If they had different widths then we can't ensure that fills will be the same.
495 DisplayInfoMessage( this,
496 _( "If the zones on this board are refilled the Copper Edge "
497 "Clearance setting will be used (see Board Setup > Design "
498 "Rules > Constraints).\n This may result in different fills "
499 "from previous KiCad versions which used the line thicknesses "
500 "of the board boundary on the Edge Cuts layer." ) );
501 }
502
503 return std::max( 0, edgeWidth / 2 );
504}
505
506
507bool PCB_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, int aCtl )
508{
509 // This is for python:
510 if( aFileSet.size() != 1 )
511 {
512 UTF8 msg = StrPrintf( "Pcbnew:%s() takes a single filename", __func__ );
513 DisplayError( this, msg );
514 return false;
515 }
516
517 wxString fullFileName( aFileSet[0] );
518 wxFileName wx_filename( fullFileName );
519 wxString msg;
520
521 if( Kiface().IsSingle() )
523
524 // We insist on caller sending us an absolute path, if it does not, we say it's a bug.
525 wxASSERT_MSG( wx_filename.IsAbsolute(), wxT( "Path is not absolute!" ) );
526
527 std::unique_ptr<LOCKFILE> lock = std::make_unique<LOCKFILE>( fullFileName );
528
529 if( !lock->Valid() && lock->IsLockedByMe() )
530 {
531 // If we cannot acquire the lock but we appear to be the one who locked it, check to
532 // see if there is another KiCad instance running. If not, then we can override the
533 // lock. This could happen if KiCad crashed or was interrupted.
534
535 if( !Pgm().SingleInstance()->IsAnotherRunning() )
536 lock->OverrideLock();
537 }
538
539 if( !lock->Valid() )
540 {
541 msg.Printf( _( "PCB '%s' is already open by '%s' at '%s'." ),
542 wx_filename.GetFullName(),
543 lock->GetUsername(),
544 lock->GetHostname() );
545
546 if( !AskOverrideLock( this, msg ) )
547 return false;
548
549 lock->OverrideLock();
550 }
551
552 if( IsContentModified() )
553 {
554 if( !HandleUnsavedChanges( this, _( "The current PCB has been modified. Save changes?" ),
555 [&]() -> bool
556 {
557 return SavePcbFile( GetBoard()->GetFileName() );
558 } ) )
559 {
560 return false;
561 }
562 }
563
564 wxFileName pro = fullFileName;
565 pro.SetExt( FILEEXT::ProjectFileExtension );
566
567 bool is_new = !wxFileName::IsFileReadable( fullFileName );
568
569 // If its a non-existent PCB and caller thinks it exists
570 if( is_new && !( aCtl & KICTL_CREATE ) )
571 {
572 // notify user that fullFileName does not exist, ask if user wants to create it.
573 msg.Printf( _( "PCB '%s' does not exist. Do you wish to create it?" ), fullFileName );
574
575 if( !IsOK( this, msg ) )
576 return false;
577 }
578
579 // Get rid of any existing warnings about the old board
580 GetInfoBar()->Dismiss();
581
582 WX_PROGRESS_REPORTER progressReporter( this, is_new ? _( "Creating PCB" )
583 : _( "Loading PCB" ), 1 );
584
585 // No save prompt (we already prompted above), and only reset to a new blank board if new
586 Clear_Pcb( false, !is_new );
587
589
590 if( !is_new )
591 pluginType = PCB_IO_MGR::FindPluginTypeFromBoardPath( fullFileName, aCtl );
592
593 if( pluginType == PCB_IO_MGR::FILE_TYPE_NONE )
594 {
595 progressReporter.Hide();
596 DisplayErrorMessage( this, _( "File format is not supported" ), wxEmptyString );
597 return false;
598 }
599
600 bool converted = pluginType != PCB_IO_MGR::LEGACY && pluginType != PCB_IO_MGR::KICAD_SEXP;
601
602 // Loading a project should only be done under carefully considered circumstances.
603
604 // The calling code should know not to ask me here to change projects unless
605 // it knows what consequences that will have on other KIFACEs running and using
606 // this same PROJECT. It can be very harmful if that calling code is stupid.
608 bool setProject;
609
610 if( Kiface().IsSingle() || !( aCtl & KICTL_NONKICAD_ONLY ) )
611 setProject = pro.GetFullPath() != mgr->Prj().GetProjectFullName();
612 else
613 setProject = Prj().GetProjectFullName().IsEmpty();
614
615 wxString path = wxPathOnly( Prj().GetProjectFullName() );
616
617 if( setProject )
618 {
619 // calls SaveProject
621
623 mgr->UnloadProject( &mgr->Prj() );
624
625 mgr->LoadProject( pro.GetFullPath() );
626
627 // Do not allow saving a project if one doesn't exist. This normally happens if we are
628 // opening a board that has been moved from its project folder.
629 // For converted projects, we don't want to set the read-only flag because we want a
630 // project to be saved for the new file in case things like netclasses got migrated.
631 Prj().SetReadOnly( !pro.Exists() && !converted );
632 }
633
634 // Clear the cache footprint list which may be project specific
636
637 if( is_new )
638 {
639 // Link the existing blank board to the new project
640 GetBoard()->SetProject( &Prj() );
641
642 GetBoard()->SetFileName( fullFileName );
643
644 OnModify();
645 }
646 else
647 {
648 BOARD* loadedBoard = nullptr; // it will be set to non-NULL if loaded OK
650
651 if( LAYER_MAPPABLE_PLUGIN* mappable_pi = dynamic_cast<LAYER_MAPPABLE_PLUGIN*>( pi.get() ) )
652 {
653 mappable_pi->RegisterCallback( std::bind( DIALOG_MAP_LAYERS::RunModal,
654 this, std::placeholders::_1 ) );
655 }
656
657 if( PROJECT_CHOOSER_PLUGIN* chooser_pi = dynamic_cast<PROJECT_CHOOSER_PLUGIN*>( pi.get() ) )
658 {
659 chooser_pi->RegisterCallback( std::bind( DIALOG_IMPORT_CHOOSE_PROJECT::RunModal,
660 this,
661 std::placeholders::_1 ) );
662 }
663
664 if( ( aCtl & KICTL_REVERT ) )
665 {
666 DeleteAutoSaveFile( fullFileName );
667 }
668 else
669 {
670 // This will rename the file if there is an autosave and the user wants to recover
671 CheckForAutoSaveFile( fullFileName );
672 }
673
674 DIALOG_HTML_REPORTER errorReporter( this );
675 bool failedLoad = false;
676
677 try
678 {
679 if( pi == nullptr )
680 {
681 // There was no plugin found, e.g. due to invalid file extension, file header,...
682 THROW_IO_ERROR( _( "File format is not supported" ) );
683 }
684
685 std::map<std::string, UTF8> props;
686
688 props.insert( m_importProperties->begin(), m_importProperties->end() );
689
690 // PCB_IO_EAGLE can use this info to center the BOARD, but it does not yet.
691 props["page_width"] = std::to_string( GetPageSizeIU().x );
692 props["page_height"] = std::to_string( GetPageSizeIU().y );
693
694 pi->SetQueryUserCallback(
695 [&]( wxString aTitle, int aIcon, wxString aMessage, wxString aAction ) -> bool
696 {
697 KIDIALOG dlg( nullptr, aMessage, aTitle, wxOK | wxCANCEL | aIcon );
698
699 if( !aAction.IsEmpty() )
700 dlg.SetOKLabel( aAction );
701
702 dlg.DoNotShowCheckbox( aMessage, 0 );
703
704 return dlg.ShowModal() == wxID_OK;
705 } );
706
707#if USE_INSTRUMENTATION
708 // measure the time to load a BOARD.
709 int64_t startTime = GetRunningMicroSecs();
710#endif
711 if( config()->m_System.show_import_issues )
712 pi->SetReporter( errorReporter.m_Reporter );
713 else
714 pi->SetReporter( &NULL_REPORTER::GetInstance() );
715
716 pi->SetProgressReporter( &progressReporter );
717 loadedBoard = pi->LoadBoard( fullFileName, nullptr, &props, &Prj() );
718
719#if USE_INSTRUMENTATION
720 int64_t stopTime = GetRunningMicroSecs();
721 printf( "PCB_IO::Load(): %u usecs\n", stopTime - startTime );
722#endif
723 }
724 catch( const FUTURE_FORMAT_ERROR& ffe )
725 {
726 msg.Printf( _( "Error loading PCB '%s'." ), fullFileName );
727 progressReporter.Hide();
728 DisplayErrorMessage( this, msg, ffe.Problem() );
729
730 failedLoad = true;
731 }
732 catch( const IO_ERROR& ioe )
733 {
734 if( ioe.Problem() != wxT( "CANCEL" ) )
735 {
736 msg.Printf( _( "Error loading PCB '%s'." ), fullFileName );
737 progressReporter.Hide();
738 DisplayErrorMessage( this, msg, ioe.What() );
739 }
740
741 failedLoad = true;
742 }
743 catch( const std::bad_alloc& )
744 {
745 msg.Printf( _( "Memory exhausted loading PCB '%s'" ), fullFileName );
746 progressReporter.Hide();
747 DisplayErrorMessage( this, msg, wxEmptyString );
748
749 failedLoad = true;
750 }
751
752 if( failedLoad || !loadedBoard )
753 {
754 // We didn't create a new blank board above, so do that now
755 Clear_Pcb( false );
756
757 return false;
758 }
759
760 // This fixes a focus issue after the progress reporter is done on GTK. It shouldn't
761 // cause any issues on macOS and Windows. If it does, it will have to be conditionally
762 // compiled.
763 Raise();
764
765 if( errorReporter.m_Reporter->HasMessage() )
766 {
767 errorReporter.m_Reporter->Flush(); // Build HTML messages
768 errorReporter.ShowModal();
769 }
770
771 // Skip (possibly expensive) connectivity build here; we build it below after load
772 SetBoard( loadedBoard, false, &progressReporter );
773
774 if( GFootprintList.GetCount() == 0 )
775 GFootprintList.ReadCacheFromFile( Prj().GetProjectPath() + wxT( "fp-info-cache" ) );
776
777 if( loadedBoard->m_LegacyDesignSettingsLoaded )
778 {
779 Prj().SetReadOnly( false );
780
781 // Before we had a copper edge clearance setting, the edge line widths could be used
782 // as a kludge to control them. So if there's no setting then infer it from the
783 // edge widths.
784 if( !loadedBoard->m_LegacyCopperEdgeClearanceLoaded )
785 {
786 // Do not show the inferred edge clearance warning dialog when loading third
787 // party boards. For some reason the dialog completely hangs all of KiCad and
788 // the imported board cannot be saved.
789 int edgeClearance = inferLegacyEdgeClearance( loadedBoard, !converted );
790 loadedBoard->GetDesignSettings().m_CopperEdgeClearance = edgeClearance;
791 }
792
793 // On save; design settings will be removed from the board
794 loadedBoard->SetModified();
795 }
796
797 // Move legacy view settings to local project settings
798 if( !loadedBoard->m_LegacyVisibleLayers.test( Rescue ) )
799 {
801 loadedBoard->SetModified();
802 }
803
805 {
807 loadedBoard->SetModified();
808 }
809
810 if( !loadedBoard->SynchronizeComponentClasses( std::unordered_set<wxString>() ) )
811 {
814 m_infoBar->ShowMessage( _( "Could not load component class assignment rules" ),
815 wxICON_WARNING, WX_INFOBAR::MESSAGE_TYPE::GENERIC );
816 }
817
818 // we should not ask PCB_IOs to do these items:
819 loadedBoard->BuildListOfNets();
820 ResolveDRCExclusions( true );
822
823 if( loadedBoard->IsModified() )
824 OnModify();
825 else
826 GetScreen()->SetContentModified( false );
827
828 if( ( pluginType == PCB_IO_MGR::LEGACY )
829 || ( pluginType == PCB_IO_MGR::KICAD_SEXP
831 && loadedBoard->GetGenerator().Lower() != wxT( "gerbview" ) ) )
832 {
835 m_infoBar->ShowMessage( _( "This file was created by an older version of KiCad. "
836 "It will be converted to the new format when saved." ),
838 }
839
840 // Import footprints into a project-specific library
841 //==================================================
842 // TODO: This should be refactored out of here into somewhere specific to the Project Import
843 // E.g. KICAD_MANAGER_FRAME::ImportNonKiCadProject
844 if( aCtl & KICTL_IMPORT_LIB )
845 {
846 wxFileName loadedBoardFn( fullFileName );
847 wxString libNickName = loadedBoardFn.GetName();
848
849 // Extract a footprint library from the design and add it to the fp-lib-table
850 // The footprints are saved in a new .pretty library.
851 // If this library already exists, all previous footprints will be deleted
852 std::vector<FOOTPRINT*> loadedFootprints = pi->GetImportedCachedLibraryFootprints();
853 wxString newLibPath = CreateNewProjectLibrary( libNickName );
854
855 // Only create the new library if CreateNewLibrary succeeded (note that this fails if
856 // the library already exists and the user aborts after seeing the warning message
857 // which prompts the user to continue with overwrite or abort)
858 if( newLibPath.Length() > 0 )
859 {
861
862 for( FOOTPRINT* footprint : loadedFootprints )
863 {
864 try
865 {
866 if( !footprint->GetFPID().GetLibItemName().empty() ) // Handle old boards.
867 {
868 footprint->SetReference( "REF**" );
869 piSexpr->FootprintSave( newLibPath, footprint );
870 delete footprint;
871 }
872 }
873 catch( const IO_ERROR& ioe )
874 {
875 wxLogError( _( "Error saving footprint %s to project specific library." )
876 + wxS( "\n%s" ),
877 footprint->GetFPID().GetUniStringLibItemName(),
878 ioe.What() );
879 }
880 }
881
883 const wxString& project_env = PROJECT_VAR_NAME;
884 wxString rel_path, env_path;
885
886 wxASSERT_MSG( wxGetEnv( project_env, &env_path ),
887 wxT( "There is no project variable?" ) );
888
889 wxString result( newLibPath );
890
891 if( result.Replace( env_path, wxT( "$(" ) + project_env + wxT( ")" ) ) )
892 rel_path = result;
893
894 FP_LIB_TABLE_ROW* row = new FP_LIB_TABLE_ROW( libNickName, rel_path,
895 wxT( "KiCad" ), wxEmptyString );
896 prjlibtable->InsertRow( row );
897
898 wxString tblName = Prj().FootprintLibTblName();
899
900 try
901 {
902 PROJECT_PCB::PcbFootprintLibs( &Prj() )->Save( tblName );
903 }
904 catch( const IO_ERROR& ioe )
905 {
906 wxLogError( _( "Error saving project specific footprint library table." )
907 + wxS( "\n%s" ),
908 ioe.What() );
909 }
910
911 // Update footprint LIB_IDs to point to the just imported library
912 for( FOOTPRINT* footprint : GetBoard()->Footprints() )
913 {
914 LIB_ID libId = footprint->GetFPID();
915
916 if( libId.GetLibItemName().empty() )
917 continue;
918
919 libId.SetLibNickname( libNickName );
920 footprint->SetFPID( libId );
921 }
922 }
923 }
924 }
925
926 {
927 wxFileName fn;
928
929 fn.SetPath( Prj().GetProjectPath() );
930 fn.SetName( Prj().GetProjectName() );
932
933 wxString fname = fn.GetFullPath();
934
935 fname.Replace( WIN_STRING_DIR_SEP, UNIX_STRING_DIR_SEP );
936
937 GetBoard()->SetFileName( fname );
938 }
939
940 // Lock the file newly opened:
941 m_file_checker.reset( lock.release() );
942
943 if( !converted )
944 UpdateFileHistory( GetBoard()->GetFileName() );
945
946 std::vector<ZONE*> toFill;
947
948 // Rebuild list of nets (full ratsnest rebuild)
949 GetBoard()->BuildConnectivity( &progressReporter );
950
951 // Load project settings after setting up board; some of them depend on the nets list
954
955 // Initialise caches used by component classes
957
958 // Syncs the UI (appearance panel, etc) with the loaded board and project
960
961 // Refresh the 3D view, if any
962 EDA_3D_VIEWER_FRAME* draw3DFrame = Get3DViewerFrame();
963
964 if( draw3DFrame )
965 draw3DFrame->NewDisplay();
966#if 0 && defined(DEBUG)
967 // Output the board object tree to stdout, but please run from command prompt:
968 GetBoard()->Show( 0, std::cout );
969#endif
970
971 // from EDA_APPL which was first loaded BOARD only:
972 {
973 /* For an obscure reason the focus is lost after loading a board file
974 * when starting up the process.
975 * (seems due to the recreation of the layer manager after loading the file)
976 * Give focus to main window and Drawpanel
977 * must be done for these 2 windows (for an obscure reason ...)
978 * Linux specific
979 * This is more a workaround than a fix.
980 */
981 SetFocus();
982 GetCanvas()->SetFocus();
983 }
984
985 return true;
986}
987
988
989bool PCB_EDIT_FRAME::SavePcbFile( const wxString& aFileName, bool addToHistory,
990 bool aChangeProject )
991{
992 // please, keep it simple. prompting goes elsewhere.
993 wxFileName pcbFileName = aFileName;
994
995 if( pcbFileName.GetExt() == FILEEXT::LegacyPcbFileExtension )
996 pcbFileName.SetExt( FILEEXT::KiCadPcbFileExtension );
997
998 // Write through symlinks, don't replace them
1000
1001 if( !IsWritable( pcbFileName ) )
1002 {
1003 wxString msg = wxString::Format( _( "Insufficient permissions to write file '%s'." ),
1004 pcbFileName.GetFullPath() );
1005
1006 DisplayError( this, msg );
1007 return false;
1008 }
1009
1010 // TODO: these will break if we ever go multi-board
1011 wxFileName projectFile( pcbFileName );
1012 wxFileName rulesFile( pcbFileName );
1013 wxString msg;
1014
1015 projectFile.SetExt( FILEEXT::ProjectFileExtension );
1016 rulesFile.SetExt( FILEEXT::DesignRulesFileExtension );
1017
1018 if( projectFile.FileExists() )
1019 {
1021 }
1022 else if( aChangeProject )
1023 {
1024 Prj().SetReadOnly( false );
1025 GetSettingsManager()->SaveProjectAs( projectFile.GetFullPath() );
1026 }
1027
1028 wxFileName currentRules( GetDesignRulesPath() );
1029
1030 if( currentRules.FileExists() && !rulesFile.FileExists() && aChangeProject )
1031 KiCopyFile( currentRules.GetFullPath(), rulesFile.GetFullPath(), msg );
1032
1033 if( !msg.IsEmpty() )
1034 {
1035 DisplayError( this, wxString::Format( _( "Error saving custom rules file '%s'." ),
1036 rulesFile.GetFullPath() ) );
1037 }
1038
1039 if( projectFile.FileExists() )
1040 {
1041 // Save various DRC parameters, such as violation severities (which may have been
1042 // edited via the DRC dialog as well as the Board Setup dialog), DRC exclusions, etc.
1044
1047 }
1048
1049 wxString tempFile = wxFileName::CreateTempFileName( wxS( "pcbnew" ) );
1050 wxString upperTxt;
1051 wxString lowerTxt;
1052
1053 try
1054 {
1056
1057 pi->SaveBoard( tempFile, GetBoard(), nullptr );
1058 }
1059 catch( const IO_ERROR& ioe )
1060 {
1061 DisplayError( this, wxString::Format( _( "Error saving board file '%s'.\n%s" ),
1062 pcbFileName.GetFullPath(),
1063 ioe.What() ) );
1064
1065 lowerTxt.Printf( _( "Failed to create temporary file '%s'." ), tempFile );
1066
1067 SetMsgPanel( upperTxt, lowerTxt );
1068
1069 // In case we started a file but didn't fully write it, clean up
1070 wxRemoveFile( tempFile );
1071
1072 return false;
1073 }
1074
1075 // Preserve the permissions of the current file
1076 KIPLATFORM::IO::DuplicatePermissions( pcbFileName.GetFullPath(), tempFile );
1077
1078 // If save succeeded, replace the original with what we just wrote
1079 if( !wxRenameFile( tempFile, pcbFileName.GetFullPath() ) )
1080 {
1081 DisplayError( this, wxString::Format( _( "Error saving board file '%s'.\n"
1082 "Failed to rename temporary file '%s." ),
1083 pcbFileName.GetFullPath(),
1084 tempFile ) );
1085
1086 lowerTxt.Printf( _( "Failed to rename temporary file '%s'." ),
1087 tempFile );
1088
1089 SetMsgPanel( upperTxt, lowerTxt );
1090
1091 return false;
1092 }
1093
1094 if( !Kiface().IsSingle() )
1095 {
1096 WX_STRING_REPORTER backupReporter;
1097
1098 if( !GetSettingsManager()->TriggerBackupIfNeeded( backupReporter ) )
1099 upperTxt = backupReporter.GetMessages();
1100 }
1101
1102 GetBoard()->SetFileName( pcbFileName.GetFullPath() );
1103
1104 // Update the lock in case it was a Save As
1105 LockFile( pcbFileName.GetFullPath() );
1106
1107 // Put the saved file in File History if requested
1108 if( addToHistory )
1109 UpdateFileHistory( GetBoard()->GetFileName() );
1110
1111 // Delete auto save file on successful save.
1112 wxFileName autoSaveFileName = pcbFileName;
1113
1114 autoSaveFileName.SetName( FILEEXT::AutoSaveFilePrefix + pcbFileName.GetName() );
1115
1116 if( autoSaveFileName.FileExists() )
1117 wxRemoveFile( autoSaveFileName.GetFullPath() );
1118
1119 lowerTxt.Printf( _( "File '%s' saved." ), pcbFileName.GetFullPath() );
1120
1121 SetStatusText( lowerTxt, 0 );
1122
1123 // Get rid of the old version conversion warning, or any other dismissable warning :)
1125 m_infoBar->Dismiss();
1126
1127 if( m_infoBar->IsShownOnScreen() && m_infoBar->HasCloseButton() )
1128 m_infoBar->Dismiss();
1129
1130 GetScreen()->SetContentModified( false );
1131 UpdateTitle();
1132 return true;
1133}
1134
1135
1136bool PCB_EDIT_FRAME::SavePcbCopy( const wxString& aFileName, bool aCreateProject, bool aHeadless )
1137{
1138 wxFileName pcbFileName( aFileName );
1139
1140 if( !IsWritable( pcbFileName ) )
1141 {
1142 if( !aHeadless )
1143 {
1144 DisplayError( this, wxString::Format( _( "Insufficient permissions to write file '%s'." ),
1145 pcbFileName.GetFullPath() ) );
1146 }
1147 return false;
1148 }
1149
1150 // Save various DRC parameters, such as violation severities (which may have been
1151 // edited via the DRC dialog as well as the Board Setup dialog), DRC exclusions, etc.
1153
1155
1156 try
1157 {
1159
1160 wxASSERT( pcbFileName.IsAbsolute() );
1161
1162 pi->SaveBoard( pcbFileName.GetFullPath(), GetBoard(), nullptr );
1163 }
1164 catch( const IO_ERROR& ioe )
1165 {
1166 if( !aHeadless )
1167 {
1168 DisplayError( this, wxString::Format( _( "Error saving board file '%s'.\n%s" ),
1169 pcbFileName.GetFullPath(),
1170 ioe.What() ) );
1171 }
1172
1173 return false;
1174 }
1175
1176 wxFileName projectFile( pcbFileName );
1177 wxFileName rulesFile( pcbFileName );
1178 wxString msg;
1179
1180 projectFile.SetExt( FILEEXT::ProjectFileExtension );
1181 rulesFile.SetExt( FILEEXT::DesignRulesFileExtension );
1182
1183 if( aCreateProject && !projectFile.FileExists() )
1184 GetSettingsManager()->SaveProjectCopy( projectFile.GetFullPath() );
1185
1186 wxFileName currentRules( GetDesignRulesPath() );
1187
1188 if( aCreateProject && currentRules.FileExists() && !rulesFile.FileExists() )
1189 KiCopyFile( currentRules.GetFullPath(), rulesFile.GetFullPath(), msg );
1190
1191 if( !msg.IsEmpty() && !aHeadless )
1192 {
1193 DisplayError( this, wxString::Format( _( "Error saving custom rules file '%s'." ),
1194 rulesFile.GetFullPath() ) );
1195 }
1196
1197 return true;
1198}
1199
1200
1202{
1203 wxFileName tmpFileName;
1204
1205 // Don't run autosave if content has not been modified
1206 if( !IsContentModified() )
1207 return true;
1208
1209 wxString title = GetTitle(); // Save frame title, that can be modified by the save process
1210
1211 if( GetBoard()->GetFileName().IsEmpty() )
1212 {
1213 tmpFileName = wxFileName( PATHS::GetDefaultUserProjectsPath(), NAMELESS_PROJECT,
1215 GetBoard()->SetFileName( tmpFileName.GetFullPath() );
1216 }
1217 else
1218 {
1219 tmpFileName = Prj().AbsolutePath( GetBoard()->GetFileName() );
1220 }
1221
1222 wxFileName autoSaveFileName = tmpFileName;
1223
1224 // Auto save file name is the board file name prepended with autosaveFilePrefix string.
1225 autoSaveFileName.SetName( FILEEXT::AutoSaveFilePrefix + autoSaveFileName.GetName() );
1226
1227 if( !autoSaveFileName.IsOk() )
1228 return false;
1229
1230 // If the board file path is not writable, try writing to a platform specific temp file
1231 // path. If that path isn't writable, give up.
1232 if( !autoSaveFileName.IsDirWritable() )
1233 {
1234 autoSaveFileName.SetPath( wxFileName::GetTempDir() );
1235
1236 if( !autoSaveFileName.IsOk() || !autoSaveFileName.IsDirWritable() )
1237 return false;
1238 }
1239
1240 wxLogTrace( traceAutoSave,
1241 wxT( "Creating auto save file <" ) + autoSaveFileName.GetFullPath() + wxT( ">" ) );
1242
1243 if( SavePcbFile( autoSaveFileName.GetFullPath(), false, false ) )
1244 {
1246 GetBoard()->SetFileName( tmpFileName.GetFullPath() );
1247 UpdateTitle();
1248 m_autoSaveRequired = false;
1249 m_autoSavePending = false;
1250
1251 if( !Kiface().IsSingle() &&
1252 GetSettingsManager()->GetCommonSettings()->m_Backup.backup_on_autosave )
1253 {
1255 }
1256
1257 SetTitle( title ); // Restore initial frame title
1258
1259 return true;
1260 }
1261
1262 GetBoard()->SetFileName( tmpFileName.GetFullPath() );
1263
1264 SetTitle( title ); // Restore initial frame title
1265
1266 return false;
1267}
1268
1269
1270bool PCB_EDIT_FRAME::importFile( const wxString& aFileName, int aFileType,
1271 const std::map<std::string, UTF8>* aProperties )
1272{
1273 m_importProperties = aProperties;
1274
1275 switch( (PCB_IO_MGR::PCB_FILE_T) aFileType )
1276 {
1278 case PCB_IO_MGR::EAGLE:
1281 return OpenProjectFiles( std::vector<wxString>( 1, aFileName ),
1283 break;
1284
1289 return OpenProjectFiles( std::vector<wxString>( 1, aFileName ),
1291
1292 default: break;
1293 }
1294
1295 m_importProperties = nullptr;
1296
1297 return false;
1298}
1299
1300
1301void PCB_EDIT_FRAME::GenIPC2581File( wxCommandEvent& event )
1302{
1303 DIALOG_EXPORT_2581 dlg( this );
1304
1305 if( dlg.ShowModal() != wxID_OK )
1306 return;
1307
1308 wxFileName pcbFileName = dlg.GetOutputPath();
1309
1310 // Write through symlinks, don't replace them
1312
1313 if( pcbFileName.GetName().empty() )
1314 {
1315 DisplayError( this, _( "The board must be saved before generating IPC-2581 file." ) );
1316 return;
1317 }
1318
1319 if( !IsWritable( pcbFileName ) )
1320 {
1321 wxString msg = wxString::Format( _( "Insufficient permissions to write file '%s'." ),
1322 pcbFileName.GetFullPath() );
1323
1324 DisplayError( this, msg );
1325 return;
1326 }
1327
1328 wxString tempFile = wxFileName::CreateTempFileName( wxS( "pcbnew_ipc" ) );
1329 wxString upperTxt;
1330 wxString lowerTxt;
1331 WX_PROGRESS_REPORTER reporter( this, _( "Generating IPC-2581 file" ), 5 );
1332 std::map<std::string, UTF8> props;
1333
1334 props["units"] = dlg.GetUnitsString();
1335 props["sigfig"] = dlg.GetPrecision();
1336 props["version"] = dlg.GetVersion();
1337 props["OEMRef"] = dlg.GetOEM();
1338 props["mpn"] = dlg.GetMPN();
1339 props["mfg"] = dlg.GetMfg();
1340 props["dist"] = dlg.GetDist();
1341 props["distpn"] = dlg.GetDistPN();
1342
1343 auto saveFile =
1344 [&]() -> bool
1345 {
1346 try
1347 {
1349 pi->SetProgressReporter( &reporter );
1350 pi->SaveBoard( tempFile, GetBoard(), &props );
1351 return true;
1352 }
1353 catch( const IO_ERROR& ioe )
1354 {
1355 DisplayError( this,
1356 wxString::Format( _( "Error generating IPC-2581 file '%s'.\n%s" ),
1357 pcbFileName.GetFullPath(),
1358 ioe.What() ) );
1359
1360 lowerTxt.Printf( _( "Failed to create temporary file '%s'." ), tempFile );
1361
1362 SetMsgPanel( upperTxt, lowerTxt );
1363
1364 // In case we started a file but didn't fully write it, clean up
1365 wxRemoveFile( tempFile );
1366
1367 return false;
1368 }
1369 };
1370
1372 auto ret = tp.submit( saveFile );
1373
1374
1375 std::future_status status = ret.wait_for( std::chrono::milliseconds( 250 ) );
1376
1377 while( status != std::future_status::ready )
1378 {
1379 reporter.KeepRefreshing();
1380 status = ret.wait_for( std::chrono::milliseconds( 250 ) );
1381 }
1382
1383 try
1384 {
1385 if( !ret.get() )
1386 return;
1387 }
1388 catch( const std::exception& e )
1389 {
1390 wxLogError( "Exception in IPC-2581 generation: %s", e.what() );
1391 GetScreen()->SetContentModified( false );
1392 return;
1393 }
1394
1395 // Preserve the permissions of the current file
1396 KIPLATFORM::IO::DuplicatePermissions( pcbFileName.GetFullPath(), tempFile );
1397
1398 if( dlg.GetCompress() )
1399 {
1400 wxFileName tempfn = pcbFileName;
1401 tempfn.SetExt( FILEEXT::Ipc2581FileExtension );
1402 wxFileName zipfn = tempFile;
1403 zipfn.SetExt( "zip" );
1404
1405 {
1406 wxFFileOutputStream fnout( zipfn.GetFullPath() );
1407 wxZipOutputStream zip( fnout );
1408 wxFFileInputStream fnin( tempFile );
1409
1410 zip.PutNextEntry( tempfn.GetFullName() );
1411 fnin.Read( zip );
1412 }
1413
1414 wxRemoveFile( tempFile );
1415 tempFile = zipfn.GetFullPath();
1416 }
1417
1418 // If save succeeded, replace the original with what we just wrote
1419 if( !wxRenameFile( tempFile, pcbFileName.GetFullPath() ) )
1420 {
1421 DisplayError( this, wxString::Format( _( "Error generating IPC-2581 file '%s'.\n"
1422 "Failed to rename temporary file '%s." ),
1423 pcbFileName.GetFullPath(),
1424 tempFile ) );
1425
1426 lowerTxt.Printf( _( "Failed to rename temporary file '%s'." ),
1427 tempFile );
1428
1429 SetMsgPanel( upperTxt, lowerTxt );
1430 }
1431
1432 GetScreen()->SetContentModified( false );
1433}
1434
1435
1436void PCB_EDIT_FRAME::GenODBPPFiles( wxCommandEvent& event )
1437{
1438 DIALOG_EXPORT_ODBPP dlg( this );
1439
1440 if( dlg.ShowModal() != wxID_OK )
1441 return;
1442
1444
1446 job.m_filename = GetBoard()->GetFileName();
1448
1449 job.m_precision = dlg.GetPrecision();
1452
1453 WX_PROGRESS_REPORTER progressReporter( this, _( "Generating ODB++ output files" ), 3, false );
1454 WX_STRING_REPORTER reporter;
1455
1456 DIALOG_EXPORT_ODBPP::GenerateODBPPFiles( job, GetBoard(), this, &progressReporter, &reporter );
1457
1458 if( reporter.HasMessage() )
1459 DisplayError( this, reporter.GetMessages() );
1460}
const char * name
Definition: DXF_plotter.cpp:59
KIFACE_BASE & Kiface()
Global KIFACE_BASE "get" accessor.
void SetContentModified(bool aModified=true)
Definition: base_screen.h:59
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:297
bool m_LegacyDesignSettingsLoaded
True if the legacy board design settings were loaded from a file.
Definition: board.h:380
GAL_SET m_LegacyVisibleItems
Definition: board.h:377
void BuildListOfNets()
Definition: board.h:860
void SetFileName(const wxString &aFileName)
Definition: board.h:332
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:185
void SynchronizeNetsAndNetClasses(bool aResetTrackAndViaSizes)
Copy NETCLASS info to each NET, based on NET membership in a NETCLASS.
Definition: board.cpp:2144
LSET m_LegacyVisibleLayers
Visibility settings stored in board prior to 6.0, only used for loading legacy files.
Definition: board.h:376
void SetProject(PROJECT *aProject, bool aReferenceOnly=false)
Link a board to a given project.
Definition: board.cpp:195
const wxString & GetFileName() const
Definition: board.h:334
int GetFileFormatVersionAtLoad() const
Definition: board.h:403
const wxString & GetGenerator() const
Adds an item to the container.
Definition: board.h:406
void ClearProject()
Definition: board.cpp:233
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:946
void SynchronizeProperties()
Copy the current project's text variables into the boards property cache.
Definition: board.cpp:2135
COMPONENT_CLASS_MANAGER & GetComponentClassManager()
Gets the component class manager.
Definition: board.h:1316
bool SynchronizeComponentClasses(const std::unordered_set< wxString > &aNewSheetPaths) const
Copy component class / component class generator information from the project settings.
Definition: board.cpp:2174
bool m_LegacyCopperEdgeClearanceLoaded
Definition: board.h:381
int GetCount() const
Return the number of objects in the list.
Definition: collector.h:82
void RebuildRequiredCaches(FOOTPRINT *aFootprint=nullptr) const
Rebuilds any caches that may be required by custom assignment rules.
wxString GetOEM() const
wxString GetPrecision() const
bool GetCompress() const
wxString GetMPN() const
wxString GetDistPN() const
wxString GetDist() const
wxString GetMfg() const
wxString GetUnitsString() const
wxString GetOutputPath() const
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
Class DIALOG_HTML_REPORTER.
WX_HTML_REPORT_BOX * m_Reporter
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.
virtual void CheckForAutoSaveFile(const wxFileName &aFileName)
Check if an auto save file exists for aFileName and takes the appropriate action depending on the use...
WX_INFOBAR * m_infoBar
void UpdateFileHistory(const wxString &FullFileName, FILE_HISTORY *aFileHistory=nullptr)
Update the list of recently opened files.
void ClearFileHistory(FILE_HISTORY *aFileHistory=nullptr)
Remove all files from the file history.
wxString GetMruPath() const
virtual void DeleteAutoSaveFile(const wxFileName &aFileName)
bool IsWritable(const wxFileName &aFileName, bool aVerbose=true)
Check if aFileName can be written.
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()
void ReleaseFile()
Release the current file marked in use.
std::unique_ptr< LOCKFILE > m_file_checker
void SetMsgPanel(const std::vector< MSG_PANEL_ITEM > &aList)
Clear the message panel and populates it with the contents of aList.
bool LockFile(const wxString &aFileName)
Mark a schematic file as being in use.
void SetFocus() override
void SetModified()
Definition: eda_item.cpp:71
bool IsModified() const
Definition: eda_item.h:112
bool GetCreateNewProject() const
Gets if this hook has attached controls to a dialog box.
void ReadCacheFromFile(const wxString &aFilePath) override
unsigned GetCount() const
Hold a record identifying a library accessed by the appropriate footprint library #PLUGIN object in t...
Definition: fp_lib_table.h:42
static const std::vector< KICAD_T > AllBoardItems
A scan list for all editable board items.
Definition: collectors.h:222
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
Definition: ki_exception.h:77
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:30
virtual const wxString Problem() const
what was the problem?
Definition: exceptions.cpp:46
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:153
Helper class to create more flexible dialogs, including 'do not show again' checkbox handling.
Definition: kidialog.h:43
void DoNotShowCheckbox(wxString file, int line)
Shows the 'do not show again' checkbox.
Definition: kidialog.cpp:51
int ShowModal() override
Definition: kidialog.cpp:95
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
Plugin class for import plugins that support remappable layers.
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 InsertRow(LIB_TABLE_ROW *aRow, bool doReplace=false)
Adds aRow if it does not already exist or if doReplace is true.
void Save(const wxString &aFileName) const
Write this library table to aFileName in s-expression form.
static REPORTER & GetInstance()
Definition: reporter.cpp:118
static wxString GetDefaultUserProjectsPath()
Gets the default path we point users to create projects.
Definition: paths.cpp:143
static TOOL_ACTION repairBoard
Definition: pcb_actions.h:569
wxString GetDesignRulesPath()
Return the absolute path to the design rules file for the currently-loaded board.
wxString CreateNewProjectLibrary(const wxString &aLibName=wxEmptyString, const wxString &aProposedName=wxEmptyString)
const VECTOR2I GetPageSizeIU() const override
Works off of GetPageSettings() to return the size of the paper page in the internal units of this par...
PCB_DRAW_PANEL_GAL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
PCB_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
BOARD * GetBoard() const
EDA_3D_VIEWER_FRAME * Get3DViewerFrame()
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 GenIPC2581File(wxCommandEvent &event)
Create and IPC2581 output file.
bool doAutoSave() override
Perform auto save when the board has been modified and not saved within the auto save interval.
void OnModify() override
Must be called after a board change to set the modified flag.
void OnClearFileHistory(wxCommandEvent &aEvent)
bool OpenProjectFiles(const std::vector< wxString > &aFileSet, int aCtl=0) override
Load a KiCad board (.kicad_pcb) from aFileName.
void onBoardLoaded()
Update the state of the GUI after a new board is loaded or created.
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 Files_io_from_id(int aId)
Read and write board files according to aId.
void GenODBPPFiles(wxCommandEvent &event)
Create and Generate ODB++ output files.
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 Files_io(wxCommandEvent &event)
Call Files_io_from_id with the wxCommandEvent id.
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:94
static PCB_IO * PluginFind(PCB_FILE_T aFileType)
Return a #PLUGIN which the caller can use to import, export, save, or load design documents.
Definition: pcb_io_mgr.cpp:69
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
@ FILE_TYPE_NONE
Definition: pcb_io_mgr.h:77
@ KICAD_SEXP
S-expression Pcbnew file format.
Definition: pcb_io_mgr.h:58
@ ALTIUM_DESIGNER
Definition: pcb_io_mgr.h:62
@ LEGACY
Legacy Pcbnew file formats prior to s-expression.
Definition: pcb_io_mgr.h:59
@ SOLIDWORKS_PCB
Definition: pcb_io_mgr.h:70
@ ALTIUM_CIRCUIT_MAKER
Definition: pcb_io_mgr.h:60
@ ALTIUM_CIRCUIT_STUDIO
Definition: pcb_io_mgr.h:61
@ CADSTAR_PCB_ARCHIVE
Definition: pcb_io_mgr.h:63
static PCB_FILE_T FindPluginTypeFromBoardPath(const wxString &aFileName, int aCtl=0)
Return a plugin type given a path for a board file.
Definition: pcb_io_mgr.cpp:112
Collect all BOARD_ITEM objects on a given layer.
Definition: collectors.h:539
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.
Definition: collectors.cpp:536
void SetLayerId(PCB_LAYER_ID aLayerId)
Definition: collectors.h:545
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 (.
static FP_LIB_TABLE * PcbFootprintLibs(PROJECT *aProject)
Return the table of footprint libraries without Kiway.
Definition: project_pcb.cpp:37
virtual void SetReadOnly(bool aReadOnly=true)
Definition: project.h:167
virtual const wxString GetProjectFullName() const
Return the full path and name of the project.
Definition: project.cpp:140
virtual PROJECT_LOCAL_SETTINGS & GetLocalSettings() const
Definition: project.h:209
virtual const wxString FootprintLibTblName() const
Returns the path and filename of this project's footprint library table.
Definition: project.cpp:176
virtual const wxString AbsolutePath(const wxString &aFileName) const
Fix up aFileName if it is relative to the project's directory to be an absolute path and filename.
Definition: project.cpp:370
virtual bool IsNullProject() const
Check if this project is a null project (i.e.
Definition: project.cpp:164
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.
bool TriggerBackupIfNeeded(REPORTER &aReporter) const
Call BackupProject() if a new backup is needed according to the current backup policy.
PROJECT & Prj() const
A helper while we are not MDI-capable – return the one and only project.
TOOL_MANAGER * m_toolManager
Definition: tools_holder.h:171
bool RunAction(const std::string &aActionName, T aParam)
Run the specified action immediately, pausing the current action to run the new one.
Definition: tool_manager.h:150
An 8 bit string that is assuredly encoded in UTF8, and supplies special conversion support to and fro...
Definition: utf8.h:72
bool empty() const
Definition: utf8.h:104
static void ResolvePossibleSymlinks(wxFileName &aFilename)
Definition: wx_filename.cpp:91
void Flush()
Build the HTML messages page.
bool HasMessage() const override
Returns true if the reporter client is non-empty.
void RemoveAllButtons()
Remove all the buttons that have been added by the user.
Definition: wx_infobar.cpp:353
bool HasCloseButton() const
Definition: wx_infobar.cpp:377
@ OUTDATED_SAVE
OUTDATED_SAVE Messages that should be cleared on save.
@ GENERIC
GENERIC Are messages that do not have special handling.
void Dismiss() override
Dismisses the infobar and updates the containing layout and AUI manager (if one is provided).
Definition: wx_infobar.cpp:190
void AddCloseButton(const wxString &aTooltip=_("Hide this message."))
Add the default close button to the infobar on the right side.
Definition: wx_infobar.cpp:343
MESSAGE_TYPE GetMessageType() const
Definition: wx_infobar.h:101
void ShowMessage(const wxString &aMessage, int aFlags=wxICON_INFORMATION) override
Show the info bar with the provided message and icon.
Definition: wx_infobar.cpp:154
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:172
bool HasMessage() const override
Returns true if the reporter client is non-empty.
Definition: reporter.cpp:100
const wxString & GetMessages() const
Definition: reporter.cpp:87
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:425
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:44
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition: confirm.cpp:249
void DisplayInfoMessage(wxWindow *aParent, const wxString &aMessage, const wxString &aExtraInfo)
Display an informational message box with aMessage.
Definition: confirm.cpp:221
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:130
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition: confirm.cpp:194
void DisplayError(wxWindow *aParent, const wxString &aText)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:170
This file is part of the common library.
#define _(s)
Declaration of the eda_3d_viewer class.
FOOTPRINT_LIST_IMPL GFootprintList
The global footprint info table.
Definition: cvpcb.cpp:156
void KiCopyFile(const wxString &aSrcPath, const wxString &aDestPath, wxString &aErrors)
Definition: gestfich.cpp:290
#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 Ipc2581FileExtension
static const std::string AutoSaveFilePrefix
static const std::string DesignRulesFileExtension
static const std::string KiCadPcbFileExtension
static wxString PcbFileWildcard()
const wxChar *const traceAutoSave
Flag to enable auto save feature debug tracing.
@ ID_NEW_BOARD
Definition: id.h:73
@ ID_SAVE_BOARD
Definition: id.h:74
@ ID_LOAD_FILE
Definition: id.h:72
@ ID_SAVE_BOARD_AS
Definition: id.h:75
std::unique_ptr< T > IO_RELEASER
Helper to hold and release an IO_BASE object when exceptions are thrown.
Definition: io_mgr.h:33
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:39
PROJECT & Prj()
Definition: kicad.cpp:597
This file is part of the common library.
#define KICTL_CREATE
caller thinks requested project files may not exist.
Definition: kiway_player.h:76
#define KICTL_REVERT
reverting to a previously-saved (KiCad) file.
Definition: kiway_player.h:78
#define KICTL_IMPORT_LIB
import all footprints into a project library.
Definition: kiway_player.h:77
#define KICTL_KICAD_ONLY
chosen file is from KiCad according to user
Definition: kiway_player.h:75
#define KICTL_NONKICAD_ONLY
chosen file is non-KiCad according to user
Definition: kiway_player.h:74
@ 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:286
@ 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:354
File locking utilities.
This file contains miscellaneous commonly used macros and functions.
#define KI_FALLTHROUGH
The KI_FALLTHROUGH macro is to be used when switch statement cases should purposely fallthrough from ...
Definition: macros.h:83
bool RegisterApplicationRestart(const wxString &aCommandLine)
Registers the application for restart with the OS with the given command line string to pass as args.
Definition: unix/app.cpp:65
bool DuplicatePermissions(const wxString &aSrc, const wxString &aDest)
Duplicates the file security data from one file to another ensuring that they are the same between bo...
Definition: unix/io.cpp:47
#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.
@ ID_IMPORT_NON_KICAD_BOARD
Definition: pcbnew_id.h:19
@ ID_REVERT_BOARD
Definition: pcbnew_id.h:18
@ ID_MENU_RECOVER_BOARD_AUTOSAVE
Definition: pcbnew_id.h:80
@ ID_COPY_BOARD_AS
Definition: pcbnew_id.h:17
SETTINGS_MANAGER * GetSettingsManager()
PGM_BASE & Pgm()
The global program "get" accessor.
Definition: pgm_base.cpp:1071
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:40
#define NAMELESS_PROJECT
default name for nameless projects
Definition: project.h:43
int StrPrintf(std::string *result, const char *format,...)
This is like sprintf() but the output is appended to a std::string instead of to a character array.
Definition: richio.cpp:70
bool show_import_issues
Stored value for "show import issues" when importing non-KiCad designs to this application.
Definition: app_settings.h:175
Variant of PARSE_ERROR indicating that a syntax or related error was likely caused by a file generate...
Definition: ki_exception.h:176
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
thread_pool & GetKiCadThreadPool()
Get a reference to the current thread pool.
Definition: thread_pool.cpp:30
static thread_pool * tp
Definition: thread_pool.cpp:28
BS::thread_pool thread_pool
Definition: thread_pool.h:31
wxLogTrace helper definitions.
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
Definition: typeinfo.h:88
wxString AddFileExtListToFilter(const std::vector< std::string > &aExts)
Build the wildcard extension file dialog wildcard filter to add to the base message dialog.
wxString formatWildcardExt(const wxString &aWildcard)
Format wildcard extension to support case sensitive file dialogs.
Definition of file extensions used in Kicad.