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() || !desc.m_CanRead )
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 = FILEEXT::AutoSaveFilePrefix + 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
447int PCB_EDIT_FRAME::inferLegacyEdgeClearance( BOARD* aBoard, bool aShowUserMsg )
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 && aShowUserMsg )
476 {
477 // If they had different widths then we can't ensure that fills will be the same.
478 DisplayInfoMessage( this,
479 _( "If the zones on this board are refilled the Copper Edge "
480 "Clearance setting will be used (see Board Setup > Design "
481 "Rules > Constraints).\n This may result in different fills "
482 "from previous KiCad versions which used the line thicknesses "
483 "of the board boundary on the Edge Cuts layer." ) );
484 }
485
486 return std::max( 0, edgeWidth / 2 );
487}
488
489
490bool PCB_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, int aCtl )
491{
492 // This is for python:
493 if( aFileSet.size() != 1 )
494 {
495 UTF8 msg = StrPrintf( "Pcbnew:%s() takes a single filename", __func__ );
496 DisplayError( this, msg );
497 return false;
498 }
499
500 wxString fullFileName( aFileSet[0] );
501 wxFileName wx_filename( fullFileName );
502 wxString msg;
503
504 if( Kiface().IsSingle() )
506
507 // We insist on caller sending us an absolute path, if it does not, we say it's a bug.
508 wxASSERT_MSG( wx_filename.IsAbsolute(), wxT( "Path is not absolute!" ) );
509
510 std::unique_ptr<LOCKFILE> lock = std::make_unique<LOCKFILE>( fullFileName );
511
512 if( !lock->Valid() && lock->IsLockedByMe() )
513 {
514 // If we cannot acquire the lock but we appear to be the one who
515 // locked it, check to see if there is another KiCad instance running.
516 // If there is not, then we can override the lock. This could happen if
517 // KiCad crashed or was interrupted
518
519 if( !Pgm().SingleInstance()->IsAnotherRunning() )
520 lock->OverrideLock();
521 }
522
523 if( !lock->Valid() )
524 {
525 msg.Printf( _( "PCB '%s' is already open by '%s' at '%s'." ), wx_filename.GetFullName(),
526 lock->GetUsername(), lock->GetHostname() );
527
528 if( !AskOverrideLock( this, msg ) )
529 return false;
530
531 lock->OverrideLock();
532 }
533
534 if( IsContentModified() )
535 {
536 if( !HandleUnsavedChanges( this, _( "The current PCB has been modified. Save changes?" ),
537 [&]() -> bool
538 {
539 return SavePcbFile( GetBoard()->GetFileName() );
540 } ) )
541 {
542 return false;
543 }
544 }
545
546 wxFileName pro = fullFileName;
547 pro.SetExt( FILEEXT::ProjectFileExtension );
548
549 bool is_new = !wxFileName::IsFileReadable( fullFileName );
550
551 // If its a non-existent schematic and caller thinks it exists
552 if( is_new && !( aCtl & KICTL_CREATE ) )
553 {
554 // notify user that fullFileName does not exist, ask if user wants to create it.
555 msg.Printf( _( "PCB '%s' does not exist. Do you wish to create it?" ), fullFileName );
556
557 if( !IsOK( this, msg ) )
558 return false;
559 }
560
561 // Get rid of any existing warnings about the old board
562 GetInfoBar()->Dismiss();
563
564 WX_PROGRESS_REPORTER progressReporter( this, is_new ? _( "Creating PCB" )
565 : _( "Loading PCB" ), 1 );
566
567 // No save prompt (we already prompted above), and only reset to a new blank board if new
568 Clear_Pcb( false, !is_new );
569
571
572 if( !is_new )
573 pluginType = PCB_IO_MGR::FindPluginTypeFromBoardPath( fullFileName, aCtl );
574
575 if( pluginType == PCB_IO_MGR::FILE_TYPE_NONE )
576 return false;
577
578 bool converted = pluginType != PCB_IO_MGR::LEGACY && pluginType != PCB_IO_MGR::KICAD_SEXP;
579
580 // Loading a project should only be done under carefully considered circumstances.
581
582 // The calling code should know not to ask me here to change projects unless
583 // it knows what consequences that will have on other KIFACEs running and using
584 // this same PROJECT. It can be very harmful if that calling code is stupid.
586
587 if( pro.GetFullPath() != mgr->Prj().GetProjectFullName() )
588 {
589 // calls SaveProject
591
593 mgr->UnloadProject( &mgr->Prj() );
594
595 mgr->LoadProject( pro.GetFullPath() );
596
597 // Do not allow saving a project if one doesn't exist. This normally happens if we are
598 // standalone and opening a board that has been moved from its project folder.
599 // For converted projects, we don't want to set the read-only flag because we want a project
600 // to be saved for the new file in case things like netclasses got migrated.
601 Prj().SetReadOnly( !pro.Exists() && !converted );
602 }
603
604 // Clear the cache footprint list which may be project specific
606
607 if( is_new )
608 {
609 // Link the existing blank board to the new project
610 GetBoard()->SetProject( &Prj() );
611
612 GetBoard()->SetFileName( fullFileName );
613
614 OnModify();
615 }
616 else
617 {
618 BOARD* loadedBoard = nullptr; // it will be set to non-NULL if loaded OK
620
621 LAYER_REMAPPABLE_PLUGIN* layerRemappableIO = dynamic_cast<LAYER_REMAPPABLE_PLUGIN*>( pi.get() );
622
623 if( layerRemappableIO )
624 {
625 layerRemappableIO->RegisterLayerMappingCallback(
626 std::bind( DIALOG_IMPORTED_LAYERS::GetMapModal, this, std::placeholders::_1 ) );
627 }
628
629 PROJECT_CHOOSER_PLUGIN* projectChooserIO = dynamic_cast<PROJECT_CHOOSER_PLUGIN*>( pi.get() );
630
631 if( projectChooserIO )
632 {
633 projectChooserIO->RegisterChooseProjectCallback(
635 std::placeholders::_1 ) );
636 }
637
638 if( ( aCtl & KICTL_REVERT ) )
639 {
640 DeleteAutoSaveFile( fullFileName );
641 }
642 else
643 {
644 // This will rename the file if there is an autosave and the user wants to recover
645 CheckForAutoSaveFile( fullFileName );
646 }
647
648 bool failedLoad = false;
649
650 try
651 {
652 if( pi == nullptr )
653 {
654 // There was no plugin found, e.g. due to invalid file extension, file header,...
655 THROW_IO_ERROR( _( "File format is not supported" ) );
656 }
657
658 STRING_UTF8_MAP props;
659
661 props.insert( m_importProperties->begin(), m_importProperties->end() );
662
663 // PCB_IO_EAGLE can use this info to center the BOARD, but it does not yet.
664 props["page_width"] = std::to_string( GetPageSizeIU().x );
665 props["page_height"] = std::to_string( GetPageSizeIU().y );
666
667 pi->SetQueryUserCallback(
668 [&]( wxString aTitle, int aIcon, wxString aMessage, wxString aAction ) -> bool
669 {
670 KIDIALOG dlg( nullptr, aMessage, aTitle, wxOK | wxCANCEL | aIcon );
671
672 if( !aAction.IsEmpty() )
673 dlg.SetOKLabel( aAction );
674
675 dlg.DoNotShowCheckbox( aMessage, 0 );
676
677 return dlg.ShowModal() == wxID_OK;
678 } );
679
680#if USE_INSTRUMENTATION
681 // measure the time to load a BOARD.
682 int64_t startTime = GetRunningMicroSecs();
683#endif
684
685 pi->SetProgressReporter( &progressReporter );
686 loadedBoard = pi->LoadBoard( fullFileName, nullptr, &props, &Prj() );
687
688#if USE_INSTRUMENTATION
689 int64_t stopTime = GetRunningMicroSecs();
690 printf( "PCB_IO::Load(): %u usecs\n", stopTime - startTime );
691#endif
692 }
693 catch( const FUTURE_FORMAT_ERROR& ffe )
694 {
695 msg.Printf( _( "Error loading PCB '%s'." ), fullFileName );
696 progressReporter.Hide();
697 DisplayErrorMessage( this, msg, ffe.Problem() );
698
699 failedLoad = true;
700 }
701 catch( const IO_ERROR& ioe )
702 {
703 if( ioe.Problem() != wxT( "CANCEL" ) )
704 {
705 msg.Printf( _( "Error loading PCB '%s'." ), fullFileName );
706 progressReporter.Hide();
707 DisplayErrorMessage( this, msg, ioe.What() );
708 }
709
710 failedLoad = true;
711 }
712 catch( const std::bad_alloc& )
713 {
714 msg.Printf( _( "Memory exhausted loading PCB '%s'" ), fullFileName );
715 progressReporter.Hide();
716 DisplayErrorMessage( this, msg, wxEmptyString );
717
718 failedLoad = true;
719 }
720
721 if( failedLoad || !loadedBoard )
722 {
723 // We didn't create a new blank board above, so do that now
724 Clear_Pcb( false );
725
726 return false;
727 }
728
729 // This fixes a focus issue after the progress reporter is done on GTK. It shouldn't
730 // cause any issues on macOS and Windows. If it does, it will have to be conditionally
731 // compiled.
732 Raise();
733
734 // Skip (possibly expensive) connectivity build here; we build it below after load
735 SetBoard( loadedBoard, false, &progressReporter );
736
737 if( GFootprintList.GetCount() == 0 )
738 GFootprintList.ReadCacheFromFile( Prj().GetProjectPath() + wxT( "fp-info-cache" ) );
739
740 if( loadedBoard->m_LegacyDesignSettingsLoaded )
741 {
742 Prj().SetReadOnly( false );
743
744 // Before we had a copper edge clearance setting, the edge line widths could be used
745 // as a kludge to control them. So if there's no setting then infer it from the
746 // edge widths.
747 if( !loadedBoard->m_LegacyCopperEdgeClearanceLoaded )
748 {
749 // Do not show the inferred edge clearance warning dialog when loading third
750 // party boards. For some reason the dialog completely hangs all of KiCad and
751 // the imported board cannot be saved.
752 int edgeClearance = inferLegacyEdgeClearance( loadedBoard, !converted );
753 loadedBoard->GetDesignSettings().m_CopperEdgeClearance = edgeClearance;
754 }
755
756 // On save; design settings will be removed from the board
757 loadedBoard->SetModified();
758 }
759
760 // Move legacy view settings to local project settings
761 if( !loadedBoard->m_LegacyVisibleLayers.test( Rescue ) )
762 {
764 loadedBoard->SetModified();
765 }
766
768 {
770 loadedBoard->SetModified();
771 }
772
773 // we should not ask PCB_IOs to do these items:
774 loadedBoard->BuildListOfNets();
775 ResolveDRCExclusions( true );
777
778 if( loadedBoard->IsModified() )
779 OnModify();
780 else
781 GetScreen()->SetContentModified( false );
782
783 if( ( pluginType == PCB_IO_MGR::LEGACY )
784 || ( pluginType == PCB_IO_MGR::KICAD_SEXP
786 && loadedBoard->GetGenerator().Lower() != wxT( "gerbview" ) ) )
787 {
790 m_infoBar->ShowMessage( _( "This file was created by an older version of KiCad. "
791 "It will be converted to the new format when saved." ),
793 }
794
795 // Import footprints into a project-specific library
796 //==================================================
797 // TODO: This should be refactored out of here into somewhere specific to the Project Import
798 // E.g. KICAD_MANAGER_FRAME::ImportNonKiCadProject
799 if( aCtl & KICTL_IMPORT_LIB )
800 {
801 wxFileName loadedBoardFn( fullFileName );
802 wxString libNickName = loadedBoardFn.GetName();
803
804 // Extract a footprint library from the design and add it to the fp-lib-table
805 // The footprints are saved in a new .pretty library.
806 // If this library already exists, all previous footprints will be deleted
807 std::vector<FOOTPRINT*> loadedFootprints = pi->GetImportedCachedLibraryFootprints();
808 wxString newLibPath = CreateNewProjectLibrary( libNickName );
809
810 // Only create the new library if CreateNewLibrary succeeded (note that this fails if
811 // the library already exists and the user aborts after seeing the warning message
812 // which prompts the user to continue with overwrite or abort)
813 if( newLibPath.Length() > 0 )
814 {
816
817 for( FOOTPRINT* footprint : loadedFootprints )
818 {
819 try
820 {
821 if( !footprint->GetFPID().GetLibItemName().empty() ) // Handle old boards.
822 {
823 footprint->SetReference( "REF**" );
824 piSexpr->FootprintSave( newLibPath, footprint );
825 delete footprint;
826 }
827 }
828 catch( const IO_ERROR& ioe )
829 {
830 wxLogError( _( "Error saving footprint %s to project specific library." )
831 + wxS( "\n%s" ),
832 footprint->GetFPID().GetUniStringLibItemName(),
833 ioe.What() );
834 }
835 }
836
838 const wxString& project_env = PROJECT_VAR_NAME;
839 wxString rel_path, env_path;
840
841 wxASSERT_MSG( wxGetEnv( project_env, &env_path ),
842 wxT( "There is no project variable?" ) );
843
844 wxString result( newLibPath );
845
846 if( result.Replace( env_path, wxT( "$(" ) + project_env + wxT( ")" ) ) )
847 rel_path = result;
848
849 FP_LIB_TABLE_ROW* row = new FP_LIB_TABLE_ROW( libNickName, rel_path,
850 wxT( "KiCad" ), wxEmptyString );
851 prjlibtable->InsertRow( row );
852
853 wxString tblName = Prj().FootprintLibTblName();
854
855 try
856 {
857 PROJECT_PCB::PcbFootprintLibs( &Prj() )->Save( tblName );
858 }
859 catch( const IO_ERROR& ioe )
860 {
861 wxLogError( _( "Error saving project specific footprint library table." )
862 + wxS( "\n%s" ),
863 ioe.What() );
864 }
865
866 // Update footprint LIB_IDs to point to the just imported library
867 for( FOOTPRINT* footprint : GetBoard()->Footprints() )
868 {
869 LIB_ID libId = footprint->GetFPID();
870
871 if( libId.GetLibItemName().empty() )
872 continue;
873
874 libId.SetLibNickname( libNickName );
875 footprint->SetFPID( libId );
876 }
877 }
878 }
879 }
880
881 {
882 wxFileName fn = fullFileName;
883
884 if( converted )
885 fn.SetExt( FILEEXT::PcbFileExtension );
886
887 wxString fname = fn.GetFullPath();
888
889 fname.Replace( WIN_STRING_DIR_SEP, UNIX_STRING_DIR_SEP );
890
891 GetBoard()->SetFileName( fname );
892 }
893
894 // Lock the file newly opened:
895 m_file_checker.reset( lock.release() );
896
897 if( !converted )
898 UpdateFileHistory( GetBoard()->GetFileName() );
899
900 std::vector<ZONE*> toFill;
901
902 // Rebuild list of nets (full ratsnest rebuild)
903 GetBoard()->BuildConnectivity( &progressReporter );
904
905 // Load project settings after setting up board; some of them depend on the nets list
907
908 // Syncs the UI (appearance panel, etc) with the loaded board and project
910
911 // Refresh the 3D view, if any
912 EDA_3D_VIEWER_FRAME* draw3DFrame = Get3DViewerFrame();
913
914 if( draw3DFrame )
915 draw3DFrame->NewDisplay();
916#if 0 && defined(DEBUG)
917 // Output the board object tree to stdout, but please run from command prompt:
918 GetBoard()->Show( 0, std::cout );
919#endif
920
921 // from EDA_APPL which was first loaded BOARD only:
922 {
923 /* For an obscure reason the focus is lost after loading a board file
924 * when starting up the process.
925 * (seems due to the recreation of the layer manager after loading the file)
926 * Give focus to main window and Drawpanel
927 * must be done for these 2 windows (for an obscure reason ...)
928 * Linux specific
929 * This is more a workaround than a fix.
930 */
931 SetFocus();
932 GetCanvas()->SetFocus();
933 }
934
935 return true;
936}
937
938
939bool PCB_EDIT_FRAME::SavePcbFile( const wxString& aFileName, bool addToHistory,
940 bool aChangeProject )
941{
942 // please, keep it simple. prompting goes elsewhere.
943 wxFileName pcbFileName = aFileName;
944
945 if( pcbFileName.GetExt() == FILEEXT::LegacyPcbFileExtension )
946 pcbFileName.SetExt( FILEEXT::KiCadPcbFileExtension );
947
948 // Write through symlinks, don't replace them
950
951 if( !IsWritable( pcbFileName ) )
952 {
953 wxString msg = wxString::Format( _( "Insufficient permissions to write file '%s'." ),
954 pcbFileName.GetFullPath() );
955
956 DisplayError( this, msg );
957 return false;
958 }
959
960 // TODO: these will break if we ever go multi-board
961 wxFileName projectFile( pcbFileName );
962 wxFileName rulesFile( pcbFileName );
963 wxString msg;
964
965 projectFile.SetExt( FILEEXT::ProjectFileExtension );
966 rulesFile.SetExt( FILEEXT::DesignRulesFileExtension );
967
968 if( projectFile.FileExists() )
969 {
971 }
972 else if( aChangeProject )
973 {
974 Prj().SetReadOnly( false );
975 GetSettingsManager()->SaveProjectAs( projectFile.GetFullPath() );
976 }
977
978 wxFileName currentRules( GetDesignRulesPath() );
979
980 if( currentRules.FileExists() && !rulesFile.FileExists() && aChangeProject )
981 KiCopyFile( currentRules.GetFullPath(), rulesFile.GetFullPath(), msg );
982
983 if( !msg.IsEmpty() )
984 {
985 DisplayError( this, wxString::Format( _( "Error saving custom rules file '%s'." ),
986 rulesFile.GetFullPath() ) );
987 }
988
989 if( projectFile.FileExists() )
990 {
991 // Save various DRC parameters, such as violation severities (which may have been
992 // edited via the DRC dialog as well as the Board Setup dialog), DRC exclusions, etc.
994
997 }
998
999 wxString tempFile = wxFileName::CreateTempFileName( wxS( "pcbnew" ) );
1000 wxString upperTxt;
1001 wxString lowerTxt;
1002
1003 try
1004 {
1006
1007 pi->SaveBoard( tempFile, GetBoard(), nullptr );
1008 }
1009 catch( const IO_ERROR& ioe )
1010 {
1011 DisplayError( this, wxString::Format( _( "Error saving board file '%s'.\n%s" ),
1012 pcbFileName.GetFullPath(),
1013 ioe.What() ) );
1014
1015 lowerTxt.Printf( _( "Failed to create temporary file '%s'." ), tempFile );
1016
1017 SetMsgPanel( upperTxt, lowerTxt );
1018
1019 // In case we started a file but didn't fully write it, clean up
1020 wxRemoveFile( tempFile );
1021
1022 return false;
1023 }
1024
1025 // Preserve the permissions of the current file
1026 KIPLATFORM::IO::DuplicatePermissions( pcbFileName.GetFullPath(), tempFile );
1027
1028 // If save succeeded, replace the original with what we just wrote
1029 if( !wxRenameFile( tempFile, pcbFileName.GetFullPath() ) )
1030 {
1031 DisplayError( this, wxString::Format( _( "Error saving board file '%s'.\n"
1032 "Failed to rename temporary file '%s." ),
1033 pcbFileName.GetFullPath(),
1034 tempFile ) );
1035
1036 lowerTxt.Printf( _( "Failed to rename temporary file '%s'." ),
1037 tempFile );
1038
1039 SetMsgPanel( upperTxt, lowerTxt );
1040
1041 return false;
1042 }
1043
1044 if( !Kiface().IsSingle() )
1045 {
1046 WX_STRING_REPORTER backupReporter( &upperTxt );
1047
1048 if( GetSettingsManager()->TriggerBackupIfNeeded( backupReporter ) )
1049 upperTxt.clear();
1050 }
1051
1052 GetBoard()->SetFileName( pcbFileName.GetFullPath() );
1053
1054 // Update the lock in case it was a Save As
1055 LockFile( pcbFileName.GetFullPath() );
1056
1057 // Put the saved file in File History if requested
1058 if( addToHistory )
1059 UpdateFileHistory( GetBoard()->GetFileName() );
1060
1061 // Delete auto save file on successful save.
1062 wxFileName autoSaveFileName = pcbFileName;
1063
1064 autoSaveFileName.SetName( FILEEXT::AutoSaveFilePrefix + pcbFileName.GetName() );
1065
1066 if( autoSaveFileName.FileExists() )
1067 wxRemoveFile( autoSaveFileName.GetFullPath() );
1068
1069 lowerTxt.Printf( _( "File '%s' saved." ), pcbFileName.GetFullPath() );
1070
1071 SetStatusText( lowerTxt, 0 );
1072
1073 // Get rid of the old version conversion warning, or any other dismissable warning :)
1075 m_infoBar->Dismiss();
1076
1077 if( m_infoBar->IsShownOnScreen() && m_infoBar->HasCloseButton() )
1078 m_infoBar->Dismiss();
1079
1080 GetScreen()->SetContentModified( false );
1081 UpdateTitle();
1082 return true;
1083}
1084
1085
1086bool PCB_EDIT_FRAME::SavePcbCopy( const wxString& aFileName, bool aCreateProject )
1087{
1088 wxFileName pcbFileName( EnsureFileExtension( aFileName, FILEEXT::KiCadPcbFileExtension ) );
1089
1090 if( !IsWritable( pcbFileName ) )
1091 {
1092 DisplayError( this, wxString::Format( _( "Insufficient permissions to write file '%s'." ),
1093 pcbFileName.GetFullPath() ) );
1094 return false;
1095 }
1096
1097 // Save various DRC parameters, such as violation severities (which may have been
1098 // edited via the DRC dialog as well as the Board Setup dialog), DRC exclusions, etc.
1100
1102
1103 try
1104 {
1106
1107 wxASSERT( pcbFileName.IsAbsolute() );
1108
1109 pi->SaveBoard( pcbFileName.GetFullPath(), GetBoard(), nullptr );
1110 }
1111 catch( const IO_ERROR& ioe )
1112 {
1113 DisplayError( this, wxString::Format( _( "Error saving board file '%s'.\n%s" ),
1114 pcbFileName.GetFullPath(),
1115 ioe.What() ) );
1116
1117 return false;
1118 }
1119
1120 wxFileName projectFile( pcbFileName );
1121 wxFileName rulesFile( pcbFileName );
1122 wxString msg;
1123
1124 projectFile.SetExt( FILEEXT::ProjectFileExtension );
1125 rulesFile.SetExt( FILEEXT::DesignRulesFileExtension );
1126
1127 if( aCreateProject && !projectFile.FileExists() )
1128 GetSettingsManager()->SaveProjectCopy( projectFile.GetFullPath() );
1129
1130 wxFileName currentRules( GetDesignRulesPath() );
1131
1132 if( aCreateProject && currentRules.FileExists() && !rulesFile.FileExists() )
1133 KiCopyFile( currentRules.GetFullPath(), rulesFile.GetFullPath(), msg );
1134
1135 if( !msg.IsEmpty() )
1136 {
1137 DisplayError( this, wxString::Format( _( "Error saving custom rules file '%s'." ),
1138 rulesFile.GetFullPath() ) );
1139 }
1140
1141 DisplayInfoMessage( this, wxString::Format( _( "Board copied to:\n%s" ),
1142 pcbFileName.GetFullPath() ) );
1143
1144 return true;
1145}
1146
1147
1149{
1150 wxFileName tmpFileName;
1151
1152 // Don't run autosave if content has not been modified
1153 if( !IsContentModified() )
1154 return true;
1155
1156 wxString title = GetTitle(); // Save frame title, that can be modified by the save process
1157
1158 if( GetBoard()->GetFileName().IsEmpty() )
1159 {
1160 tmpFileName = wxFileName( PATHS::GetDefaultUserProjectsPath(), NAMELESS_PROJECT,
1162 GetBoard()->SetFileName( tmpFileName.GetFullPath() );
1163 }
1164 else
1165 {
1166 tmpFileName = Prj().AbsolutePath( GetBoard()->GetFileName() );
1167 }
1168
1169 wxFileName autoSaveFileName = tmpFileName;
1170
1171 // Auto save file name is the board file name prepended with autosaveFilePrefix string.
1172 autoSaveFileName.SetName( FILEEXT::AutoSaveFilePrefix + autoSaveFileName.GetName() );
1173
1174 if( !autoSaveFileName.IsOk() )
1175 return false;
1176
1177 // If the board file path is not writable, try writing to a platform specific temp file
1178 // path. If that path isn't writable, give up.
1179 if( !autoSaveFileName.IsDirWritable() )
1180 {
1181 autoSaveFileName.SetPath( wxFileName::GetTempDir() );
1182
1183 if( !autoSaveFileName.IsOk() || !autoSaveFileName.IsDirWritable() )
1184 return false;
1185 }
1186
1187 wxLogTrace( traceAutoSave,
1188 wxT( "Creating auto save file <" ) + autoSaveFileName.GetFullPath() + wxT( ">" ) );
1189
1190 if( SavePcbFile( autoSaveFileName.GetFullPath(), false, false ) )
1191 {
1193 GetBoard()->SetFileName( tmpFileName.GetFullPath() );
1194 UpdateTitle();
1195 m_autoSaveRequired = false;
1196 m_autoSavePending = false;
1197
1198 if( !Kiface().IsSingle() &&
1199 GetSettingsManager()->GetCommonSettings()->m_Backup.backup_on_autosave )
1200 {
1202 }
1203
1204 SetTitle( title ); // Restore initial frame title
1205
1206 return true;
1207 }
1208
1209 GetBoard()->SetFileName( tmpFileName.GetFullPath() );
1210
1211 SetTitle( title ); // Restore initial frame title
1212
1213 return false;
1214}
1215
1216
1217bool PCB_EDIT_FRAME::importFile( const wxString& aFileName, int aFileType,
1218 const STRING_UTF8_MAP* aProperties )
1219{
1220 m_importProperties = aProperties;
1221
1222 switch( (PCB_IO_MGR::PCB_FILE_T) aFileType )
1223 {
1225 case PCB_IO_MGR::EAGLE:
1228 return OpenProjectFiles( std::vector<wxString>( 1, aFileName ),
1230
1231 default: break;
1232 }
1233
1234 m_importProperties = nullptr;
1235
1236 return false;
1237}
1238
1239
1240void PCB_EDIT_FRAME::GenIPC2581File( wxCommandEvent& event )
1241{
1242 DIALOG_EXPORT_2581 dlg( this );
1243
1244 if( dlg.ShowModal() != wxID_OK )
1245 return;
1246
1247 wxFileName pcbFileName = dlg.GetOutputPath();
1248
1249 // Write through symlinks, don't replace them
1251
1252 if( pcbFileName.GetName().empty() )
1253 {
1254 DisplayError( this, _( "The board must be saved before generating IPC2581 file." ) );
1255 return;
1256 }
1257
1258 if( !IsWritable( pcbFileName ) )
1259 {
1260 wxString msg = wxString::Format( _( "Insufficient permissions to write file '%s'." ),
1261 pcbFileName.GetFullPath() );
1262
1263 DisplayError( this, msg );
1264 return;
1265 }
1266
1267 wxString tempFile = wxFileName::CreateTempFileName( wxS( "pcbnew_ipc" ) );
1268 wxString upperTxt;
1269 wxString lowerTxt;
1270 WX_PROGRESS_REPORTER reporter( this, _( "Generating IPC2581 file" ), 5 );
1271 STRING_UTF8_MAP props;
1272
1273 props["units"] = dlg.GetUnitsString();
1274 props["sigfig"] = dlg.GetPrecision();
1275 props["version"] = dlg.GetVersion();
1276 props["OEMRef"] = dlg.GetOEM();
1277 props["mpn"] = dlg.GetMPN();
1278 props["mfg"] = dlg.GetMfg();
1279 props["dist"] = dlg.GetDist();
1280 props["distpn"] = dlg.GetDistPN();
1281
1282 auto saveFile = [&]() -> bool
1283 {
1284 try
1285 {
1287 pi->SetProgressReporter( &reporter );
1288 pi->SaveBoard( tempFile, GetBoard(), &props );
1289 return true;
1290 }
1291 catch( const IO_ERROR& ioe )
1292 {
1293 DisplayError( this, wxString::Format( _( "Error generating IPC2581 file '%s'.\n%s" ),
1294 pcbFileName.GetFullPath(), ioe.What() ) );
1295
1296 lowerTxt.Printf( _( "Failed to create temporary file '%s'." ), tempFile );
1297
1298 SetMsgPanel( upperTxt, lowerTxt );
1299
1300 // In case we started a file but didn't fully write it, clean up
1301 wxRemoveFile( tempFile );
1302
1303 return false;
1304 }
1305 };
1306
1308 auto ret = tp.submit( saveFile );
1309
1310
1311 std::future_status status = ret.wait_for( std::chrono::milliseconds( 250 ) );
1312
1313 while( status != std::future_status::ready )
1314 {
1315 reporter.KeepRefreshing();
1316 status = ret.wait_for( std::chrono::milliseconds( 250 ) );
1317 }
1318
1319 try
1320 {
1321 if( !ret.get() )
1322 return;
1323 }
1324 catch(const std::exception& e)
1325 {
1326 wxLogError( "Exception in IPC2581 generation: %s", e.what() );
1327 GetScreen()->SetContentModified( false );
1328 return;
1329 }
1330
1331 // Preserve the permissions of the current file
1332 KIPLATFORM::IO::DuplicatePermissions( pcbFileName.GetFullPath(), tempFile );
1333
1334 if( dlg.GetCompress() )
1335 {
1336 wxFileName tempfn = pcbFileName;
1337 tempfn.SetExt( FILEEXT::Ipc2581FileExtension );
1338 wxFileName zipfn = tempFile;
1339 zipfn.SetExt( "zip" );
1340
1341 wxFFileOutputStream fnout( zipfn.GetFullPath() );
1342 wxZipOutputStream zip( fnout );
1343 wxFFileInputStream fnin( tempFile );
1344
1345 zip.PutNextEntry( tempfn.GetFullName() );
1346 fnin.Read( zip );
1347 zip.Close();
1348 fnout.Close();
1349
1350 wxRemoveFile( tempFile );
1351 tempFile = zipfn.GetFullPath();
1352 }
1353
1354 // If save succeeded, replace the original with what we just wrote
1355 if( !wxRenameFile( tempFile, pcbFileName.GetFullPath() ) )
1356 {
1357 DisplayError( this, wxString::Format( _( "Error generating IPC2581 file '%s'.\n"
1358 "Failed to rename temporary file '%s." ),
1359 pcbFileName.GetFullPath(),
1360 tempFile ) );
1361
1362 lowerTxt.Printf( _( "Failed to rename temporary file '%s'." ),
1363 tempFile );
1364
1365 SetMsgPanel( upperTxt, lowerTxt );
1366 }
1367
1368 GetScreen()->SetContentModified( false );
1369}
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:282
bool m_LegacyDesignSettingsLoaded
True if the legacy board design settings were loaded from a file.
Definition: board.h:365
GAL_SET m_LegacyVisibleItems
Definition: board.h:362
void BuildListOfNets()
Definition: board.h:816
void SetFileName(const wxString &aFileName)
Definition: board.h:317
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:180
void SynchronizeNetsAndNetClasses(bool aResetTrackAndViaSizes)
Copy NETCLASS info to each NET, based on NET membership in a NETCLASS.
Definition: board.cpp:1943
LSET m_LegacyVisibleLayers
Visibility settings stored in board prior to 6.0, only used for loading legacy files.
Definition: board.h:361
void SetProject(PROJECT *aProject, bool aReferenceOnly=false)
Link a board to a given project.
Definition: board.cpp:190
const wxString & GetFileName() const
Definition: board.h:319
int GetFileFormatVersionAtLoad() const
Definition: board.h:386
const wxString & GetGenerator() const
Adds an item to the container.
Definition: board.h:389
void ClearProject()
Definition: board.cpp:229
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:797
void SynchronizeProperties()
Copy the current project's text variables into the boards property cache.
Definition: board.cpp:1934
bool m_LegacyCopperEdgeClearanceLoaded
Definition: board.h:366
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.
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:105
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:129
static TOOL_ACTION repairBoard
Definition: pcb_actions.h:537
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, bool aShowUserMsg=true)
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:93
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:56
@ FILE_TYPE_NONE
Definition: pcb_io_mgr.h:76
@ 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: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:535
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:72
bool empty() const
Definition: utf8.h:104
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:156
void KiCopyFile(const wxString &aSrcPath, const wxString &aDestPath, wxString &aErrors)
Definition: gestfich.cpp:305
#define WIN_STRING_DIR_SEP
Definition: gestfich.h:37
#define UNIX_STRING_DIR_SEP
Definition: gestfich.h:36
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: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:595
#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:230
@ Edge_Cuts
Definition: layer_ids.h:113
@ Rescue
Definition: layer_ids.h:133
#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: 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: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:1059
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: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
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
bool m_CanRead
Whether the IO can read this file type.
Definition: io_base.h:44
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.