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>
52#include <kiplatform/ui.h>
54#include <widgets/wx_infobar.h>
57#include <paths.h>
58#include <pgm_base.h>
60#include <project_pcb.h>
64#include <pcb_io/pcb_io_mgr.h>
72#include <tools/pcb_actions.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
193
194 if( dlg.ShowModal() == wxID_OK )
195 {
196 *aFileName = dlg.GetPath();
197 aParent->SetMruPath( wxFileName( dlg.GetPath() ).GetPath() );
198
199 if( !kicadFormat )
200 aParent->config()->m_System.show_import_issues = importOptions.GetShowIssues();
201
202 return true;
203 }
204 else
205 {
206 return false;
207 }
208}
209
210
220bool AskSaveBoardFileName( PCB_EDIT_FRAME* aParent, wxString* aFileName, bool* aCreateProject )
221{
222 wxString wildcard = FILEEXT::PcbFileWildcard();
223 wxFileName fn = *aFileName;
224
226
227 wxFileDialog dlg( aParent, _( "Save Board File As" ), fn.GetPath(), fn.GetFullName(), wildcard,
228 wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
229
230// Add a "Create a project" checkbox in standalone mode and one isn't loaded
231 FILEDLG_HOOK_SAVE_PROJECT newProjectHook;
232
233 if( Kiface().IsSingle() && aParent->Prj().IsNullProject() )
234 dlg.SetCustomizeHook( newProjectHook );
235
237
238 if( dlg.ShowModal() != wxID_OK )
239 return false;
240
241 *aFileName = dlg.GetPath();
242 *aFileName = EnsureFileExtension( *aFileName, FILEEXT::KiCadPcbFileExtension );
243
244 if( newProjectHook.IsAttachedToDialog() )
245 *aCreateProject = newProjectHook.GetCreateNewProject();
246 else if( !aParent->Prj().IsNullProject() )
247 *aCreateProject = true;
248
249 return true;
250}
251
252
253void PCB_EDIT_FRAME::OnFileHistory( wxCommandEvent& event )
254{
255 wxString filename = GetFileFromHistory( event.GetId(), _( "Printed circuit board" ) );
256
257 if( !filename.IsEmpty() )
258 {
259 if( !wxFileName::IsFileReadable( filename ) )
260 {
261 if( !AskLoadBoardFileName( this, &filename, KICTL_KICAD_ONLY ) )
262 return;
263 }
264
265 OpenProjectFiles( std::vector<wxString>( 1, filename ), KICTL_KICAD_ONLY );
266 }
267}
268
269
270void PCB_EDIT_FRAME::OnClearFileHistory( wxCommandEvent& aEvent )
271{
273}
274
275
277{
278 // Only standalone mode can directly load a new document
279 if( !Kiface().IsSingle() )
280 return false;
281
282 int open_ctl = KICTL_KICAD_ONLY;
283 wxString fileName = m_frame->Prj().AbsolutePath( m_frame->GetBoard()->GetFileName() );
284
285 if( AskLoadBoardFileName( m_frame, &fileName, open_ctl ) )
286 m_frame->OpenProjectFiles( std::vector<wxString>( 1, fileName ), open_ctl );
287
288 return 0;
289}
290
291
293{
294 // Note: we explicitly allow this even if not in standalone mode for now, even though it is dangerous.
295 int open_ctl = KICTL_NONKICAD_ONLY;
296 wxString fileName; // = Prj().AbsolutePath( GetBoard()->GetFileName() );
297
298 if( AskLoadBoardFileName( m_frame, &fileName, open_ctl ) )
299 m_frame->OpenProjectFiles( std::vector<wxString>( 1, fileName ), open_ctl );
300
301 return 0;
302}
303
304
306{
307 wxFileName fn = m_frame->Prj().AbsolutePath( m_frame->GetBoard()->GetFileName() );
308
309 if( !IsOK( m_frame, wxString::Format( _( "Revert '%s' to last version saved?" ), fn.GetFullPath() ) ) )
310 return false;
311
312 m_frame->GetScreen()->SetContentModified( false ); // do not prompt the user for changes
313
314 m_frame->ReleaseFile();
315
316 m_frame->OpenProjectFiles( std::vector<wxString>( 1, fn.GetFullPath() ), KICTL_REVERT );
317
318 return 0;
319}
320
321
323{
324 // Only standalone mode can directly load a new document
325 if( !Kiface().IsSingle() )
326 return false;
327
328 if( m_frame->IsContentModified() )
329 {
330 wxFileName fileName = m_frame->GetBoard()->GetFileName();
331 wxString saveMsg = _( "Current board will be closed, save changes to '%s' before "
332 "continuing?" );
333
334 if( !HandleUnsavedChanges( m_frame, wxString::Format( saveMsg, fileName.GetFullName() ),
335 [&]()->bool
336 {
337 return m_frame->SaveBoard();
338 } ) )
339 {
340 return false;
341 }
342 }
343 else if( !m_frame->GetBoard()->IsEmpty() )
344 {
345 if( !IsOK( m_frame, _( "Current Board will be closed. Continue?" ) ) )
346 return false;
347 }
348
349 m_frame->SaveProjectLocalSettings();
350
351 m_frame->GetBoard()->ClearProject();
352 m_frame->GetSettingsManager()->UnloadProject( &m_frame->Prj() );
353
354 if( !m_frame->Clear_Pcb( false ) )
355 return false;
356
357 m_frame->LoadProjectSettings();
358 m_frame->LoadDrawingSheet();
359
360 m_frame->OnBoardLoaded();
361 m_frame->OnModify();
362
363 return 0;
364}
365
366
367bool PCB_EDIT_FRAME::SaveBoard( bool aSaveAs, bool aSaveCopy )
368{
369 if( !aSaveAs )
370 {
371 if( !GetBoard()->GetFileName().IsEmpty() )
372 {
373 if( SavePcbFile( Prj().AbsolutePath( GetBoard()->GetFileName() ) ) )
374 {
375 m_autoSaveRequired = false;
376 return true;
377 }
378
379 return false;
380 }
381 }
382
383 wxString orig_name;
384
385 wxFileName::SplitPath( GetBoard()->GetFileName(), nullptr, nullptr, &orig_name, nullptr );
386
387 if( orig_name.IsEmpty() )
388 orig_name = NAMELESS_PROJECT;
389
390 wxFileName savePath( Prj().GetProjectFullName() );
391
392 if( !savePath.IsOk() || !savePath.IsDirWritable() )
393 {
394 savePath = GetMruPath();
395
396 if( !savePath.IsOk() || !savePath.IsDirWritable() )
398 }
399
400 wxFileName fn( savePath.GetPath(), orig_name, FILEEXT::KiCadPcbFileExtension );
401 wxString filename = fn.GetFullPath();
402 bool createProject = false;
403 bool success = false;
404
405 if( AskSaveBoardFileName( this, &filename, &createProject ) )
406 {
407 if( aSaveCopy )
408 {
409 success = SavePcbCopy( EnsureFileExtension( filename, FILEEXT::KiCadPcbFileExtension ), createProject );
410 }
411 else
412 {
413 success = SavePcbFile( filename, aSaveAs, createProject );
414
415 if( success )
416 m_autoSaveRequired = false;
417 }
418 }
419
420 return success;
421}
422
423
424int PCB_EDIT_FRAME::inferLegacyEdgeClearance( BOARD* aBoard, bool aShowUserMsg )
425{
426 PCB_LAYER_COLLECTOR collector;
427
428 collector.SetLayerId( Edge_Cuts );
429 collector.Collect( aBoard, GENERAL_COLLECTOR::AllBoardItems );
430
431 int edgeWidth = -1;
432 bool mixed = false;
433
434 for( int i = 0; i < collector.GetCount(); i++ )
435 {
436 if( collector[i]->Type() == PCB_SHAPE_T )
437 {
438 int itemWidth = static_cast<PCB_SHAPE*>( collector[i] )->GetWidth();
439
440 if( edgeWidth != -1 && edgeWidth != itemWidth )
441 {
442 mixed = true;
443 edgeWidth = std::max( edgeWidth, itemWidth );
444 }
445 else
446 {
447 edgeWidth = itemWidth;
448 }
449 }
450 }
451
452 if( mixed && aShowUserMsg )
453 {
454 // If they had different widths then we can't ensure that fills will be the same.
455 DisplayInfoMessage( this,
456 _( "If the zones on this board are refilled the Copper Edge "
457 "Clearance setting will be used (see Board Setup > Design "
458 "Rules > Constraints).\n This may result in different fills "
459 "from previous KiCad versions which used the line thicknesses "
460 "of the board boundary on the Edge Cuts layer." ) );
461 }
462
463 return std::max( 0, edgeWidth / 2 );
464}
465
466
467bool PCB_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, int aCtl )
468{
469 // This is for python:
470 if( aFileSet.size() != 1 )
471 {
472 DisplayError( this, wxString::Format( "Pcbnew:%s() takes a single filename", __func__ ) );
473 return false;
474 }
475
476 wxString fullFileName( aFileSet[0] );
477 wxFileName wx_filename( fullFileName );
478 Kiway().LocalHistory().Init( wx_filename.GetPath() );
479 wxString msg;
480
481 if( Kiface().IsSingle() )
483
484 // We insist on caller sending us an absolute path, if it does not, we say it's a bug.
485 wxASSERT_MSG( wx_filename.IsAbsolute(), wxT( "Path is not absolute!" ) );
486
487 std::unique_ptr<LOCKFILE> lock = std::make_unique<LOCKFILE>( fullFileName );
488
489 if( !lock->Valid() && lock->IsLockedByMe() )
490 {
491 // If we cannot acquire the lock but we appear to be the one who locked it, check to
492 // see if there is another KiCad instance running. If not, then we can override the
493 // lock. This could happen if KiCad crashed or was interrupted.
494
495 if( !Pgm().SingleInstance()->IsAnotherRunning() )
496 lock->OverrideLock();
497 }
498
499 if( !lock->Valid() )
500 {
501 // If project-level lock override was already granted, silently override this file's lock
502 if( Prj().IsLockOverrideGranted() )
503 {
504 lock->OverrideLock();
505 }
506 else
507 {
508 msg.Printf( _( "PCB '%s' is already open by '%s' at '%s'." ),
509 wx_filename.GetFullName(),
510 lock->GetUsername(),
511 lock->GetHostname() );
512
513 if( !AskOverrideLock( this, msg ) )
514 return false;
515
516 lock->OverrideLock();
517 }
518 }
519
520 if( IsContentModified() )
521 {
522 if( !HandleUnsavedChanges( this, _( "The current PCB has been modified. Save changes?" ),
523 [&]() -> bool
524 {
525 return SavePcbFile( GetBoard()->GetFileName() );
526 } ) )
527 {
528 return false;
529 }
530 }
531
532 wxFileName pro = fullFileName;
533 pro.SetExt( FILEEXT::ProjectFileExtension );
534
535 bool is_new = !wxFileName::IsFileReadable( fullFileName );
536
537 wxString previousBoardFileName = GetBoard() ? GetBoard()->GetFileName() : wxString();
538
539 // If its a non-existent PCB and caller thinks it exists
540 if( is_new && !( aCtl & KICTL_CREATE ) )
541 {
542 // notify user that fullFileName does not exist, ask if user wants to create it.
543 msg.Printf( _( "PCB '%s' does not exist. Do you wish to create it?" ), fullFileName );
544
545 if( !IsOK( this, msg ) )
546 return false;
547 }
548
549 // Get rid of any existing warnings about the old board
550 GetInfoBar()->Dismiss();
551
552 if( KISTATUSBAR* statusBar = dynamic_cast<KISTATUSBAR*>( GetStatusBar() ) )
553 statusBar->ClearLoadWarningMessages();
554
555 WX_PROGRESS_REPORTER progressReporter( this, is_new ? _( "Create PCB" ) : _( "Load PCB" ), 1,
556 PR_CAN_ABORT );
557 WX_STRING_REPORTER loadReporter;
558 LOAD_INFO_REPORTER_SCOPE loadReporterScope( &loadReporter );
559
560 // No save prompt (we already prompted above), and only reset to a new blank board if new
561 Clear_Pcb( false, !is_new );
562
564
565 if( !is_new )
566 pluginType = PCB_IO_MGR::FindPluginTypeFromBoardPath( fullFileName, aCtl );
567
568 if( pluginType == PCB_IO_MGR::FILE_TYPE_NONE )
569 {
570 progressReporter.Hide();
571 DisplayErrorMessage( this, _( "File format is not supported" ), wxEmptyString );
572 return false;
573 }
574
575 bool converted = pluginType != PCB_IO_MGR::LEGACY && pluginType != PCB_IO_MGR::KICAD_SEXP;
576
577 // Loading a project should only be done under carefully considered circumstances.
578
579 // The calling code should know not to ask me here to change projects unless
580 // it knows what consequences that will have on other KIFACEs running and using
581 // this same PROJECT. It can be very harmful if that calling code is stupid.
583 bool setProject;
584
585 if( Kiface().IsSingle() || !( aCtl & KICTL_NONKICAD_ONLY ) )
586 setProject = pro.GetFullPath() != mgr->Prj().GetProjectFullName();
587 else
588 setProject = Prj().GetProjectFullName().IsEmpty();
589
590 if( setProject )
591 {
592 // calls SaveProject
594
596 mgr->UnloadProject( &mgr->Prj() );
597
598 mgr->LoadProject( pro.GetFullPath() );
599
600 // Do not allow saving a project if one doesn't exist. This normally happens if we are
601 // opening a board that has been moved from its project folder.
602 // For converted projects, we don't want to set the read-only flag because we want a
603 // project to be saved for the new file in case things like netclasses got migrated.
604 Prj().SetReadOnly( !pro.Exists() && !converted );
605 }
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 if( LAYER_MAPPABLE_PLUGIN* mappable_pi = dynamic_cast<LAYER_MAPPABLE_PLUGIN*>( pi.get() ) )
622 {
623 mappable_pi->RegisterCallback( std::bind( DIALOG_MAP_LAYERS::RunModal,
624 this, std::placeholders::_1 ) );
625 }
626
627 if( PROJECT_CHOOSER_PLUGIN* chooser_pi = dynamic_cast<PROJECT_CHOOSER_PLUGIN*>( pi.get() ) )
628 {
629 chooser_pi->RegisterCallback( std::bind( DIALOG_IMPORT_CHOOSE_PROJECT::RunModal,
630 this,
631 std::placeholders::_1 ) );
632 }
633
634 bool failedLoad = false;
635
636 try
637 {
638 if( pi == nullptr )
639 {
640 // There was no plugin found, e.g. due to invalid file extension, file header,...
641 THROW_IO_ERROR( _( "File format is not supported" ) );
642 }
643
644 std::map<std::string, UTF8> props;
645
647 props.insert( m_importProperties->begin(), m_importProperties->end() );
648
649 // PCB_IO_EAGLE can use this info to center the BOARD, but it does not yet.
650 props["page_width"] = std::to_string( GetPageSizeIU().x );
651 props["page_height"] = std::to_string( GetPageSizeIU().y );
652
653 pi->SetQueryUserCallback(
654 [&]( wxString aTitle, int aIcon, wxString aMessage, wxString aAction ) -> bool
655 {
656 KIDIALOG dlg( nullptr, aMessage, aTitle, wxOK | wxCANCEL | aIcon );
657
658 if( !aAction.IsEmpty() )
659 dlg.SetOKLabel( aAction );
660
661 dlg.DoNotShowCheckbox( aMessage, 0 );
662
663 return dlg.ShowModal() == wxID_OK;
664 } );
665
666#if USE_INSTRUMENTATION
667 // measure the time to load a BOARD.
668 int64_t startTime = GetRunningMicroSecs();
669#endif
670 // Use loadReporter for import issues - they will be shown in the status bar
671 // warning icon instead of a modal dialog
672 if( config()->m_System.show_import_issues )
673 pi->SetReporter( &loadReporter );
674 else
675 pi->SetReporter( &NULL_REPORTER::GetInstance() );
676
677 pi->SetProgressReporter( &progressReporter );
678 loadedBoard = pi->LoadBoard( fullFileName, nullptr, &props, &Prj() );
679
680#if USE_INSTRUMENTATION
681 int64_t stopTime = GetRunningMicroSecs();
682 printf( "PCB_IO::Load(): %u usecs\n", stopTime - startTime );
683#endif
684 }
685 catch( const FUTURE_FORMAT_ERROR& ffe )
686 {
687 msg.Printf( _( "Error loading PCB '%s'." ), fullFileName );
688 progressReporter.Hide();
689 DisplayErrorMessage( this, msg, ffe.Problem() );
690
691 failedLoad = true;
692 }
693 catch( const IO_ERROR& ioe )
694 {
695 if( ioe.Problem() != wxT( "CANCEL" ) )
696 {
697 msg.Printf( _( "Error loading PCB '%s'." ), fullFileName );
698 progressReporter.Hide();
699 DisplayErrorMessage( this, msg, ioe.What() );
700 }
701
702 failedLoad = true;
703 }
704 catch( const std::bad_alloc& )
705 {
706 msg.Printf( _( "Memory exhausted loading PCB '%s'" ), fullFileName );
707 progressReporter.Hide();
708 DisplayErrorMessage( this, msg, wxEmptyString );
709
710 failedLoad = true;
711 }
712
713 if( failedLoad || !loadedBoard )
714 {
715 // We didn't create a new blank board above, so do that now
716 Clear_Pcb( false );
717
718 // Show any messages collected before the failure
719 if( KISTATUSBAR* statusBar = dynamic_cast<KISTATUSBAR*>( GetStatusBar() ) )
720 statusBar->SetLoadWarningMessages( loadReporter.GetMessages() );
721
722 return false;
723 }
724
725 // This fixes a focus issue after the progress reporter is done on GTK. It shouldn't
726 // cause any issues on macOS and Windows. If it does, it will have to be conditionally
727 // compiled.
728 Raise();
729
730 // Skip (possibly expensive) connectivity build here; we build it below after load
731 SetBoard( loadedBoard, false, &progressReporter );
732
733 if( loadedBoard->m_LegacyDesignSettingsLoaded )
734 {
735 Prj().SetReadOnly( false );
736
737 // Before we had a copper edge clearance setting, the edge line widths could be used
738 // as a kludge to control them. So if there's no setting then infer it from the
739 // edge widths.
740 if( !loadedBoard->m_LegacyCopperEdgeClearanceLoaded )
741 {
742 // Do not show the inferred edge clearance warning dialog when loading third
743 // party boards. For some reason the dialog completely hangs all of KiCad and
744 // the imported board cannot be saved.
745 int edgeClearance = inferLegacyEdgeClearance( loadedBoard, !converted );
746 loadedBoard->GetDesignSettings().m_CopperEdgeClearance = edgeClearance;
747 }
748
749 // On save; design settings will be removed from the board
750 loadedBoard->SetModified();
751 }
752
753 // Move legacy view settings to local project settings
754 if( !loadedBoard->m_LegacyVisibleLayers.test( Rescue ) )
755 {
757 loadedBoard->SetModified();
758 }
759
761 {
763 loadedBoard->SetModified();
764 }
765
766 if( !loadedBoard->SynchronizeComponentClasses( std::unordered_set<wxString>() ) )
767 {
768 m_infoBar->RemoveAllButtons();
769 m_infoBar->AddCloseButton();
770 m_infoBar->ShowMessage( _( "Could not load component class assignment rules" ),
771 wxICON_WARNING, WX_INFOBAR::MESSAGE_TYPE::GENERIC );
772 }
773
774 // we should not ask PCB_IOs to do these items:
775 loadedBoard->BuildListOfNets();
776 m_toolManager->RunAction( PCB_ACTIONS::repairBoard, true);
778
779 if( loadedBoard->IsModified() )
780 OnModify();
781 else
782 GetScreen()->SetContentModified( false );
783
784 if( ( pluginType == PCB_IO_MGR::LEGACY )
785 || ( pluginType == PCB_IO_MGR::KICAD_SEXP
787 && loadedBoard->GetGenerator().Lower() != wxT( "gerbview" ) ) )
788 {
789 m_infoBar->RemoveAllButtons();
790 m_infoBar->AddCloseButton();
791 m_infoBar->ShowMessage( _( "This file was created by an older version of KiCad. "
792 "It will be converted to the new format when saved." ),
794 }
795
796 // TODO(JE) library tables -- I think this functionality should be deleted
797#if 0
798
799 // Import footprints into a project-specific library
800 //==================================================
801 // TODO: This should be refactored out of here into somewhere specific to the Project Import
802 // E.g. KICAD_MANAGER_FRAME::ImportNonKiCadProject
803 if( aCtl & KICTL_IMPORT_LIB )
804 {
805 wxFileName loadedBoardFn( fullFileName );
806 wxString libNickName = loadedBoardFn.GetName();
807
808 // Extract a footprint library from the design and add it to the fp-lib-table
809 // The footprints are saved in a new .pretty library.
810 // If this library already exists, all previous footprints will be deleted
811 std::vector<FOOTPRINT*> loadedFootprints = pi->GetImportedCachedLibraryFootprints();
812 wxString newLibPath = CreateNewProjectLibrary( _( "New Footprint Library" ),
813 libNickName );
814
815 // Only create the new library if CreateNewLibrary succeeded (note that this fails if
816 // the library already exists and the user aborts after seeing the warning message
817 // which prompts the user to continue with overwrite or abort)
818 if( newLibPath.Length() > 0 )
819 {
821
822 for( FOOTPRINT* footprint : loadedFootprints )
823 {
824 try
825 {
826 if( !footprint->GetFPID().GetLibItemName().empty() ) // Handle old boards.
827 {
828 footprint->SetReference( "REF**" );
829 piSexpr->FootprintSave( newLibPath, footprint );
830 delete footprint;
831 }
832 }
833 catch( const IO_ERROR& ioe )
834 {
835 wxLogError( _( "Error saving footprint %s to project specific library." )
836 + wxS( "\n%s" ),
837 footprint->GetFPID().GetUniStringLibItemName(),
838 ioe.What() );
839 }
840 }
841
842 FP_LIB_TABLE* prjlibtable = PROJECT_PCB::PcbFootprintLibs( &Prj() );
843 const wxString& project_env = PROJECT_VAR_NAME;
844 wxString rel_path, env_path;
845
846 wxASSERT_MSG( wxGetEnv( project_env, &env_path ),
847 wxT( "There is no project variable?" ) );
848
849 wxString result( newLibPath );
850
851 if( result.Replace( env_path, wxT( "$(" ) + project_env + wxT( ")" ) ) )
852 rel_path = result;
853
854 FP_LIB_TABLE_ROW* row = new FP_LIB_TABLE_ROW( libNickName, rel_path,
855 wxT( "KiCad" ), wxEmptyString );
856 prjlibtable->InsertRow( row );
857
858 wxString tblName = Prj().FootprintLibTblName();
859
860 try
861 {
862 PROJECT_PCB::PcbFootprintLibs( &Prj() )->Save( tblName );
863 }
864 catch( const IO_ERROR& ioe )
865 {
866 wxLogError( _( "Error saving project specific footprint library table." )
867 + wxS( "\n%s" ),
868 ioe.What() );
869 }
870
871 // Update footprint LIB_IDs to point to the just imported library
872 for( FOOTPRINT* footprint : GetBoard()->Footprints() )
873 {
874 LIB_ID libId = footprint->GetFPID();
875
876 if( libId.GetLibItemName().empty() )
877 continue;
878
879 libId.SetLibNickname( libNickName );
880 footprint->SetFPID( libId );
881 }
882 }
883 }
884#endif
885 }
886
887 {
888 wxString fname;
889
890 if( !previousBoardFileName.IsEmpty() && ( aCtl & KICTL_NONKICAD_ONLY ) && !setProject )
891 {
892 fname = previousBoardFileName;
893 }
894 else
895 {
896 wxFileName fn;
897
898 fn.SetPath( Prj().GetProjectPath() );
899 fn.SetName( Prj().GetProjectName() );
901
902 fname = fn.GetFullPath();
903
904 fname.Replace( WIN_STRING_DIR_SEP, UNIX_STRING_DIR_SEP );
905 }
906
907 GetBoard()->SetFileName( fname );
908 }
909
910 // Lock the file newly opened:
911 m_file_checker.reset( lock.release() );
912
913 if( !converted )
914 UpdateFileHistory( GetBoard()->GetFileName() );
915
916 std::vector<ZONE*> toFill;
917
918 // Rebuild list of nets (full ratsnest rebuild)
919 GetBoard()->BuildConnectivity( &progressReporter );
920
921 // Load project settings after setting up board; some of them depend on the nets list
924
925 // Resolve DRC exclusions after project settings are loaded
926 ResolveDRCExclusions( true );
927
928 // Initialise caches used by component classes
930
931 // Initialise time domain tuning caches
933
934 // Syncs the UI (appearance panel, etc) with the loaded board and project
936
937 // Refresh the 3D view, if any
938 EDA_3D_VIEWER_FRAME* draw3DFrame = Get3DViewerFrame();
939
940 if( draw3DFrame )
941 draw3DFrame->NewDisplay();
942#if 0 && defined(DEBUG)
943 // Output the board object tree to stdout, but please run from command prompt:
944 GetBoard()->Show( 0, std::cout );
945#endif
946
947 // from EDA_APPL which was first loaded BOARD only:
948 {
949 /* For an obscure reason the focus is lost after loading a board file
950 * when starting up the process.
951 * (seems due to the recreation of the layer manager after loading the file)
952 * Give focus to main window and Drawpanel
953 * must be done for these 2 windows (for an obscure reason ...)
954 * Linux specific
955 * This is more a workaround than a fix.
956 */
957 SetFocus();
958 GetCanvas()->SetFocus();
959 }
960
961 if( !setProject )
962 {
963 // If we didn't reload the project, we still need to call ProjectChanged() to ensure
964 // frame-specific initialization happens (like registering the autosave saver).
965 // When running under the project manager, KIWAY::ProjectChanged() was called before
966 // this frame existed, so we need to call our own ProjectChanged() now.
968 }
969
970 if( KISTATUSBAR* statusBar = dynamic_cast<KISTATUSBAR*>( GetStatusBar() ) )
971 statusBar->SetLoadWarningMessages( loadReporter.GetMessages() );
972
973 return true;
974}
975
976
977bool PCB_EDIT_FRAME::SavePcbFile( const wxString& aFileName, bool addToHistory,
978 bool aChangeProject )
979{
980 // please, keep it simple. prompting goes elsewhere.
981 wxFileName pcbFileName = aFileName;
982
983 if( pcbFileName.GetExt() == FILEEXT::LegacyPcbFileExtension )
984 pcbFileName.SetExt( FILEEXT::KiCadPcbFileExtension );
985
986 // Write through symlinks, don't replace them
988
989 if( !IsWritable( pcbFileName ) )
990 {
991 wxString msg = wxString::Format( _( "Insufficient permissions to write file '%s'." ),
992 pcbFileName.GetFullPath() );
993
994 DisplayError( this, msg );
995 return false;
996 }
997
998 // TODO: these will break if we ever go multi-board
999 wxFileName projectFile( pcbFileName );
1000 wxFileName rulesFile( pcbFileName );
1001 wxString msg;
1002
1003 projectFile.SetExt( FILEEXT::ProjectFileExtension );
1004 rulesFile.SetExt( FILEEXT::DesignRulesFileExtension );
1005
1006 if( projectFile.FileExists() )
1007 {
1009 }
1010 else if( aChangeProject )
1011 {
1012 Prj().SetReadOnly( false );
1013 GetSettingsManager()->SaveProjectAs( projectFile.GetFullPath() );
1014 }
1015
1016 wxFileName currentRules( GetDesignRulesPath() );
1017
1018 if( currentRules.FileExists() && !rulesFile.FileExists() && aChangeProject )
1019 KiCopyFile( currentRules.GetFullPath(), rulesFile.GetFullPath(), msg );
1020
1021 if( !msg.IsEmpty() )
1022 {
1023 DisplayError( this, wxString::Format( _( "Error saving custom rules file '%s'." ),
1024 rulesFile.GetFullPath() ) );
1025 }
1026
1027 if( projectFile.FileExists() )
1028 {
1029 // Save various DRC parameters, such as violation severities (which may have been
1030 // edited via the DRC dialog as well as the Board Setup dialog), DRC exclusions, etc.
1032
1035 }
1036
1037 wxString upperTxt;
1038 wxString lowerTxt;
1039
1040 // On Windows, ensure the target file is writeable by clearing problematic attributes like
1041 // hidden or read-only. This can happen when files are synced via cloud services.
1042 if( pcbFileName.FileExists() )
1043 KIPLATFORM::IO::MakeWriteable( pcbFileName.GetFullPath() );
1044
1045 try
1046 {
1048
1049 pi->SaveBoard( pcbFileName.GetFullPath(), GetBoard(), nullptr );
1050 }
1051 catch( const IO_ERROR& ioe )
1052 {
1053 DisplayError( this, wxString::Format( _( "Error saving board file '%s'.\n%s" ),
1054 pcbFileName.GetFullPath(),
1055 ioe.What() ) );
1056 return false;
1057 }
1058
1059 if( !Kiface().IsSingle() )
1060 {
1061 WX_STRING_REPORTER backupReporter;
1062
1063 if( !GetSettingsManager()->TriggerBackupIfNeeded( backupReporter ) )
1064 {
1065 upperTxt = backupReporter.GetMessages();
1066 SetStatusText( upperTxt, 1 );
1067 }
1068 }
1069
1070 GetBoard()->SetFileName( pcbFileName.GetFullPath() );
1071
1072 // Update the lock in case it was a Save As
1073 LockFile( pcbFileName.GetFullPath() );
1074
1075 // Put the saved file in File History if requested
1076 if( addToHistory )
1077 UpdateFileHistory( GetBoard()->GetFileName() );
1078
1079 lowerTxt.Printf( _( "File '%s' saved." ), pcbFileName.GetFullPath() );
1080
1081 SetStatusText( lowerTxt, 0 );
1082
1083 // Get rid of the old version conversion warning, or any other dismissable warning :)
1084 if( m_infoBar->GetMessageType() == WX_INFOBAR::MESSAGE_TYPE::OUTDATED_SAVE )
1085 m_infoBar->Dismiss();
1086
1087 if( m_infoBar->IsShownOnScreen() && m_infoBar->HasCloseButton() )
1088 m_infoBar->Dismiss();
1089
1090 GetScreen()->SetContentModified( false );
1091 UpdateTitle();
1093
1094 // Capture entire project state for PCB save events.
1095 Kiway().LocalHistory().CommitFullProjectSnapshot( pcbFileName.GetPath(), wxS( "PCB Save" ) );
1096 Kiway().LocalHistory().TagSave( pcbFileName.GetPath(), wxS( "pcb" ) );
1097
1098 if( m_autoSaveTimer )
1099 m_autoSaveTimer->Stop();
1100
1101 m_autoSavePending = false;
1102 m_autoSaveRequired = false;
1103 return true;
1104}
1105
1106
1107bool PCB_EDIT_FRAME::SavePcbCopy( const wxString& aFileName, bool aCreateProject, bool aHeadless )
1108{
1109 wxFileName pcbFileName( aFileName );
1110
1111 if( !IsWritable( pcbFileName ) )
1112 {
1113 if( !aHeadless )
1114 {
1115 DisplayError( this, wxString::Format( _( "Insufficient permissions to write file '%s'." ),
1116 pcbFileName.GetFullPath() ) );
1117 }
1118 return false;
1119 }
1120
1121 // Save various DRC parameters, such as violation severities (which may have been
1122 // edited via the DRC dialog as well as the Board Setup dialog), DRC exclusions, etc.
1124
1126
1127 // On Windows, ensure the target file is writeable by clearing problematic attributes like
1128 // hidden or read-only. This can happen when files are synced via cloud services.
1129 if( pcbFileName.FileExists() )
1130 KIPLATFORM::IO::MakeWriteable( pcbFileName.GetFullPath() );
1131
1132 try
1133 {
1135
1136 wxASSERT( pcbFileName.IsAbsolute() );
1137
1138 pi->SaveBoard( pcbFileName.GetFullPath(), GetBoard(), nullptr );
1139 }
1140 catch( const IO_ERROR& ioe )
1141 {
1142 if( !aHeadless )
1143 {
1144 DisplayError( this, wxString::Format( _( "Error saving board file '%s'.\n%s" ),
1145 pcbFileName.GetFullPath(),
1146 ioe.What() ) );
1147 }
1148
1149 return false;
1150 }
1151
1152 wxFileName projectFile( pcbFileName );
1153 wxFileName rulesFile( pcbFileName );
1154 wxString msg;
1155
1156 projectFile.SetExt( FILEEXT::ProjectFileExtension );
1157 rulesFile.SetExt( FILEEXT::DesignRulesFileExtension );
1158
1159 if( aCreateProject && !projectFile.FileExists() )
1160 GetSettingsManager()->SaveProjectCopy( projectFile.GetFullPath() );
1161
1162 wxFileName currentRules( GetDesignRulesPath() );
1163
1164 if( aCreateProject && currentRules.FileExists() && !rulesFile.FileExists() )
1165 KiCopyFile( currentRules.GetFullPath(), rulesFile.GetFullPath(), msg );
1166
1167 if( !msg.IsEmpty() && !aHeadless )
1168 {
1169 DisplayError( this, wxString::Format( _( "Error saving custom rules file '%s'." ),
1170 rulesFile.GetFullPath() ) );
1171 }
1172
1173 return true;
1174}
1175
1176
1177bool PCB_EDIT_FRAME::importFile( const wxString& aFileName, int aFileType,
1178 const std::map<std::string, UTF8>* aProperties )
1179{
1180 NULLER raiiNuller( (void*&) m_importProperties );
1181
1182 m_importProperties = aProperties;
1183
1184 switch( (PCB_IO_MGR::PCB_FILE_T) aFileType )
1185 {
1187 case PCB_IO_MGR::EAGLE:
1190 return OpenProjectFiles( std::vector<wxString>( 1, aFileName ), KICTL_NONKICAD_ONLY | KICTL_IMPORT_LIB );
1191
1196 return OpenProjectFiles( std::vector<wxString>( 1, aFileName ), KICTL_NONKICAD_ONLY );
1197
1198 default:
1199 return false;
1200 }
1201}
1202
1203
1205{
1207
1208 dlg.ShowModal();
1209
1210 return 0;
1211}
1212
1213
1215{
1217
1218 if( dlg.ShowModal() != wxID_OK )
1219 return 0;
1220
1222
1224 job.m_filename = m_frame->GetBoard()->GetFileName();
1226
1227 job.m_precision = dlg.GetPrecision();
1230
1231 WX_PROGRESS_REPORTER progressReporter( m_frame, _( "Generate ODB++ Files" ), 3, PR_CAN_ABORT );
1232 WX_STRING_REPORTER reporter;
1233
1234 DIALOG_EXPORT_ODBPP::GenerateODBPPFiles( job, m_frame->GetBoard(), m_frame, &progressReporter, &reporter );
1235
1236 if( reporter.HasMessage() )
1237 DisplayError( m_frame, reporter.GetMessages() );
1238
1239 return 0;
1240}
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:2668
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:1084
void SynchronizeProperties()
Copy the current project's text variables into the boards property cache.
Definition board.cpp:2482
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:2698
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:162
virtual PROJECT_LOCAL_SETTINGS & GetLocalSettings() const
Definition project.h:209
virtual const wxString FootprintLibTblName() const
Returns the path and filename of this project's footprint library table.
Definition project.cpp:198
virtual bool IsNullProject() const
Check if this project is a null project (i.e.
Definition project.cpp:186
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:629
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.
void KiCopyFile(const wxString &aSrcPath, const wxString &aDestPath, wxString &aErrors)
Definition gestfich.cpp:293
#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:74
void AllowNetworkFileSystems(wxDialog *aDialog)
Configure a file dialog to show network and virtual file systems.
Definition wxgtk/ui.cpp:717
#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