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