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