KiCad PCB EDA Suite
Loading...
Searching...
No Matches
pcbnew/files.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2004-2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
5 * Copyright (C) 2011 Wayne Stambaugh <[email protected]>
6 * Copyright (C) 2023 CERN (www.cern.ch)
7 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, you may find one here:
21 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
22 * or you may search the http://www.gnu.org website for the version 2 license,
23 * or you may write to the Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
25 */
26
27#include <string>
28#include <vector>
29
30#include <confirm.h>
31#include <kidialog.h>
32#include <core/arraydim.h>
33#include <thread_pool.h>
34#include <gestfich.h>
35#include <local_history.h>
36#include <pcb_edit_frame.h>
40#include <kiface_base.h>
41#include <macros.h>
42#include <trace_helpers.h>
44#include <lockfile.h>
45#include <wx/snglinst.h>
47#include <pcbnew_id.h>
49#include <tool/tool_manager.h>
50#include <board.h>
51#include <kiplatform/app.h>
53#include <widgets/wx_infobar.h>
56#include <paths.h>
57#include <pgm_base.h>
59#include <project_pcb.h>
63#include <pcb_io/pcb_io_mgr.h>
71#include <tools/pcb_actions.h>
73#include "footprint_info_impl.h"
74#include <board_commit.h>
75#include <reporter.h>
76#include <zone_filler.h>
78#include <widgets/kistatusbar.h>
80#include <wx_filename.h> // For ::ResolvePossibleSymlinks()
81#include <kiplatform/io.h>
82
83#include <wx/stdpaths.h>
84#include <wx/ffile.h>
85#include <wx/filedlg.h>
86#include <wx/txtstrm.h>
87#include <wx/wfstream.h>
88#include <wx/zipstrm.h>
89#include <wx/dir.h>
90
92
93//#define USE_INSTRUMENTATION 1
94#define USE_INSTRUMENTATION 0
95
96
106bool AskLoadBoardFileName( PCB_EDIT_FRAME* aParent, wxString* aFileName, int aCtl = 0 )
107{
108 std::vector<IO_BASE::IO_FILE_DESC> descriptions;
109
110 for( const auto& plugin : PCB_IO_MGR::PLUGIN_REGISTRY::Instance()->AllPlugins() )
111 {
112 bool isKiCad = plugin.m_type == PCB_IO_MGR::KICAD_SEXP || plugin.m_type == PCB_IO_MGR::LEGACY;
113
114 if( ( aCtl & KICTL_KICAD_ONLY ) && !isKiCad )
115 continue;
116
117 if( ( aCtl & KICTL_NONKICAD_ONLY ) && isKiCad )
118 continue;
119
120 IO_RELEASER<PCB_IO> pi( plugin.m_createFunc() );
121 wxCHECK( pi, false );
122
123 const IO_BASE::IO_FILE_DESC& desc = pi->GetBoardFileDesc();
124
125 if( desc.m_FileExtensions.empty() || !desc.m_CanRead )
126 continue;
127
128 descriptions.emplace_back( desc );
129 }
130
131 wxString fileFiltersStr;
132 std::vector<std::string> allExtensions;
133 std::set<wxString> allWildcardsSet;
134
135 for( const IO_BASE::IO_FILE_DESC& desc : descriptions )
136 {
137 if( !fileFiltersStr.IsEmpty() )
138 fileFiltersStr += wxChar( '|' );
139
140 fileFiltersStr += desc.FileFilter();
141
142 for( const std::string& ext : desc.m_FileExtensions )
143 {
144 allExtensions.emplace_back( ext );
145 allWildcardsSet.insert( wxT( "*." ) + formatWildcardExt( ext ) + wxT( ";" ) );
146 }
147 }
148
149 wxString allWildcardsStr;
150
151 for( const wxString& wildcard : allWildcardsSet )
152 allWildcardsStr << wildcard;
153
154 if( aCtl & KICTL_KICAD_ONLY )
155 {
156 fileFiltersStr = _( "All KiCad Board Files" ) + AddFileExtListToFilter( allExtensions );
157 }
158 else
159 {
160 fileFiltersStr = _( "All supported formats" ) + wxT( "|" ) + allWildcardsStr + wxT( "|" )
161 + fileFiltersStr;
162 }
163
164 wxFileName fileName( *aFileName );
165 wxString path;
166 wxString name;
167
168 if( fileName.FileExists() )
169 {
170 path = fileName.GetPath();
171 name = fileName.GetFullName();
172 }
173 else
174 {
175 path = aParent->GetMruPath();
176
177 if( path.IsEmpty() )
179 // leave name empty
180 }
181
182 bool kicadFormat = ( aCtl & KICTL_KICAD_ONLY );
183
184 wxFileDialog dlg( aParent, kicadFormat ? _( "Open Board File" ) : _( "Import Non KiCad Board File" ),
185 path, name, fileFiltersStr, wxFD_OPEN | wxFD_FILE_MUST_EXIST );
186
187 FILEDLG_IMPORT_NON_KICAD importOptions( aParent->config()->m_System.show_import_issues );
188
189 if( !kicadFormat )
190 dlg.SetCustomizeHook( importOptions );
191
192 if( dlg.ShowModal() == wxID_OK )
193 {
194 *aFileName = dlg.GetPath();
195 aParent->SetMruPath( wxFileName( dlg.GetPath() ).GetPath() );
196
197 if( !kicadFormat )
198 aParent->config()->m_System.show_import_issues = importOptions.GetShowIssues();
199
200 return true;
201 }
202 else
203 {
204 return false;
205 }
206}
207
208
218bool AskSaveBoardFileName( PCB_EDIT_FRAME* aParent, wxString* aFileName, bool* aCreateProject )
219{
220 wxString wildcard = FILEEXT::PcbFileWildcard();
221 wxFileName fn = *aFileName;
222
224
225 wxFileDialog dlg( aParent, _( "Save Board File As" ), fn.GetPath(), fn.GetFullName(), wildcard,
226 wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
227
228// Add a "Create a project" checkbox in standalone mode and one isn't loaded
229 FILEDLG_HOOK_SAVE_PROJECT newProjectHook;
230
231 if( Kiface().IsSingle() && aParent->Prj().IsNullProject() )
232 dlg.SetCustomizeHook( newProjectHook );
233
234 if( dlg.ShowModal() != wxID_OK )
235 return false;
236
237 *aFileName = dlg.GetPath();
238 *aFileName = EnsureFileExtension( *aFileName, FILEEXT::KiCadPcbFileExtension );
239
240 if( newProjectHook.IsAttachedToDialog() )
241 *aCreateProject = newProjectHook.GetCreateNewProject();
242 else if( !aParent->Prj().IsNullProject() )
243 *aCreateProject = true;
244
245 return true;
246}
247
248
249void PCB_EDIT_FRAME::OnFileHistory( wxCommandEvent& event )
250{
251 wxString filename = GetFileFromHistory( event.GetId(), _( "Printed circuit board" ) );
252
253 if( !filename.IsEmpty() )
254 {
255 if( !wxFileName::IsFileReadable( filename ) )
256 {
257 if( !AskLoadBoardFileName( this, &filename, KICTL_KICAD_ONLY ) )
258 return;
259 }
260
261 OpenProjectFiles( std::vector<wxString>( 1, filename ), KICTL_KICAD_ONLY );
262 }
263}
264
265
266void PCB_EDIT_FRAME::OnClearFileHistory( wxCommandEvent& aEvent )
267{
269}
270
271
273{
274 // Only standalone mode can directly load a new document
275 if( !Kiface().IsSingle() )
276 return false;
277
278 int open_ctl = KICTL_KICAD_ONLY;
279 wxString fileName = m_frame->Prj().AbsolutePath( m_frame->GetBoard()->GetFileName() );
280
281 if( AskLoadBoardFileName( m_frame, &fileName, open_ctl ) )
282 m_frame->OpenProjectFiles( std::vector<wxString>( 1, fileName ), open_ctl );
283
284 return 0;
285}
286
287
289{
290 // Note: we explicitly allow this even if not in standalone mode for now, even though it is dangerous.
291 int open_ctl = KICTL_NONKICAD_ONLY;
292 wxString fileName; // = Prj().AbsolutePath( GetBoard()->GetFileName() );
293
294 if( AskLoadBoardFileName( m_frame, &fileName, open_ctl ) )
295 m_frame->OpenProjectFiles( std::vector<wxString>( 1, fileName ), open_ctl );
296
297 return 0;
298}
299
300
302{
303 wxFileName fn = m_frame->Prj().AbsolutePath( m_frame->GetBoard()->GetFileName() );
304
305 if( !IsOK( m_frame, wxString::Format( _( "Revert '%s' to last version saved?" ), fn.GetFullPath() ) ) )
306 return false;
307
308 m_frame->GetScreen()->SetContentModified( false ); // do not prompt the user for changes
309
310 m_frame->ReleaseFile();
311
312 m_frame->OpenProjectFiles( std::vector<wxString>( 1, fn.GetFullPath() ), KICTL_REVERT );
313
314 return 0;
315}
316
317
319{
320 // Only standalone mode can directly load a new document
321 if( !Kiface().IsSingle() )
322 return false;
323
324 if( m_frame->IsContentModified() )
325 {
326 wxFileName fileName = m_frame->GetBoard()->GetFileName();
327 wxString saveMsg = _( "Current board will be closed, save changes to '%s' before "
328 "continuing?" );
329
330 if( !HandleUnsavedChanges( m_frame, wxString::Format( saveMsg, fileName.GetFullName() ),
331 [&]()->bool
332 {
333 return m_frame->SaveBoard();
334 } ) )
335 {
336 return false;
337 }
338 }
339 else if( !m_frame->GetBoard()->IsEmpty() )
340 {
341 if( !IsOK( m_frame, _( "Current Board will be closed. Continue?" ) ) )
342 return false;
343 }
344
345 m_frame->SaveProjectLocalSettings();
346
347 m_frame->GetBoard()->ClearProject();
348 m_frame->GetSettingsManager()->UnloadProject( &m_frame->Prj() );
349
350 if( !m_frame->Clear_Pcb( false ) )
351 return false;
352
353 m_frame->LoadProjectSettings();
354 m_frame->LoadDrawingSheet();
355
356 m_frame->OnBoardLoaded();
357 m_frame->OnModify();
358
359 return 0;
360}
361
362
363bool PCB_EDIT_FRAME::SaveBoard( bool aSaveAs, bool aSaveCopy )
364{
365 if( !aSaveAs )
366 {
367 if( !GetBoard()->GetFileName().IsEmpty() )
368 {
369 if( SavePcbFile( Prj().AbsolutePath( GetBoard()->GetFileName() ) ) )
370 {
371 m_autoSaveRequired = false;
372 return true;
373 }
374
375 return false;
376 }
377 }
378
379 wxString orig_name;
380
381 wxFileName::SplitPath( GetBoard()->GetFileName(), nullptr, nullptr, &orig_name, nullptr );
382
383 if( orig_name.IsEmpty() )
384 orig_name = NAMELESS_PROJECT;
385
386 wxFileName savePath( Prj().GetProjectFullName() );
387
388 if( !savePath.IsOk() || !savePath.IsDirWritable() )
389 {
390 savePath = GetMruPath();
391
392 if( !savePath.IsOk() || !savePath.IsDirWritable() )
394 }
395
396 wxFileName fn( savePath.GetPath(), orig_name, FILEEXT::KiCadPcbFileExtension );
397 wxString filename = fn.GetFullPath();
398 bool createProject = false;
399 bool success = false;
400
401 if( AskSaveBoardFileName( this, &filename, &createProject ) )
402 {
403 if( aSaveCopy )
404 {
405 success = SavePcbCopy( EnsureFileExtension( filename, FILEEXT::KiCadPcbFileExtension ), createProject );
406 }
407 else
408 {
409 success = SavePcbFile( filename, aSaveAs, createProject );
410
411 if( success )
412 m_autoSaveRequired = false;
413 }
414 }
415
416 return success;
417}
418
419
420int PCB_EDIT_FRAME::inferLegacyEdgeClearance( BOARD* aBoard, bool aShowUserMsg )
421{
422 PCB_LAYER_COLLECTOR collector;
423
424 collector.SetLayerId( Edge_Cuts );
425 collector.Collect( aBoard, GENERAL_COLLECTOR::AllBoardItems );
426
427 int edgeWidth = -1;
428 bool mixed = false;
429
430 for( int i = 0; i < collector.GetCount(); i++ )
431 {
432 if( collector[i]->Type() == PCB_SHAPE_T )
433 {
434 int itemWidth = static_cast<PCB_SHAPE*>( collector[i] )->GetWidth();
435
436 if( edgeWidth != -1 && edgeWidth != itemWidth )
437 {
438 mixed = true;
439 edgeWidth = std::max( edgeWidth, itemWidth );
440 }
441 else
442 {
443 edgeWidth = itemWidth;
444 }
445 }
446 }
447
448 if( mixed && aShowUserMsg )
449 {
450 // If they had different widths then we can't ensure that fills will be the same.
451 DisplayInfoMessage( this,
452 _( "If the zones on this board are refilled the Copper Edge "
453 "Clearance setting will be used (see Board Setup > Design "
454 "Rules > Constraints).\n This may result in different fills "
455 "from previous KiCad versions which used the line thicknesses "
456 "of the board boundary on the Edge Cuts layer." ) );
457 }
458
459 return std::max( 0, edgeWidth / 2 );
460}
461
462
463bool PCB_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, int aCtl )
464{
465 // This is for python:
466 if( aFileSet.size() != 1 )
467 {
468 DisplayError( this, wxString::Format( "Pcbnew:%s() takes a single filename", __func__ ) );
469 return false;
470 }
471
472 wxString fullFileName( aFileSet[0] );
473 wxFileName wx_filename( fullFileName );
474 Kiway().LocalHistory().Init( wx_filename.GetPath() );
475 wxString msg;
476
477 if( Kiface().IsSingle() )
479
480 // We insist on caller sending us an absolute path, if it does not, we say it's a bug.
481 wxASSERT_MSG( wx_filename.IsAbsolute(), wxT( "Path is not absolute!" ) );
482
483 std::unique_ptr<LOCKFILE> lock = std::make_unique<LOCKFILE>( fullFileName );
484
485 if( !lock->Valid() && lock->IsLockedByMe() )
486 {
487 // If we cannot acquire the lock but we appear to be the one who locked it, check to
488 // see if there is another KiCad instance running. If not, then we can override the
489 // lock. This could happen if KiCad crashed or was interrupted.
490
491 if( !Pgm().SingleInstance()->IsAnotherRunning() )
492 lock->OverrideLock();
493 }
494
495 if( !lock->Valid() )
496 {
497 msg.Printf( _( "PCB '%s' is already open by '%s' at '%s'." ),
498 wx_filename.GetFullName(),
499 lock->GetUsername(),
500 lock->GetHostname() );
501
502 if( !AskOverrideLock( this, msg ) )
503 return false;
504
505 lock->OverrideLock();
506 }
507
508 if( IsContentModified() )
509 {
510 if( !HandleUnsavedChanges( this, _( "The current PCB has been modified. Save changes?" ),
511 [&]() -> bool
512 {
513 return SavePcbFile( GetBoard()->GetFileName() );
514 } ) )
515 {
516 return false;
517 }
518 }
519
520 wxFileName pro = fullFileName;
521 pro.SetExt( FILEEXT::ProjectFileExtension );
522
523 bool is_new = !wxFileName::IsFileReadable( fullFileName );
524
525 wxString previousBoardFileName = GetBoard() ? GetBoard()->GetFileName() : wxString();
526
527 // If its a non-existent PCB and caller thinks it exists
528 if( is_new && !( aCtl & KICTL_CREATE ) )
529 {
530 // notify user that fullFileName does not exist, ask if user wants to create it.
531 msg.Printf( _( "PCB '%s' does not exist. Do you wish to create it?" ), fullFileName );
532
533 if( !IsOK( this, msg ) )
534 return false;
535 }
536
537 // Get rid of any existing warnings about the old board
538 GetInfoBar()->Dismiss();
539
540 if( KISTATUSBAR* statusBar = dynamic_cast<KISTATUSBAR*>( GetStatusBar() ) )
541 statusBar->ClearLoadWarningMessages();
542
543 WX_PROGRESS_REPORTER progressReporter( this, is_new ? _( "Create PCB" ) : _( "Load PCB" ), 1,
544 PR_CAN_ABORT );
545 WX_STRING_REPORTER loadReporter;
546 LOAD_INFO_REPORTER_SCOPE loadReporterScope( &loadReporter );
547
548 // No save prompt (we already prompted above), and only reset to a new blank board if new
549 Clear_Pcb( false, !is_new );
550
552
553 if( !is_new )
554 pluginType = PCB_IO_MGR::FindPluginTypeFromBoardPath( fullFileName, aCtl );
555
556 if( pluginType == PCB_IO_MGR::FILE_TYPE_NONE )
557 {
558 progressReporter.Hide();
559 DisplayErrorMessage( this, _( "File format is not supported" ), wxEmptyString );
560 return false;
561 }
562
563 bool converted = pluginType != PCB_IO_MGR::LEGACY && pluginType != PCB_IO_MGR::KICAD_SEXP;
564
565 // Loading a project should only be done under carefully considered circumstances.
566
567 // The calling code should know not to ask me here to change projects unless
568 // it knows what consequences that will have on other KIFACEs running and using
569 // this same PROJECT. It can be very harmful if that calling code is stupid.
571 bool setProject;
572
573 if( Kiface().IsSingle() || !( aCtl & KICTL_NONKICAD_ONLY ) )
574 setProject = pro.GetFullPath() != mgr->Prj().GetProjectFullName();
575 else
576 setProject = Prj().GetProjectFullName().IsEmpty();
577
578 if( setProject )
579 {
580 // calls SaveProject
582
584 mgr->UnloadProject( &mgr->Prj() );
585
586 mgr->LoadProject( pro.GetFullPath() );
587
588 // Do not allow saving a project if one doesn't exist. This normally happens if we are
589 // opening a board that has been moved from its project folder.
590 // For converted projects, we don't want to set the read-only flag because we want a
591 // project to be saved for the new file in case things like netclasses got migrated.
592 Prj().SetReadOnly( !pro.Exists() && !converted );
593 }
594
595 // Clear the cache footprint list which may be project specific
596 GFootprintList.Clear();
597
598 if( is_new )
599 {
600 // Link the existing blank board to the new project
601 GetBoard()->SetProject( &Prj() );
602
603 GetBoard()->SetFileName( fullFileName );
604
605 OnModify();
606 }
607 else
608 {
609 BOARD* loadedBoard = nullptr; // it will be set to non-NULL if loaded OK
611
612 if( LAYER_MAPPABLE_PLUGIN* mappable_pi = dynamic_cast<LAYER_MAPPABLE_PLUGIN*>( pi.get() ) )
613 {
614 mappable_pi->RegisterCallback( std::bind( DIALOG_MAP_LAYERS::RunModal,
615 this, std::placeholders::_1 ) );
616 }
617
618 if( PROJECT_CHOOSER_PLUGIN* chooser_pi = dynamic_cast<PROJECT_CHOOSER_PLUGIN*>( pi.get() ) )
619 {
620 chooser_pi->RegisterCallback( std::bind( DIALOG_IMPORT_CHOOSE_PROJECT::RunModal,
621 this,
622 std::placeholders::_1 ) );
623 }
624
625 bool failedLoad = false;
626
627 try
628 {
629 if( pi == nullptr )
630 {
631 // There was no plugin found, e.g. due to invalid file extension, file header,...
632 THROW_IO_ERROR( _( "File format is not supported" ) );
633 }
634
635 std::map<std::string, UTF8> props;
636
638 props.insert( m_importProperties->begin(), m_importProperties->end() );
639
640 // PCB_IO_EAGLE can use this info to center the BOARD, but it does not yet.
641 props["page_width"] = std::to_string( GetPageSizeIU().x );
642 props["page_height"] = std::to_string( GetPageSizeIU().y );
643
644 pi->SetQueryUserCallback(
645 [&]( wxString aTitle, int aIcon, wxString aMessage, wxString aAction ) -> bool
646 {
647 KIDIALOG dlg( nullptr, aMessage, aTitle, wxOK | wxCANCEL | aIcon );
648
649 if( !aAction.IsEmpty() )
650 dlg.SetOKLabel( aAction );
651
652 dlg.DoNotShowCheckbox( aMessage, 0 );
653
654 return dlg.ShowModal() == wxID_OK;
655 } );
656
657#if USE_INSTRUMENTATION
658 // measure the time to load a BOARD.
659 int64_t startTime = GetRunningMicroSecs();
660#endif
661 // Use loadReporter for import issues - they will be shown in the status bar
662 // warning icon instead of a modal dialog
663 if( config()->m_System.show_import_issues )
664 pi->SetReporter( &loadReporter );
665 else
666 pi->SetReporter( &NULL_REPORTER::GetInstance() );
667
668 pi->SetProgressReporter( &progressReporter );
669 loadedBoard = pi->LoadBoard( fullFileName, nullptr, &props, &Prj() );
670
671#if USE_INSTRUMENTATION
672 int64_t stopTime = GetRunningMicroSecs();
673 printf( "PCB_IO::Load(): %u usecs\n", stopTime - startTime );
674#endif
675 }
676 catch( const FUTURE_FORMAT_ERROR& ffe )
677 {
678 msg.Printf( _( "Error loading PCB '%s'." ), fullFileName );
679 progressReporter.Hide();
680 DisplayErrorMessage( this, msg, ffe.Problem() );
681
682 failedLoad = true;
683 }
684 catch( const IO_ERROR& ioe )
685 {
686 if( ioe.Problem() != wxT( "CANCEL" ) )
687 {
688 msg.Printf( _( "Error loading PCB '%s'." ), fullFileName );
689 progressReporter.Hide();
690 DisplayErrorMessage( this, msg, ioe.What() );
691 }
692
693 failedLoad = true;
694 }
695 catch( const std::bad_alloc& )
696 {
697 msg.Printf( _( "Memory exhausted loading PCB '%s'" ), fullFileName );
698 progressReporter.Hide();
699 DisplayErrorMessage( this, msg, wxEmptyString );
700
701 failedLoad = true;
702 }
703
704 if( failedLoad || !loadedBoard )
705 {
706 // We didn't create a new blank board above, so do that now
707 Clear_Pcb( false );
708
709 // Show any messages collected before the failure
710 if( KISTATUSBAR* statusBar = dynamic_cast<KISTATUSBAR*>( GetStatusBar() ) )
711 statusBar->SetLoadWarningMessages( loadReporter.GetMessages() );
712
713 return false;
714 }
715
716 // This fixes a focus issue after the progress reporter is done on GTK. It shouldn't
717 // cause any issues on macOS and Windows. If it does, it will have to be conditionally
718 // compiled.
719 Raise();
720
721 // Skip (possibly expensive) connectivity build here; we build it below after load
722 SetBoard( loadedBoard, false, &progressReporter );
723
724 if( GFootprintList.GetCount() == 0 )
725 GFootprintList.ReadCacheFromFile( Prj().GetProjectPath() + wxT( "fp-info-cache" ) );
726
727 if( loadedBoard->m_LegacyDesignSettingsLoaded )
728 {
729 Prj().SetReadOnly( false );
730
731 // Before we had a copper edge clearance setting, the edge line widths could be used
732 // as a kludge to control them. So if there's no setting then infer it from the
733 // edge widths.
734 if( !loadedBoard->m_LegacyCopperEdgeClearanceLoaded )
735 {
736 // Do not show the inferred edge clearance warning dialog when loading third
737 // party boards. For some reason the dialog completely hangs all of KiCad and
738 // the imported board cannot be saved.
739 int edgeClearance = inferLegacyEdgeClearance( loadedBoard, !converted );
740 loadedBoard->GetDesignSettings().m_CopperEdgeClearance = edgeClearance;
741 }
742
743 // On save; design settings will be removed from the board
744 loadedBoard->SetModified();
745 }
746
747 // Move legacy view settings to local project settings
748 if( !loadedBoard->m_LegacyVisibleLayers.test( Rescue ) )
749 {
751 loadedBoard->SetModified();
752 }
753
755 {
757 loadedBoard->SetModified();
758 }
759
760 if( !loadedBoard->SynchronizeComponentClasses( std::unordered_set<wxString>() ) )
761 {
762 m_infoBar->RemoveAllButtons();
763 m_infoBar->AddCloseButton();
764 m_infoBar->ShowMessage( _( "Could not load component class assignment rules" ),
765 wxICON_WARNING, WX_INFOBAR::MESSAGE_TYPE::GENERIC );
766 }
767
768 // we should not ask PCB_IOs to do these items:
769 loadedBoard->BuildListOfNets();
770 m_toolManager->RunAction( PCB_ACTIONS::repairBoard, true);
772
773 if( loadedBoard->IsModified() )
774 OnModify();
775 else
776 GetScreen()->SetContentModified( false );
777
778 if( ( pluginType == PCB_IO_MGR::LEGACY )
779 || ( pluginType == PCB_IO_MGR::KICAD_SEXP
781 && loadedBoard->GetGenerator().Lower() != wxT( "gerbview" ) ) )
782 {
783 m_infoBar->RemoveAllButtons();
784 m_infoBar->AddCloseButton();
785 m_infoBar->ShowMessage( _( "This file was created by an older version of KiCad. "
786 "It will be converted to the new format when saved." ),
788 }
789
790 // TODO(JE) library tables -- I think this functionality should be deleted
791#if 0
792
793 // Import footprints into a project-specific library
794 //==================================================
795 // TODO: This should be refactored out of here into somewhere specific to the Project Import
796 // E.g. KICAD_MANAGER_FRAME::ImportNonKiCadProject
797 if( aCtl & KICTL_IMPORT_LIB )
798 {
799 wxFileName loadedBoardFn( fullFileName );
800 wxString libNickName = loadedBoardFn.GetName();
801
802 // Extract a footprint library from the design and add it to the fp-lib-table
803 // The footprints are saved in a new .pretty library.
804 // If this library already exists, all previous footprints will be deleted
805 std::vector<FOOTPRINT*> loadedFootprints = pi->GetImportedCachedLibraryFootprints();
806 wxString newLibPath = CreateNewProjectLibrary( _( "New Footprint Library" ),
807 libNickName );
808
809 // Only create the new library if CreateNewLibrary succeeded (note that this fails if
810 // the library already exists and the user aborts after seeing the warning message
811 // which prompts the user to continue with overwrite or abort)
812 if( newLibPath.Length() > 0 )
813 {
815
816 for( FOOTPRINT* footprint : loadedFootprints )
817 {
818 try
819 {
820 if( !footprint->GetFPID().GetLibItemName().empty() ) // Handle old boards.
821 {
822 footprint->SetReference( "REF**" );
823 piSexpr->FootprintSave( newLibPath, footprint );
824 delete footprint;
825 }
826 }
827 catch( const IO_ERROR& ioe )
828 {
829 wxLogError( _( "Error saving footprint %s to project specific library." )
830 + wxS( "\n%s" ),
831 footprint->GetFPID().GetUniStringLibItemName(),
832 ioe.What() );
833 }
834 }
835
836 FP_LIB_TABLE* prjlibtable = PROJECT_PCB::PcbFootprintLibs( &Prj() );
837 const wxString& project_env = PROJECT_VAR_NAME;
838 wxString rel_path, env_path;
839
840 wxASSERT_MSG( wxGetEnv( project_env, &env_path ),
841 wxT( "There is no project variable?" ) );
842
843 wxString result( newLibPath );
844
845 if( result.Replace( env_path, wxT( "$(" ) + project_env + wxT( ")" ) ) )
846 rel_path = result;
847
848 FP_LIB_TABLE_ROW* row = new FP_LIB_TABLE_ROW( libNickName, rel_path,
849 wxT( "KiCad" ), wxEmptyString );
850 prjlibtable->InsertRow( row );
851
852 wxString tblName = Prj().FootprintLibTblName();
853
854 try
855 {
856 PROJECT_PCB::PcbFootprintLibs( &Prj() )->Save( tblName );
857 }
858 catch( const IO_ERROR& ioe )
859 {
860 wxLogError( _( "Error saving project specific footprint library table." )
861 + wxS( "\n%s" ),
862 ioe.What() );
863 }
864
865 // Update footprint LIB_IDs to point to the just imported library
866 for( FOOTPRINT* footprint : GetBoard()->Footprints() )
867 {
868 LIB_ID libId = footprint->GetFPID();
869
870 if( libId.GetLibItemName().empty() )
871 continue;
872
873 libId.SetLibNickname( libNickName );
874 footprint->SetFPID( libId );
875 }
876 }
877 }
878#endif
879 }
880
881 {
882 wxString fname;
883
884 if( !previousBoardFileName.IsEmpty() && ( aCtl & KICTL_NONKICAD_ONLY ) && !setProject )
885 {
886 fname = previousBoardFileName;
887 }
888 else
889 {
890 wxFileName fn;
891
892 fn.SetPath( Prj().GetProjectPath() );
893 fn.SetName( Prj().GetProjectName() );
895
896 fname = fn.GetFullPath();
897
898 fname.Replace( WIN_STRING_DIR_SEP, UNIX_STRING_DIR_SEP );
899 }
900
901 GetBoard()->SetFileName( fname );
902 }
903
904 // Lock the file newly opened:
905 m_file_checker.reset( lock.release() );
906
907 if( !converted )
908 UpdateFileHistory( GetBoard()->GetFileName() );
909
910 std::vector<ZONE*> toFill;
911
912 // Rebuild list of nets (full ratsnest rebuild)
913 GetBoard()->BuildConnectivity( &progressReporter );
914
915 // Load project settings after setting up board; some of them depend on the nets list
918
919 // Resolve DRC exclusions after project settings are loaded
920 ResolveDRCExclusions( true );
921
922 // Initialise caches used by component classes
924
925 // Initialise time domain tuning caches
927
928 // Syncs the UI (appearance panel, etc) with the loaded board and project
930
931 // Refresh the 3D view, if any
932 EDA_3D_VIEWER_FRAME* draw3DFrame = Get3DViewerFrame();
933
934 if( draw3DFrame )
935 draw3DFrame->NewDisplay();
936#if 0 && defined(DEBUG)
937 // Output the board object tree to stdout, but please run from command prompt:
938 GetBoard()->Show( 0, std::cout );
939#endif
940
941 // from EDA_APPL which was first loaded BOARD only:
942 {
943 /* For an obscure reason the focus is lost after loading a board file
944 * when starting up the process.
945 * (seems due to the recreation of the layer manager after loading the file)
946 * Give focus to main window and Drawpanel
947 * must be done for these 2 windows (for an obscure reason ...)
948 * Linux specific
949 * This is more a workaround than a fix.
950 */
951 SetFocus();
952 GetCanvas()->SetFocus();
953 }
954
955 if( !setProject )
956 {
957 // If we didn't reload the project, we still need to call ProjectChanged() to ensure
958 // frame-specific initialization happens (like registering the autosave saver).
959 // When running under the project manager, KIWAY::ProjectChanged() was called before
960 // this frame existed, so we need to call our own ProjectChanged() now.
962 }
963
964 if( KISTATUSBAR* statusBar = dynamic_cast<KISTATUSBAR*>( GetStatusBar() ) )
965 statusBar->SetLoadWarningMessages( loadReporter.GetMessages() );
966
967 return true;
968}
969
970
971bool PCB_EDIT_FRAME::SavePcbFile( const wxString& aFileName, bool addToHistory,
972 bool aChangeProject )
973{
974 // please, keep it simple. prompting goes elsewhere.
975 wxFileName pcbFileName = aFileName;
976
977 if( pcbFileName.GetExt() == FILEEXT::LegacyPcbFileExtension )
978 pcbFileName.SetExt( FILEEXT::KiCadPcbFileExtension );
979
980 // Write through symlinks, don't replace them
982
983 if( !IsWritable( pcbFileName ) )
984 {
985 wxString msg = wxString::Format( _( "Insufficient permissions to write file '%s'." ),
986 pcbFileName.GetFullPath() );
987
988 DisplayError( this, msg );
989 return false;
990 }
991
992 // TODO: these will break if we ever go multi-board
993 wxFileName projectFile( pcbFileName );
994 wxFileName rulesFile( pcbFileName );
995 wxString msg;
996
997 projectFile.SetExt( FILEEXT::ProjectFileExtension );
998 rulesFile.SetExt( FILEEXT::DesignRulesFileExtension );
999
1000 if( projectFile.FileExists() )
1001 {
1003 }
1004 else if( aChangeProject )
1005 {
1006 Prj().SetReadOnly( false );
1007 GetSettingsManager()->SaveProjectAs( projectFile.GetFullPath() );
1008 }
1009
1010 wxFileName currentRules( GetDesignRulesPath() );
1011
1012 if( currentRules.FileExists() && !rulesFile.FileExists() && aChangeProject )
1013 KiCopyFile( currentRules.GetFullPath(), rulesFile.GetFullPath(), msg );
1014
1015 if( !msg.IsEmpty() )
1016 {
1017 DisplayError( this, wxString::Format( _( "Error saving custom rules file '%s'." ),
1018 rulesFile.GetFullPath() ) );
1019 }
1020
1021 if( projectFile.FileExists() )
1022 {
1023 // Save various DRC parameters, such as violation severities (which may have been
1024 // edited via the DRC dialog as well as the Board Setup dialog), DRC exclusions, etc.
1026
1029 }
1030
1031 wxString upperTxt;
1032 wxString lowerTxt;
1033
1034 // On Windows, ensure the target file is writeable by clearing problematic attributes like
1035 // hidden or read-only. This can happen when files are synced via cloud services.
1036 if( pcbFileName.FileExists() )
1037 KIPLATFORM::IO::MakeWriteable( pcbFileName.GetFullPath() );
1038
1039 try
1040 {
1042
1043 pi->SaveBoard( pcbFileName.GetFullPath(), GetBoard(), nullptr );
1044 }
1045 catch( const IO_ERROR& ioe )
1046 {
1047 DisplayError( this, wxString::Format( _( "Error saving board file '%s'.\n%s" ),
1048 pcbFileName.GetFullPath(),
1049 ioe.What() ) );
1050 return false;
1051 }
1052
1053 if( !Kiface().IsSingle() )
1054 {
1055 WX_STRING_REPORTER backupReporter;
1056
1057 if( !GetSettingsManager()->TriggerBackupIfNeeded( backupReporter ) )
1058 {
1059 upperTxt = backupReporter.GetMessages();
1060 SetStatusText( upperTxt, 1 );
1061 }
1062 }
1063
1064 GetBoard()->SetFileName( pcbFileName.GetFullPath() );
1065
1066 // Update the lock in case it was a Save As
1067 LockFile( pcbFileName.GetFullPath() );
1068
1069 // Put the saved file in File History if requested
1070 if( addToHistory )
1071 UpdateFileHistory( GetBoard()->GetFileName() );
1072
1073 lowerTxt.Printf( _( "File '%s' saved." ), pcbFileName.GetFullPath() );
1074
1075 SetStatusText( lowerTxt, 0 );
1076
1077 // Get rid of the old version conversion warning, or any other dismissable warning :)
1078 if( m_infoBar->GetMessageType() == WX_INFOBAR::MESSAGE_TYPE::OUTDATED_SAVE )
1079 m_infoBar->Dismiss();
1080
1081 if( m_infoBar->IsShownOnScreen() && m_infoBar->HasCloseButton() )
1082 m_infoBar->Dismiss();
1083
1084 GetScreen()->SetContentModified( false );
1085 UpdateTitle();
1087
1088 // Capture entire project state for PCB save events.
1089 Kiway().LocalHistory().CommitFullProjectSnapshot( pcbFileName.GetPath(), wxS( "PCB Save" ) );
1090 Kiway().LocalHistory().TagSave( pcbFileName.GetPath(), wxS( "pcb" ) );
1091
1092 if( m_autoSaveTimer )
1093 m_autoSaveTimer->Stop();
1094
1095 m_autoSavePending = false;
1096 m_autoSaveRequired = false;
1097 return true;
1098}
1099
1100
1101bool PCB_EDIT_FRAME::SavePcbCopy( const wxString& aFileName, bool aCreateProject, bool aHeadless )
1102{
1103 wxFileName pcbFileName( aFileName );
1104
1105 if( !IsWritable( pcbFileName ) )
1106 {
1107 if( !aHeadless )
1108 {
1109 DisplayError( this, wxString::Format( _( "Insufficient permissions to write file '%s'." ),
1110 pcbFileName.GetFullPath() ) );
1111 }
1112 return false;
1113 }
1114
1115 // Save various DRC parameters, such as violation severities (which may have been
1116 // edited via the DRC dialog as well as the Board Setup dialog), DRC exclusions, etc.
1118
1120
1121 // On Windows, ensure the target file is writeable by clearing problematic attributes like
1122 // hidden or read-only. This can happen when files are synced via cloud services.
1123 if( pcbFileName.FileExists() )
1124 KIPLATFORM::IO::MakeWriteable( pcbFileName.GetFullPath() );
1125
1126 try
1127 {
1129
1130 wxASSERT( pcbFileName.IsAbsolute() );
1131
1132 pi->SaveBoard( pcbFileName.GetFullPath(), GetBoard(), nullptr );
1133 }
1134 catch( const IO_ERROR& ioe )
1135 {
1136 if( !aHeadless )
1137 {
1138 DisplayError( this, wxString::Format( _( "Error saving board file '%s'.\n%s" ),
1139 pcbFileName.GetFullPath(),
1140 ioe.What() ) );
1141 }
1142
1143 return false;
1144 }
1145
1146 wxFileName projectFile( pcbFileName );
1147 wxFileName rulesFile( pcbFileName );
1148 wxString msg;
1149
1150 projectFile.SetExt( FILEEXT::ProjectFileExtension );
1151 rulesFile.SetExt( FILEEXT::DesignRulesFileExtension );
1152
1153 if( aCreateProject && !projectFile.FileExists() )
1154 GetSettingsManager()->SaveProjectCopy( projectFile.GetFullPath() );
1155
1156 wxFileName currentRules( GetDesignRulesPath() );
1157
1158 if( aCreateProject && currentRules.FileExists() && !rulesFile.FileExists() )
1159 KiCopyFile( currentRules.GetFullPath(), rulesFile.GetFullPath(), msg );
1160
1161 if( !msg.IsEmpty() && !aHeadless )
1162 {
1163 DisplayError( this, wxString::Format( _( "Error saving custom rules file '%s'." ),
1164 rulesFile.GetFullPath() ) );
1165 }
1166
1167 return true;
1168}
1169
1170
1171bool PCB_EDIT_FRAME::importFile( const wxString& aFileName, int aFileType,
1172 const std::map<std::string, UTF8>* aProperties )
1173{
1174 NULLER raiiNuller( (void*&) m_importProperties );
1175
1176 m_importProperties = aProperties;
1177
1178 switch( (PCB_IO_MGR::PCB_FILE_T) aFileType )
1179 {
1181 case PCB_IO_MGR::EAGLE:
1184 return OpenProjectFiles( std::vector<wxString>( 1, aFileName ), KICTL_NONKICAD_ONLY | KICTL_IMPORT_LIB );
1185
1190 return OpenProjectFiles( std::vector<wxString>( 1, aFileName ), KICTL_NONKICAD_ONLY );
1191
1192 default:
1193 return false;
1194 }
1195}
1196
1197
1199{
1201
1202 dlg.ShowModal();
1203
1204 return 0;
1205}
1206
1207
1209{
1211
1212 if( dlg.ShowModal() != wxID_OK )
1213 return 0;
1214
1216
1218 job.m_filename = m_frame->GetBoard()->GetFileName();
1220
1221 job.m_precision = dlg.GetPrecision();
1224
1225 WX_PROGRESS_REPORTER progressReporter( m_frame, _( "Generate ODB++ Files" ), 3, PR_CAN_ABORT );
1226 WX_STRING_REPORTER reporter;
1227
1228 DIALOG_EXPORT_ODBPP::GenerateODBPPFiles( job, m_frame->GetBoard(), m_frame, &progressReporter, &reporter );
1229
1230 if( reporter.HasMessage() )
1231 DisplayError( m_frame, reporter.GetMessages() );
1232
1233 return 0;
1234}
const char * name
KIFACE_BASE & Kiface()
Global KIFACE_BASE "get" accessor.
void SetContentModified(bool aModified=true)
Definition base_screen.h:59
int GenerateODBPPFiles(const TOOL_EVENT &aEvent)
int New(const TOOL_EVENT &aEvent)
int Revert(const TOOL_EVENT &aEvent)
int GenIPC2581File(const TOOL_EVENT &aEvent)
int Open(const TOOL_EVENT &aEvent)
int OpenNonKicadBoard(const TOOL_EVENT &aEvent)
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:322
bool m_LegacyDesignSettingsLoaded
True if the legacy board design settings were loaded from a file.
Definition board.h:436
GAL_SET m_LegacyVisibleItems
Definition board.h:433
LENGTH_DELAY_CALCULATION * GetLengthCalculation() const
Returns the track length calculator.
Definition board.h:1402
void BuildListOfNets()
Definition board.h:959
void SetFileName(const wxString &aFileName)
Definition board.h:357
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:192
void SynchronizeNetsAndNetClasses(bool aResetTrackAndViaSizes)
Copy NETCLASS info to each NET, based on NET membership in a NETCLASS.
Definition board.cpp:2664
LSET m_LegacyVisibleLayers
Visibility settings stored in board prior to 6.0, only used for loading legacy files.
Definition board.h:432
void SetProject(PROJECT *aProject, bool aReferenceOnly=false)
Link a board to a given project.
Definition board.cpp:202
const wxString & GetFileName() const
Definition board.h:359
int GetFileFormatVersionAtLoad() const
Definition board.h:456
const wxString & GetGenerator() const
Adds an item to the container.
Definition board.h:459
void ClearProject()
Definition board.cpp:240
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition board.cpp:1082
void SynchronizeProperties()
Copy the current project's text variables into the boards property cache.
Definition board.cpp:2478
COMPONENT_CLASS_MANAGER & GetComponentClassManager()
Gets the component class manager.
Definition board.h:1407
bool SynchronizeComponentClasses(const std::unordered_set< wxString > &aNewSheetPaths) const
Copy component class / component class generator information from the project settings.
Definition board.cpp:2694
bool m_LegacyCopperEdgeClearanceLoaded
Definition board.h:437
int GetCount() const
Return the number of objects in the list.
Definition collector.h:83
void RebuildRequiredCaches(FOOTPRINT *aFootprint=nullptr) const
Rebuilds any caches that may be required by custom assignment rules.
static void GenerateODBPPFiles(const JOB_EXPORT_PCB_ODB &aJob, BOARD *aBoard, PCB_EDIT_FRAME *aParentFrame=nullptr, PROGRESS_REPORTER *aProgressReporter=nullptr, REPORTER *aErrorReporter=nullptr)
wxString GetOutputPath() const
wxString GetUnitsString() const
static std::vector< IMPORT_PROJECT_DESC > RunModal(wxWindow *aParent, const std::vector< IMPORT_PROJECT_DESC > &aProjectDesc)
Create and show a dialog (modal) and returns the data from it after completion.
static std::map< wxString, PCB_LAYER_ID > RunModal(wxWindow *aParent, const std::vector< INPUT_LAYER_DESC > &aLayerDesc)
Create and show a dialog (modal) and returns the data from it after completion.
int ShowModal() override
Create and handle a window for the 3d viewer connected to a Kiway and a pcbboard.
void NewDisplay(bool aForceImmediateRedraw=false)
Reload and refresh (rebuild) the 3D scene.
virtual APP_SETTINGS_BASE * config() const
Return the settings object used in SaveSettings(), and is overloaded in KICAD_MANAGER_FRAME.
WX_INFOBAR * m_infoBar
wxTimer * m_autoSaveTimer
void UpdateFileHistory(const wxString &FullFileName, FILE_HISTORY *aFileHistory=nullptr)
Update the list of recently opened files.
wxString GetMruPath() const
bool IsWritable(const wxFileName &aFileName, bool aVerbose=true)
Check if aFileName can be written.
virtual void ClearFileHistory()
Remove all files from the file history.
wxString GetFileFromHistory(int cmdId, const wxString &type, FILE_HISTORY *aFileHistory=nullptr)
Fetch the file name from the file history list.
void SetMruPath(const wxString &aPath)
WX_INFOBAR * GetInfoBar()
std::unique_ptr< LOCKFILE > m_file_checker
bool LockFile(const wxString &aFileName)
Mark a schematic file as being in use.
void SetFocus() override
void SetModified()
Definition eda_item.cpp:100
bool IsModified() const
Definition eda_item.h:123
bool GetCreateNewProject() const
Gets the selected state of the copy subsheets option.
static const std::vector< KICAD_T > AllBoardItems
A scan list for all editable board items.
Definition collectors.h:41
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
virtual const wxString What() const
A composite of Problem() and Where()
virtual const wxString Problem() const
what was the problem?
ODB_COMPRESSION m_compressionMode
void SetConfiguredOutputPath(const wxString &aPath)
Sets the configured output path for the job, this path is always saved to file.
Definition job.cpp:157
Helper class to create more flexible dialogs, including 'do not show again' checkbox handling.
Definition kidialog.h:42
void DoNotShowCheckbox(wxString file, int line)
Shows the 'do not show again' checkbox.
Definition kidialog.cpp:55
int ShowModal() override
Definition kidialog.cpp:93
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
LOCAL_HISTORY & LocalHistory()
Return the LOCAL_HISTORY associated with this KIWAY.
Definition kiway.h:406
Plugin class for import plugins that support remappable layers.
void SynchronizeTuningProfileProperties() const
Ensure time domain properties provider is synced with board / project settings if required.
A logical library item identifier and consists of various portions much like a URI.
Definition lib_id.h:49
int SetLibNickname(const UTF8 &aLibNickname)
Override the logical library name portion of the LIB_ID to aLibNickname.
Definition lib_id.cpp:100
const UTF8 & GetLibItemName() const
Definition lib_id.h:102
bool TagSave(const wxString &aProjectPath, const wxString &aFileType)
Tag a manual save in the local history repository.
bool Init(const wxString &aProjectPath)
Initialize the local history repository for the given project path.
bool CommitFullProjectSnapshot(const wxString &aProjectPath, const wxString &aTitle)
Commit a snapshot of the entire project directory (excluding the .history directory and ignored trans...
Definition raii.h:38
static REPORTER & GetInstance()
Definition reporter.cpp:97
static wxString GetDefaultUserProjectsPath()
Gets the default path we point users to create projects.
Definition paths.cpp:137
static TOOL_ACTION repairBoard
static TOOL_ACTION rehatchShapes
wxString GetDesignRulesPath()
Return the absolute path to the design rules file for the currently-loaded board.
wxString CreateNewProjectLibrary(const wxString &aDialogTitle, const wxString &aLibName)
const VECTOR2I GetPageSizeIU() const override
Works off of GetPageSettings() to return the size of the paper page in the internal units of this par...
PCB_DRAW_PANEL_GAL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
PCB_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
BOARD * GetBoard() const
EDA_3D_VIEWER_FRAME * Get3DViewerFrame()
virtual void UpdateStatusBar() override
Update the status bar information.
The main frame for Pcbnew.
void LoadDrawingSheet()
Load the drawing sheet file.
void ResolveDRCExclusions(bool aCreateMarkers)
If aCreateMarkers then create DRC exclusion markers from the serialized data.
void SetBoard(BOARD *aBoard, PROGRESS_REPORTER *aReporter=nullptr) override
Set the #m_Pcb member in such as way as to ensure deleting any previous BOARD.
void OnModify() override
Must be called after a board change to set the modified flag.
void OnClearFileHistory(wxCommandEvent &aEvent)
bool SaveBoard(bool aSaveAs=false, bool aSaveCopy=false)
bool OpenProjectFiles(const std::vector< wxString > &aFileSet, int aCtl=0) override
Load a KiCad board (.kicad_pcb) from aFileName.
void ProjectChanged() override
Notification event that the project has changed.
void SaveProjectLocalSettings() override
Save changes to the project local settings.
bool SavePcbCopy(const wxString &aFileName, bool aCreateProject=false, bool aHeadless=false)
Write the board data structures to aFileName.
bool IsContentModified() const override
Get if the current board has been modified but not saved.
bool LoadProjectSettings()
Load the current project's file configuration settings which are pertinent to this PCB_EDIT_FRAME ins...
bool Clear_Pcb(bool doAskAboutUnsavedChanges, bool aFinal=false)
Delete all and reinitialize the current board.
Definition initpcb.cpp:42
void OnBoardLoaded()
Update the state of the GUI after a new board is loaded or created.
void UpdateTitle()
Set the main window title bar text.
int inferLegacyEdgeClearance(BOARD *aBoard, bool aShowUserMsg=true)
const std::map< std::string, UTF8 > * m_importProperties
bool SavePcbFile(const wxString &aFileName, bool addToHistory=true, bool aChangeProject=true)
Write the board data structures to a aFileName.
bool importFile(const wxString &aFileName, int aFileType, const std::map< std::string, UTF8 > *aProperties=nullptr)
Load the given filename but sets the path to the current project path.
void saveProjectSettings() override
Save any design-related project settings associated with this frame.
void OnFileHistory(wxCommandEvent &event)
static PLUGIN_REGISTRY * Instance()
Definition pcb_io_mgr.h:95
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
@ KICAD_SEXP
S-expression Pcbnew file format.
Definition pcb_io_mgr.h:58
@ ALTIUM_DESIGNER
Definition pcb_io_mgr.h:62
@ LEGACY
Legacy Pcbnew file formats prior to s-expression.
Definition pcb_io_mgr.h:59
@ ALTIUM_CIRCUIT_MAKER
Definition pcb_io_mgr.h:60
@ ALTIUM_CIRCUIT_STUDIO
Definition pcb_io_mgr.h:61
@ CADSTAR_PCB_ARCHIVE
Definition pcb_io_mgr.h:63
static PCB_IO * FindPlugin(PCB_FILE_T aFileType)
Return a #PLUGIN which the caller can use to import, export, save, or load design documents.
static PCB_FILE_T FindPluginTypeFromBoardPath(const wxString &aFileName, int aCtl=0)
Return a plugin type given a path for a board file.
Collect all BOARD_ITEM objects on a given layer.
Definition collectors.h:549
void Collect(BOARD_ITEM *aBoard, const std::vector< KICAD_T > &aTypes)
Test a BOARD_ITEM using this class's Inspector method, which does the collection.
void SetLayerId(PCB_LAYER_ID aLayerId)
Definition collectors.h:555
Plugin class for import plugins that support choosing a project.
LSET m_VisibleLayers
Board settings.
GAL_SET m_VisibleItems
The GAL layers (aka items) that are turned on for viewing (.
virtual void SetReadOnly(bool aReadOnly=true)
Definition project.h:163
virtual const wxString GetProjectFullName() const
Return the full path and name of the project.
Definition project.cpp:161
virtual PROJECT_LOCAL_SETTINGS & GetLocalSettings() const
Definition project.h:205
virtual const wxString FootprintLibTblName() const
Returns the path and filename of this project's footprint library table.
Definition project.cpp:197
virtual bool IsNullProject() const
Check if this project is a null project (i.e.
Definition project.cpp:185
virtual bool HasMessage() const
Returns true if any messages were reported.
Definition reporter.h:134
void SaveProjectAs(const wxString &aFullPath, PROJECT *aProject=nullptr)
Set the currently loaded project path and saves it (pointers remain valid).
void SaveProjectCopy(const wxString &aFullPath, PROJECT *aProject=nullptr)
Save a copy of the current project under the given path.
bool SaveProject(const wxString &aFullPath=wxEmptyString, PROJECT *aProject=nullptr)
Save a loaded project.
bool LoadProject(const wxString &aFullPath, bool aSetActive=true)
Load a project or sets up a new project with a specified path.
bool UnloadProject(PROJECT *aProject, bool aSave=true)
Save, unload and unregister the given PROJECT.
PROJECT & Prj() const
A helper while we are not MDI-capable – return the one and only project.
TOOL_MANAGER * m_toolManager
Generic, UI-independent tool event.
Definition tool_event.h:171
bool empty() const
Definition utf8.h:109
static void ResolvePossibleSymlinks(wxFileName &aFilename)
@ OUTDATED_SAVE
OUTDATED_SAVE Messages that should be cleared on save.
Definition wx_infobar.h:96
@ GENERIC
GENERIC Are messages that do not have special handling.
Definition wx_infobar.h:95
void Dismiss() override
Dismisses the infobar and updates the containing layout and AUI manager (if one is provided).
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:191
const wxString & GetMessages() const
Definition reporter.cpp:78
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:628
bool AskOverrideLock(wxWindow *aParent, const wxString &aMessage)
Display a dialog indicating the file is already open, with an option to reset the lock.
Definition confirm.cpp:42
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition confirm.cpp:259
void DisplayInfoMessage(wxWindow *aParent, const wxString &aMessage, const wxString &aExtraInfo)
Display an informational message box with aMessage.
Definition confirm.cpp:230
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:131
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition confirm.cpp:202
void DisplayError(wxWindow *aParent, const wxString &aText)
Display an error or warning message box with aMessage.
Definition confirm.cpp:177
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:138
void KiCopyFile(const wxString &aSrcPath, const wxString &aDestPath, wxString &aErrors)
Definition gestfich.cpp:292
#define WIN_STRING_DIR_SEP
Definition gestfich.h:38
#define UNIX_STRING_DIR_SEP
Definition gestfich.h:37
static const std::string ProjectFileExtension
static const std::string LegacyPcbFileExtension
static const std::string DesignRulesFileExtension
static const std::string KiCadPcbFileExtension
static wxString PcbFileWildcard()
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)
macro which captures the "call site" values of FILE_, __FUNCTION & LINE
PROJECT & Prj()
Definition kicad.cpp:637
#define KICTL_CREATE
caller thinks requested project files may not exist.
#define KICTL_REVERT
reverting to a previously-saved (KiCad) file.
#define KICTL_IMPORT_LIB
import all footprints into a project library.
#define KICTL_KICAD_ONLY
chosen file is from KiCad according to user
#define KICTL_NONKICAD_ONLY
chosen file is non-KiCad according to user
@ 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:287
@ Edge_Cuts
Definition layer_ids.h:112
@ Rescue
Definition layer_ids.h:121
#define GAL_LAYER_INDEX(x)
Use this macro to convert a GAL layer to a 0-indexed offset from LAYER_VIAS.
Definition layer_ids.h:364
File locking utilities.
This file contains miscellaneous commonly used macros and functions.
bool RegisterApplicationRestart(const wxString &aCommandLine)
Registers the application for restart with the OS with the given command line string to pass as args.
Definition unix/app.cpp:65
bool MakeWriteable(const wxString &aFilePath)
Ensures that a file has write permissions.
Definition unix/io.cpp:70
#define SEXPR_BOARD_FILE_VERSION
Current s-expression file format version. 2 was the last legacy format version.
bool AskLoadBoardFileName(PCB_EDIT_FRAME *aParent, wxString *aFileName, int aCtl=0)
Show a wxFileDialog asking for a BOARD filename to open.
bool AskSaveBoardFileName(PCB_EDIT_FRAME *aParent, wxString *aFileName, bool *aCreateProject)
Put up a wxFileDialog asking for a BOARD filename to save.
SETTINGS_MANAGER * GetSettingsManager()
PGM_BASE & Pgm()
The global program "get" accessor.
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:41
#define NAMELESS_PROJECT
default name for nameless projects
Definition project.h:44
KIWAY Kiway(KFCTL_STANDALONE)
bool show_import_issues
Stored value for "show import issues" when importing non-KiCad designs to this application.
Variant of PARSE_ERROR indicating that a syntax or related error was likely caused by a file generate...
Container that describes file type info.
Definition io_base.h:43
std::vector< std::string > m_FileExtensions
Filter used for file pickers if m_IsFile is true.
Definition io_base.h:47
bool m_CanRead
Whether the IO can read this file type.
Definition io_base.h:52
std::string path
wxString result
Test unit parsing edge cases and error handling.
wxLogTrace helper definitions.
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
Definition typeinfo.h:88
wxString AddFileExtListToFilter(const std::vector< std::string > &aExts)
Build the wildcard extension file dialog wildcard filter to add to the base message dialog.
wxString formatWildcardExt(const wxString &aWildcard)
Format wildcard extension to support case sensitive file dialogs.
Definition of file extensions used in Kicad.
#define PR_CAN_ABORT