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 (C) 2016-2023 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 <core/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( filename, 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 // we should not ask PCB_IOs to do these items:
811 loadedBoard->BuildListOfNets();
812 ResolveDRCExclusions( true );
814
815 if( loadedBoard->IsModified() )
816 OnModify();
817 else
818 GetScreen()->SetContentModified( false );
819
820 if( ( pluginType == PCB_IO_MGR::LEGACY )
821 || ( pluginType == PCB_IO_MGR::KICAD_SEXP
823 && loadedBoard->GetGenerator().Lower() != wxT( "gerbview" ) ) )
824 {
827 m_infoBar->ShowMessage( _( "This file was created by an older version of KiCad. "
828 "It will be converted to the new format when saved." ),
830 }
831
832 // Import footprints into a project-specific library
833 //==================================================
834 // TODO: This should be refactored out of here into somewhere specific to the Project Import
835 // E.g. KICAD_MANAGER_FRAME::ImportNonKiCadProject
836 if( aCtl & KICTL_IMPORT_LIB )
837 {
838 wxFileName loadedBoardFn( fullFileName );
839 wxString libNickName = loadedBoardFn.GetName();
840
841 // Extract a footprint library from the design and add it to the fp-lib-table
842 // The footprints are saved in a new .pretty library.
843 // If this library already exists, all previous footprints will be deleted
844 std::vector<FOOTPRINT*> loadedFootprints = pi->GetImportedCachedLibraryFootprints();
845 wxString newLibPath = CreateNewProjectLibrary( libNickName );
846
847 // Only create the new library if CreateNewLibrary succeeded (note that this fails if
848 // the library already exists and the user aborts after seeing the warning message
849 // which prompts the user to continue with overwrite or abort)
850 if( newLibPath.Length() > 0 )
851 {
853
854 for( FOOTPRINT* footprint : loadedFootprints )
855 {
856 try
857 {
858 if( !footprint->GetFPID().GetLibItemName().empty() ) // Handle old boards.
859 {
860 footprint->SetReference( "REF**" );
861 piSexpr->FootprintSave( newLibPath, footprint );
862 delete footprint;
863 }
864 }
865 catch( const IO_ERROR& ioe )
866 {
867 wxLogError( _( "Error saving footprint %s to project specific library." )
868 + wxS( "\n%s" ),
869 footprint->GetFPID().GetUniStringLibItemName(),
870 ioe.What() );
871 }
872 }
873
875 const wxString& project_env = PROJECT_VAR_NAME;
876 wxString rel_path, env_path;
877
878 wxASSERT_MSG( wxGetEnv( project_env, &env_path ),
879 wxT( "There is no project variable?" ) );
880
881 wxString result( newLibPath );
882
883 if( result.Replace( env_path, wxT( "$(" ) + project_env + wxT( ")" ) ) )
884 rel_path = result;
885
886 FP_LIB_TABLE_ROW* row = new FP_LIB_TABLE_ROW( libNickName, rel_path,
887 wxT( "KiCad" ), wxEmptyString );
888 prjlibtable->InsertRow( row );
889
890 wxString tblName = Prj().FootprintLibTblName();
891
892 try
893 {
894 PROJECT_PCB::PcbFootprintLibs( &Prj() )->Save( tblName );
895 }
896 catch( const IO_ERROR& ioe )
897 {
898 wxLogError( _( "Error saving project specific footprint library table." )
899 + wxS( "\n%s" ),
900 ioe.What() );
901 }
902
903 // Update footprint LIB_IDs to point to the just imported library
904 for( FOOTPRINT* footprint : GetBoard()->Footprints() )
905 {
906 LIB_ID libId = footprint->GetFPID();
907
908 if( libId.GetLibItemName().empty() )
909 continue;
910
911 libId.SetLibNickname( libNickName );
912 footprint->SetFPID( libId );
913 }
914 }
915 }
916 }
917
918 {
919 wxFileName fn;
920
921 fn.SetPath( Prj().GetProjectPath() );
922 fn.SetName( Prj().GetProjectName() );
924
925 wxString fname = fn.GetFullPath();
926
927 fname.Replace( WIN_STRING_DIR_SEP, UNIX_STRING_DIR_SEP );
928
929 GetBoard()->SetFileName( fname );
930 }
931
932 // Lock the file newly opened:
933 m_file_checker.reset( lock.release() );
934
935 if( !converted )
936 UpdateFileHistory( GetBoard()->GetFileName() );
937
938 std::vector<ZONE*> toFill;
939
940 // Rebuild list of nets (full ratsnest rebuild)
941 GetBoard()->BuildConnectivity( &progressReporter );
942
943 // Load project settings after setting up board; some of them depend on the nets list
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 tempFile = wxFileName::CreateTempFileName( wxS( "pcbnew" ) );
1039 wxString upperTxt;
1040 wxString lowerTxt;
1041
1042 try
1043 {
1045
1046 pi->SaveBoard( tempFile, GetBoard(), nullptr );
1047 }
1048 catch( const IO_ERROR& ioe )
1049 {
1050 DisplayError( this, wxString::Format( _( "Error saving board file '%s'.\n%s" ),
1051 pcbFileName.GetFullPath(),
1052 ioe.What() ) );
1053
1054 lowerTxt.Printf( _( "Failed to create temporary file '%s'." ), tempFile );
1055
1056 SetMsgPanel( upperTxt, lowerTxt );
1057
1058 // In case we started a file but didn't fully write it, clean up
1059 wxRemoveFile( tempFile );
1060
1061 return false;
1062 }
1063
1064 // Preserve the permissions of the current file
1065 KIPLATFORM::IO::DuplicatePermissions( pcbFileName.GetFullPath(), tempFile );
1066
1067 // If save succeeded, replace the original with what we just wrote
1068 if( !wxRenameFile( tempFile, pcbFileName.GetFullPath() ) )
1069 {
1070 DisplayError( this, wxString::Format( _( "Error saving board file '%s'.\n"
1071 "Failed to rename temporary file '%s." ),
1072 pcbFileName.GetFullPath(),
1073 tempFile ) );
1074
1075 lowerTxt.Printf( _( "Failed to rename temporary file '%s'." ),
1076 tempFile );
1077
1078 SetMsgPanel( upperTxt, lowerTxt );
1079
1080 return false;
1081 }
1082
1083 if( !Kiface().IsSingle() )
1084 {
1085 WX_STRING_REPORTER backupReporter;
1086
1087 if( !GetSettingsManager()->TriggerBackupIfNeeded( backupReporter ) )
1088 upperTxt = backupReporter.GetMessages();
1089 }
1090
1091 GetBoard()->SetFileName( pcbFileName.GetFullPath() );
1092
1093 // Update the lock in case it was a Save As
1094 LockFile( pcbFileName.GetFullPath() );
1095
1096 // Put the saved file in File History if requested
1097 if( addToHistory )
1098 UpdateFileHistory( GetBoard()->GetFileName() );
1099
1100 // Delete auto save file on successful save.
1101 wxFileName autoSaveFileName = pcbFileName;
1102
1103 autoSaveFileName.SetName( FILEEXT::AutoSaveFilePrefix + pcbFileName.GetName() );
1104
1105 if( autoSaveFileName.FileExists() )
1106 wxRemoveFile( autoSaveFileName.GetFullPath() );
1107
1108 lowerTxt.Printf( _( "File '%s' saved." ), pcbFileName.GetFullPath() );
1109
1110 SetStatusText( lowerTxt, 0 );
1111
1112 // Get rid of the old version conversion warning, or any other dismissable warning :)
1114 m_infoBar->Dismiss();
1115
1116 if( m_infoBar->IsShownOnScreen() && m_infoBar->HasCloseButton() )
1117 m_infoBar->Dismiss();
1118
1119 GetScreen()->SetContentModified( false );
1120 UpdateTitle();
1121 return true;
1122}
1123
1124
1125bool PCB_EDIT_FRAME::SavePcbCopy( const wxString& aFileName, bool aCreateProject )
1126{
1127 wxFileName pcbFileName( EnsureFileExtension( aFileName, FILEEXT::KiCadPcbFileExtension ) );
1128
1129 if( !IsWritable( pcbFileName ) )
1130 {
1131 DisplayError( this, wxString::Format( _( "Insufficient permissions to write file '%s'." ),
1132 pcbFileName.GetFullPath() ) );
1133 return false;
1134 }
1135
1136 // Save various DRC parameters, such as violation severities (which may have been
1137 // edited via the DRC dialog as well as the Board Setup dialog), DRC exclusions, etc.
1139
1141
1142 try
1143 {
1145
1146 wxASSERT( pcbFileName.IsAbsolute() );
1147
1148 pi->SaveBoard( pcbFileName.GetFullPath(), GetBoard(), nullptr );
1149 }
1150 catch( const IO_ERROR& ioe )
1151 {
1152 DisplayError( this, wxString::Format( _( "Error saving board file '%s'.\n%s" ),
1153 pcbFileName.GetFullPath(),
1154 ioe.What() ) );
1155
1156 return false;
1157 }
1158
1159 wxFileName projectFile( pcbFileName );
1160 wxFileName rulesFile( pcbFileName );
1161 wxString msg;
1162
1163 projectFile.SetExt( FILEEXT::ProjectFileExtension );
1164 rulesFile.SetExt( FILEEXT::DesignRulesFileExtension );
1165
1166 if( aCreateProject && !projectFile.FileExists() )
1167 GetSettingsManager()->SaveProjectCopy( projectFile.GetFullPath() );
1168
1169 wxFileName currentRules( GetDesignRulesPath() );
1170
1171 if( aCreateProject && currentRules.FileExists() && !rulesFile.FileExists() )
1172 KiCopyFile( currentRules.GetFullPath(), rulesFile.GetFullPath(), msg );
1173
1174 if( !msg.IsEmpty() )
1175 {
1176 DisplayError( this, wxString::Format( _( "Error saving custom rules file '%s'." ),
1177 rulesFile.GetFullPath() ) );
1178 }
1179
1180 DisplayInfoMessage( this, wxString::Format( _( "Board copied to:\n%s" ),
1181 pcbFileName.GetFullPath() ) );
1182
1183 return true;
1184}
1185
1186
1188{
1189 wxFileName tmpFileName;
1190
1191 // Don't run autosave if content has not been modified
1192 if( !IsContentModified() )
1193 return true;
1194
1195 wxString title = GetTitle(); // Save frame title, that can be modified by the save process
1196
1197 if( GetBoard()->GetFileName().IsEmpty() )
1198 {
1199 tmpFileName = wxFileName( PATHS::GetDefaultUserProjectsPath(), NAMELESS_PROJECT,
1201 GetBoard()->SetFileName( tmpFileName.GetFullPath() );
1202 }
1203 else
1204 {
1205 tmpFileName = Prj().AbsolutePath( GetBoard()->GetFileName() );
1206 }
1207
1208 wxFileName autoSaveFileName = tmpFileName;
1209
1210 // Auto save file name is the board file name prepended with autosaveFilePrefix string.
1211 autoSaveFileName.SetName( FILEEXT::AutoSaveFilePrefix + autoSaveFileName.GetName() );
1212
1213 if( !autoSaveFileName.IsOk() )
1214 return false;
1215
1216 // If the board file path is not writable, try writing to a platform specific temp file
1217 // path. If that path isn't writable, give up.
1218 if( !autoSaveFileName.IsDirWritable() )
1219 {
1220 autoSaveFileName.SetPath( wxFileName::GetTempDir() );
1221
1222 if( !autoSaveFileName.IsOk() || !autoSaveFileName.IsDirWritable() )
1223 return false;
1224 }
1225
1226 wxLogTrace( traceAutoSave,
1227 wxT( "Creating auto save file <" ) + autoSaveFileName.GetFullPath() + wxT( ">" ) );
1228
1229 if( SavePcbFile( autoSaveFileName.GetFullPath(), false, false ) )
1230 {
1232 GetBoard()->SetFileName( tmpFileName.GetFullPath() );
1233 UpdateTitle();
1234 m_autoSaveRequired = false;
1235 m_autoSavePending = false;
1236
1237 if( !Kiface().IsSingle() &&
1238 GetSettingsManager()->GetCommonSettings()->m_Backup.backup_on_autosave )
1239 {
1241 }
1242
1243 SetTitle( title ); // Restore initial frame title
1244
1245 return true;
1246 }
1247
1248 GetBoard()->SetFileName( tmpFileName.GetFullPath() );
1249
1250 SetTitle( title ); // Restore initial frame title
1251
1252 return false;
1253}
1254
1255
1256bool PCB_EDIT_FRAME::importFile( const wxString& aFileName, int aFileType,
1257 const std::map<std::string, UTF8>* aProperties )
1258{
1259 m_importProperties = aProperties;
1260
1261 switch( (PCB_IO_MGR::PCB_FILE_T) aFileType )
1262 {
1264 case PCB_IO_MGR::EAGLE:
1267 return OpenProjectFiles( std::vector<wxString>( 1, aFileName ),
1269
1270 default: break;
1271 }
1272
1273 m_importProperties = nullptr;
1274
1275 return false;
1276}
1277
1278
1279void PCB_EDIT_FRAME::GenIPC2581File( wxCommandEvent& event )
1280{
1281 DIALOG_EXPORT_2581 dlg( this );
1282
1283 if( dlg.ShowModal() != wxID_OK )
1284 return;
1285
1286 wxFileName pcbFileName = dlg.GetOutputPath();
1287
1288 // Write through symlinks, don't replace them
1290
1291 if( pcbFileName.GetName().empty() )
1292 {
1293 DisplayError( this, _( "The board must be saved before generating IPC2581 file." ) );
1294 return;
1295 }
1296
1297 if( !IsWritable( pcbFileName ) )
1298 {
1299 wxString msg = wxString::Format( _( "Insufficient permissions to write file '%s'." ),
1300 pcbFileName.GetFullPath() );
1301
1302 DisplayError( this, msg );
1303 return;
1304 }
1305
1306 wxString tempFile = wxFileName::CreateTempFileName( wxS( "pcbnew_ipc" ) );
1307 wxString upperTxt;
1308 wxString lowerTxt;
1309 WX_PROGRESS_REPORTER reporter( this, _( "Generating IPC2581 file" ), 5 );
1310 std::map<std::string, UTF8> props;
1311
1312 props["units"] = dlg.GetUnitsString();
1313 props["sigfig"] = dlg.GetPrecision();
1314 props["version"] = dlg.GetVersion();
1315 props["OEMRef"] = dlg.GetOEM();
1316 props["mpn"] = dlg.GetMPN();
1317 props["mfg"] = dlg.GetMfg();
1318 props["dist"] = dlg.GetDist();
1319 props["distpn"] = dlg.GetDistPN();
1320
1321 auto saveFile =
1322 [&]() -> bool
1323 {
1324 try
1325 {
1327 pi->SetProgressReporter( &reporter );
1328 pi->SaveBoard( tempFile, GetBoard(), &props );
1329 return true;
1330 }
1331 catch( const IO_ERROR& ioe )
1332 {
1333 DisplayError( this, wxString::Format( _( "Error generating IPC2581 file '%s'.\n%s" ),
1334 pcbFileName.GetFullPath(), ioe.What() ) );
1335
1336 lowerTxt.Printf( _( "Failed to create temporary file '%s'." ), tempFile );
1337
1338 SetMsgPanel( upperTxt, lowerTxt );
1339
1340 // In case we started a file but didn't fully write it, clean up
1341 wxRemoveFile( tempFile );
1342
1343 return false;
1344 }
1345 };
1346
1348 auto ret = tp.submit( saveFile );
1349
1350
1351 std::future_status status = ret.wait_for( std::chrono::milliseconds( 250 ) );
1352
1353 while( status != std::future_status::ready )
1354 {
1355 reporter.KeepRefreshing();
1356 status = ret.wait_for( std::chrono::milliseconds( 250 ) );
1357 }
1358
1359 try
1360 {
1361 if( !ret.get() )
1362 return;
1363 }
1364 catch( const std::exception& e )
1365 {
1366 wxLogError( "Exception in IPC2581 generation: %s", e.what() );
1367 GetScreen()->SetContentModified( false );
1368 return;
1369 }
1370
1371 // Preserve the permissions of the current file
1372 KIPLATFORM::IO::DuplicatePermissions( pcbFileName.GetFullPath(), tempFile );
1373
1374 if( dlg.GetCompress() )
1375 {
1376 wxFileName tempfn = pcbFileName;
1377 tempfn.SetExt( FILEEXT::Ipc2581FileExtension );
1378 wxFileName zipfn = tempFile;
1379 zipfn.SetExt( "zip" );
1380
1381 wxFFileOutputStream fnout( zipfn.GetFullPath() );
1382 wxZipOutputStream zip( fnout );
1383 wxFFileInputStream fnin( tempFile );
1384
1385 zip.PutNextEntry( tempfn.GetFullName() );
1386 fnin.Read( zip );
1387 zip.Close();
1388 fnout.Close();
1389
1390 wxRemoveFile( tempFile );
1391 tempFile = zipfn.GetFullPath();
1392 }
1393
1394 // If save succeeded, replace the original with what we just wrote
1395 if( !wxRenameFile( tempFile, pcbFileName.GetFullPath() ) )
1396 {
1397 DisplayError( this, wxString::Format( _( "Error generating IPC2581 file '%s'.\n"
1398 "Failed to rename temporary file '%s." ),
1399 pcbFileName.GetFullPath(),
1400 tempFile ) );
1401
1402 lowerTxt.Printf( _( "Failed to rename temporary file '%s'." ),
1403 tempFile );
1404
1405 SetMsgPanel( upperTxt, lowerTxt );
1406 }
1407
1408 GetScreen()->SetContentModified( false );
1409}
1410
1411
1412void PCB_EDIT_FRAME::GenODBPPFiles( wxCommandEvent& event )
1413{
1414 DIALOG_EXPORT_ODBPP dlg( this );
1415
1416 if( dlg.ShowModal() != wxID_OK )
1417 return;
1418
1420
1421 job.SetOutputPath( dlg.GetOutputPath() );
1422 job.m_filename = GetBoard()->GetFileName();
1425 job.m_precision = dlg.GetPrecision();
1428
1429 WX_PROGRESS_REPORTER progressReporter( this, _( "Generating ODB++ output files" ), 3, false );
1430 WX_STRING_REPORTER reporter;
1431
1432 DIALOG_EXPORT_ODBPP::GenerateODBPPFiles( job, GetBoard(), this, &progressReporter, &reporter );
1433
1434 if( reporter.HasMessage() )
1435 DisplayError( this, reporter.GetMessages() );
1436}
const char * name
Definition: DXF_plotter.cpp:57
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:290
bool m_LegacyDesignSettingsLoaded
True if the legacy board design settings were loaded from a file.
Definition: board.h:373
GAL_SET m_LegacyVisibleItems
Definition: board.h:370
void BuildListOfNets()
Definition: board.h:834
void SetFileName(const wxString &aFileName)
Definition: board.h:325
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:187
void SynchronizeNetsAndNetClasses(bool aResetTrackAndViaSizes)
Copy NETCLASS info to each NET, based on NET membership in a NETCLASS.
Definition: board.cpp:2055
LSET m_LegacyVisibleLayers
Visibility settings stored in board prior to 6.0, only used for loading legacy files.
Definition: board.h:369
void SetProject(PROJECT *aProject, bool aReferenceOnly=false)
Link a board to a given project.
Definition: board.cpp:197
const wxString & GetFileName() const
Definition: board.h:327
int GetFileFormatVersionAtLoad() const
Definition: board.h:394
const wxString & GetGenerator() const
Adds an item to the container.
Definition: board.h:397
void ClearProject()
Definition: board.cpp:235
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:895
void SynchronizeProperties()
Copy the current project's text variables into the boards property cache.
Definition: board.cpp:2046
bool m_LegacyCopperEdgeClearanceLoaded
Definition: board.h:374
int GetCount() const
Return the number of objects in the list.
Definition: collector.h:81
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
Returns 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)
Removes all files from the file history.
wxString GetMruPath() const
virtual void DeleteAutoSaveFile(const wxFileName &aFileName)
bool IsWritable(const wxFileName &aFileName, bool aVerbose=true)
Checks if aFileName can be written.
wxString GetFileFromHistory(int cmdId, const wxString &type, FILE_HISTORY *aFileHistory=nullptr)
Fetches 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:67
bool IsModified() const
Definition: eda_item.h:106
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 SetOutputPath(const wxString &aPath)
Definition: job.cpp:129
Helper class to create more flexible dialogs, including 'do not show again' checkbox handling.
Definition: kidialog.h:43
void DoNotShowCheckbox(wxString file, int line)
Checks the 'do not show again' setting for the dialog.
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:99
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:115
static wxString GetDefaultUserProjectsPath()
Gets the default path we point users to create projects.
Definition: paths.cpp:140
static TOOL_ACTION repairBoard
Definition: pcb_actions.h:549
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 SavePcbCopy(const wxString &aFileName, bool aCreateProject=false)
Write the board data structures to aFileName.
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 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
Saves 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
@ LEGACY
Legacy Pcbnew file formats prior to s-expression.
Definition: pcb_io_mgr.h:59
@ 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:164
virtual const wxString GetProjectFullName() const
Return the full path and name of the project.
Definition: project.cpp:129
virtual PROJECT_LOCAL_SETTINGS & GetLocalSettings() const
Definition: project.h:206
virtual const wxString FootprintLibTblName() const
Returns the path and filename of this project's footprint library table.
Definition: project.cpp:165
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:359
virtual bool IsNullProject() const
Check if this project is a null project (i.e.
Definition: project.cpp:153
void SaveProjectAs(const wxString &aFullPath, PROJECT *aProject=nullptr)
Sets the currently loaded project path and saves it (pointers remain valid) Note that this will not m...
void SaveProjectCopy(const wxString &aFullPath, PROJECT *aProject=nullptr)
Saves a copy of the current project under the given path.
bool SaveProject(const wxString &aFullPath=wxEmptyString, PROJECT *aProject=nullptr)
Saves a loaded project.
bool LoadProject(const wxString &aFullPath, bool aSetActive=true)
Loads a project or sets up a new project with a specified path.
bool UnloadProject(PROJECT *aProject, bool aSave=true)
Saves, unloads and unregisters the given PROJECT.
bool TriggerBackupIfNeeded(REPORTER &aReporter) const
Calls 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:167
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:92
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:304
bool HasCloseButton() const
Definition: wx_infobar.cpp:328
@ OUTDATED_SAVE
OUTDATED_SAVE Messages that should be cleared on save.
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:294
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:171
bool HasMessage() const override
Returns true if the reporter client is non-empty.
Definition: reporter.cpp:97
const wxString & GetMessages() const
Definition: reporter.cpp:84
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:422
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:250
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:170
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:130
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition: confirm.cpp:195
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:309
#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:75
@ ID_SAVE_BOARD
Definition: id.h:76
@ ID_LOAD_FILE
Definition: id.h:74
@ ID_SAVE_BOARD_AS
Definition: id.h:77
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:227
@ 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:272
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:40
#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:81
@ ID_COPY_BOARD_AS
Definition: pcbnew_id.h:17
SETTINGS_MANAGER * GetSettingsManager()
PGM_BASE & Pgm()
The global Program "get" accessor.
Definition: pgm_base.cpp:1060
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:68
bool show_import_issues
Stored value for "show import issues" when importing non-KiCad designs to this application.
Definition: app_settings.h:158
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:45
bool m_CanRead
Whether the IO can read this file type.
Definition: io_base.h:48
static thread_pool * tp
Definition: thread_pool.cpp:30
BS::thread_pool thread_pool
Definition: thread_pool.h:30
thread_pool & GetKiCadThreadPool()
Get a reference to the current thread pool.
Definition: thread_pool.cpp:32
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.