KiCad PCB EDA Suite
Loading...
Searching...
No Matches
dialog_board_setup.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 The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or (at your
9 * option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19#include <pcb_edit_frame.h>
20#include <panel_setup_layers.h>
28#include <confirm.h>
30#include <widgets/wx_infobar.h>
31#include <kiface_base.h>
32#include <drc/drc_item.h>
34#include <pcb_io/pcb_io.h>
35#include <pcb_io/pcb_io_mgr.h>
45#include <project.h>
51
52#include "dialog_board_setup.h"
53
54#include <advanced_config.h>
55#include <dialog_board_setup.h>
56#include <footprint.h>
57
58
59#define RESOLVE_PAGE( T, pageIndex ) static_cast<T*>( m_treebook->ResolvePage( pageIndex ) )
60
61DIALOG_BOARD_SETUP::DIALOG_BOARD_SETUP( PCB_EDIT_FRAME* aFrame, wxWindow* aParentWindow ) :
62 PAGED_DIALOG( aParentWindow ? aParentWindow : aFrame, _( "Board Setup" ), false, false,
63 _( "Import Settings from Another Board..." ), wxSize( 980, 600 ) ),
64 m_frame( aFrame ),
65 m_layers( nullptr ),
66 m_boardFinish( nullptr ),
67 m_physicalStackup( nullptr ),
68 m_zoneHatchOffsets( nullptr ),
69 m_tuningProfiles( nullptr ),
70 m_netClasses( nullptr ),
71 m_currentPage( 0 ),
72 m_layersPage( 0 ),
75 m_defaultsPage( 0 ),
81 m_teardropsPage( 0 ),
87{
88 SetEvtHandlerEnabled( false );
89
90 /*
91 * WARNING: If you change page names you MUST update calls to ShowBoardSetupDialog().
92 */
93
94 m_treebook->AddPage( new wxPanel( GetTreebook() ), _( "Board Stackup" ) );
95
96 /*
97 * WARNING: Code currently relies on the layers setup coming before the physical stackup panel,
98 * and thus transferring data to the board first. See comment in
99 * PANEL_SETUP_BOARD_STACKUP::TransferDataFromWindow and rework this logic if it is determined
100 * that the order of these pages should be changed.
101 */
102 m_layersPage = m_treebook->GetPageCount();
103 m_treebook->AddLazySubPage(
104 [this]( wxWindow* aParent ) -> wxWindow*
105 {
106 return new PANEL_SETUP_LAYERS( aParent, m_frame );
107 }, _( "Board Editor Layers" ) );
108
109 m_physicalStackupPage = m_treebook->GetPageCount();
110 m_treebook->AddLazySubPage(
111 [this]( wxWindow* aParent ) -> wxWindow*
112 {
116 }, _( "Physical Stackup" ) );
117
118 m_boardFinishPage = m_treebook->GetPageCount();
119 m_treebook->AddLazySubPage(
120 [this]( wxWindow* aParent ) -> wxWindow*
121 {
122 return new PANEL_SETUP_BOARD_FINISH( aParent, m_frame );
123 }, _( "Board Finish" ) );
124
125 m_maskAndPastePage = m_treebook->GetPageCount();
126 m_treebook->AddLazySubPage(
127 [this]( wxWindow* aParent ) -> wxWindow*
128 {
129 return new PANEL_SETUP_MASK_AND_PASTE( aParent, m_frame );
130 }, _( "Solder Mask/Paste" ) );
131
132 m_zoneHatchOffsetsPage = m_treebook->GetPageCount();
133 m_treebook->AddLazySubPage(
134 [this]( wxWindow* aParent ) -> wxWindow*
135 {
136 BOARD_DESIGN_SETTINGS& bds = m_frame->GetBoard()->GetDesignSettings();
137
138 return new PANEL_SETUP_ZONE_HATCH_OFFSETS( aParent, m_frame, bds );
139 }, _( "Zone Hatch Offsets" ) );
140
141 m_treebook->AddPage( new wxPanel( GetTreebook() ), _( "Text & Graphics" ) );
142
143 m_defaultsPage = m_treebook->GetPageCount();
144 m_treebook->AddLazySubPage(
145 [this]( wxWindow* aParent ) -> wxWindow*
146 {
147 return new PANEL_SETUP_DEFAULTS( aParent, m_frame );
148 }, _( "Defaults" ) );
149
150 m_formattingPage = m_treebook->GetPageCount();
151 m_treebook->AddLazySubPage(
152 [this]( wxWindow* aParent ) -> wxWindow*
153 {
154 return new PANEL_SETUP_FORMATTING( aParent, m_frame );
155 }, _( "Formatting" ) );
156
157 m_treebook->AddLazySubPage(
158 [this]( wxWindow* aParent ) -> wxWindow*
159 {
160 return new PANEL_TEXT_VARIABLES( aParent, &Prj() );
161 }, _( "Text Variables" ) );
162
163 m_treebook->AddPage( new wxPanel( GetTreebook() ), _( "Design Rules" ) );
164
165 m_constraintsPage = m_treebook->GetPageCount();
166 m_treebook->AddLazySubPage(
167 [this]( wxWindow* aParent ) -> wxWindow*
168 {
169 return new PANEL_SETUP_CONSTRAINTS( aParent, m_frame );
170 }, _( "Constraints" ) );
171
172 m_tracksAndViasPage = m_treebook->GetPageCount();
173 m_treebook->AddLazySubPage(
174 [this]( wxWindow* aParent ) -> wxWindow*
175 {
176 return new PANEL_SETUP_TRACKS_AND_VIAS( aParent, m_frame );
177 }, _( "Pre-defined Sizes" ) );
178
179 m_teardropsPage = m_treebook->GetPageCount();
180 m_treebook->AddLazySubPage(
181 [this]( wxWindow* aParent ) -> wxWindow*
182 {
183 return new PANEL_SETUP_TEARDROPS( aParent, m_frame );
184 }, _( "Teardrops" ) );
185
186 m_tuningPatternsPage = m_treebook->GetPageCount();
187 m_treebook->AddLazySubPage(
188 [this]( wxWindow* aParent ) -> wxWindow*
189 {
190 BOARD_DESIGN_SETTINGS& bds = m_frame->GetBoard()->GetDesignSettings();
191
192 return new PANEL_SETUP_TUNING_PATTERNS( aParent, m_frame,
196 }, _( "Length-tuning Patterns" ) );
197
198 m_tuningProfilesPage = m_treebook->GetPageCount();
199 m_treebook->AddLazySubPage(
200 [this]( wxWindow* aParent ) -> wxWindow*
201 {
202 BOARD* board = m_frame->GetBoard();
203 return new PANEL_SETUP_TUNING_PROFILES( aParent, m_frame, board,
204 m_frame->Prj().GetProjectFile().TuningProfileParameters() );
205 },
206 _( "Tuning Profiles" ) );
207
208 m_netclassesPage = m_treebook->GetPageCount();
209 m_treebook->AddLazySubPage(
210 [this]( wxWindow* aParent ) -> wxWindow*
211 {
212 BOARD* board = m_frame->GetBoard();
213 return new PANEL_SETUP_NETCLASSES( aParent, m_frame,
214 m_frame->Prj().GetProjectFile().NetSettings(),
216 false );
217 }, _( "Net Classes" ) );
218
219 m_componentClassesPage = m_treebook->GetPageCount();
220 m_treebook->AddLazySubPage(
221 [this]( wxWindow* aParent ) -> wxWindow*
222 {
223 // Construct the panel
225 aParent, m_frame, m_frame->Prj().GetProjectFile().ComponentClassSettings(),
226 this );
227 },
228 _( "Component Classes" ) );
229
230 m_customRulesPage = m_treebook->GetPageCount();
231 m_treebook->AddLazySubPage(
232 [this]( wxWindow* aParent ) -> wxWindow*
233 {
234 return new PANEL_SETUP_RULES( aParent, m_frame );
235 },
236 _( "Custom Rules" ) );
237
238 m_severitiesPage = m_treebook->GetPageCount();
239 m_treebook->AddLazySubPage(
240 [this]( wxWindow* aParent ) -> wxWindow*
241 {
242 BOARD* board = m_frame->GetBoard();
245 },
246 _( "Violation Severity" ) );
247
248 m_treebook->AddPage( new wxPanel( GetTreebook() ), _( "Board Data" ) );
249 m_embeddedFilesPage = m_treebook->GetPageCount();
250 m_treebook->AddLazySubPage(
251 [this]( wxWindow* aParent ) -> wxWindow*
252 {
253 BOARD* board = m_frame->GetBoard();
254
255 std::vector<const EMBEDDED_FILES*> inheritedFiles;
256
257 for( FOOTPRINT* fp : board->Footprints() )
258 inheritedFiles.push_back( fp->GetEmbeddedFiles() );
259
260 return new PANEL_EMBEDDED_FILES( aParent, board, NO_MARGINS, inheritedFiles );
261 },
262 _( "Embedded Files" ) );
263
264 for( size_t i = 0; i < m_treebook->GetPageCount(); ++i )
265 m_treebook->ExpandNode( i );
266
267 SetEvtHandlerEnabled( true );
268
270
271 if( Prj().IsReadOnly() )
272 {
273 m_infoBar->ShowMessage( _( "Project is missing or read-only. Some settings will not be editable." ),
274 wxICON_WARNING );
275 }
276
277 wxBookCtrlEvent evt( wxEVT_TREEBOOK_PAGE_CHANGED, wxID_ANY, 0 );
278
279 wxQueueEvent( m_treebook, evt.Clone() );
280}
281
282
286
287
288void DIALOG_BOARD_SETUP::onPageChanged( wxBookCtrlEvent& aEvent )
289{
291
292 size_t page = aEvent.GetSelection();
293
294 if( m_physicalStackupPage > 0 ) // Don't run this during initialization
295 {
297 || page == m_tuningProfilesPage || page == m_zoneHatchOffsetsPage )
298 {
304 }
305
306 // Ensure layer page always gets updated even if we aren't moving towards it
308 {
309 m_layers->SyncCopperLayers( m_physicalStackup->GetCopperLayerCount() );
310
311 // Avoid calling SyncCopperLayers twice if moving from stackup to tuning profiles directly
312 m_tuningProfiles->SyncCopperLayers( m_physicalStackup->GetCopperLayerCount() );
313 }
314
315 if( page == m_physicalStackupPage )
316 {
317 m_physicalStackup->OnLayersOptionsChanged( m_layers->GetUILayerMask() );
318 }
320 {
321 m_netClasses->UpdateDelayProfileNames( m_tuningProfiles->GetDelayProfileNames() );
322 }
323 else if( page == m_tuningProfilesPage )
324 {
325 m_tuningProfiles->SyncCopperLayers( m_physicalStackup->GetCopperLayerCount() );
326 }
327 else if( page == m_zoneHatchOffsetsPage )
328 {
329 m_zoneHatchOffsets->SyncCopperLayers( m_physicalStackup->GetCopperLayerCount() );
330 }
331
332 if( Prj().IsReadOnly() )
333 {
334 KIUI::Disable( m_treebook->GetPage( page ) );
335 }
336 }
337
338 m_currentPage = page;
339}
340
341
342void DIALOG_BOARD_SETUP::onAuxiliaryAction( wxCommandEvent& aEvent )
343{
344 DIALOG_IMPORT_SETTINGS importDlg( this, m_frame );
345
346 if( importDlg.ShowModal() == wxID_CANCEL )
347 return;
348
349 wxFileName boardFn( importDlg.GetFilePath() );
350 wxFileName projectFn( boardFn );
351
352 projectFn.SetExt( FILEEXT::ProjectFileExtension );
353
354 if( !m_frame->GetSettingsManager()->LoadProject( projectFn.GetFullPath(), false ) )
355 {
356 wxString msg = wxString::Format( _( "Error importing settings from board:\n"
357 "Associated project file %s could not be loaded" ),
358 projectFn.GetFullPath() );
359 DisplayErrorMessage( this, msg );
360
361 return;
362 }
363
367
368 // Flag so user can stop work if it will result in deleted inner copper layers
369 // and still clean up this function properly.
370 bool okToProceed = true;
371
372 PROJECT* otherPrj = m_frame->GetSettingsManager()->GetProject( projectFn.GetFullPath() );
373
375 BOARD* otherBoard = nullptr;
376
377 try
378 {
379 WX_PROGRESS_REPORTER progressReporter( this, _( "Load PCB" ), 1, PR_CAN_ABORT );
380
381 pi->SetProgressReporter( &progressReporter );
382
383 otherBoard = pi->LoadBoard( boardFn.GetFullPath(), nullptr );
384
385 if( importDlg.m_LayersOpt->GetValue() )
386 {
387 BOARD* loadedBoard = m_frame->GetBoard();
388
389 // Check if "Import Settings" board has more layers than the current board.
390 okToProceed = m_layers->CheckCopperLayerCount( loadedBoard, otherBoard );
391 }
392 }
393 catch( const IO_ERROR& ioe )
394 {
395 // You wouldn't think boardFn.GetFullPath() would throw, but we get a stack buffer
396 // underflow from ASAN. While it's probably an ASAN error, a second try/catch doesn't
397 // cost us much.
398 try
399 {
400 if( ioe.Problem() != wxT( "CANCEL" ) )
401 {
402 wxString msg = wxString::Format( _( "Error loading board file:\n%s" ), boardFn.GetFullPath() );
403 DisplayErrorMessage( this, msg, ioe.What() );
404 }
405
406 if( otherPrj != &m_frame->Prj() )
407 m_frame->GetSettingsManager()->UnloadProject( otherPrj, false );
408 }
409 catch(...)
410 {
411 // That was already our best-efforts
412 }
413
414 return;
415 }
416
417 if( okToProceed )
418 {
419 otherBoard->SetProject( otherPrj );
420
421 // If layers options are imported, import also the stackup
422 // layers options and stackup are linked, so they cannot be imported
423 // separately, and stackup can be imported only after layers options
424 if( importDlg.m_LayersOpt->GetValue() )
425 {
426 m_physicalStackup->ImportSettingsFrom( otherBoard );
427 m_layers->ImportSettingsFrom( otherBoard );
428 m_boardFinish->ImportSettingsFrom( otherBoard );
429 }
430
431 if( importDlg.m_TextAndGraphicsOpt->GetValue() )
432 RESOLVE_PAGE( PANEL_SETUP_DEFAULTS, m_defaultsPage )->ImportSettingsFrom( otherBoard );
433
434 if( importDlg.m_FormattingOpt->GetValue() )
435 RESOLVE_PAGE( PANEL_SETUP_FORMATTING, m_formattingPage )->ImportSettingsFrom( otherBoard );
436
437 if( importDlg.m_ConstraintsOpt->GetValue() )
438 RESOLVE_PAGE( PANEL_SETUP_CONSTRAINTS, m_constraintsPage )->ImportSettingsFrom( otherBoard );
439
440 if( importDlg.m_NetclassesOpt->GetValue() )
441 {
442 PROJECT_FILE& otherProjectFile = otherPrj->GetProjectFile();
443
445 m_netclassesPage )->ImportSettingsFrom( otherProjectFile.m_NetSettings );
446 }
447
448 if( importDlg.m_ComponentClassesOpt->GetValue() )
449 {
450 PROJECT_FILE& otherProjectFile = otherPrj->GetProjectFile();
451
453 m_componentClassesPage )->ImportSettingsFrom( otherProjectFile.m_ComponentClassSettings );
454 }
455
456 if( importDlg.m_TracksAndViasOpt->GetValue() )
457 RESOLVE_PAGE( PANEL_SETUP_TRACKS_AND_VIAS, m_tracksAndViasPage )->ImportSettingsFrom( otherBoard );
458
459 if( importDlg.m_TeardropsOpt->GetValue() )
460 RESOLVE_PAGE( PANEL_SETUP_TEARDROPS, m_teardropsPage )->ImportSettingsFrom( otherBoard );
461
462 if( importDlg.m_TuningPatternsOpt->GetValue() )
463 RESOLVE_PAGE( PANEL_SETUP_TUNING_PATTERNS, m_tuningPatternsPage )->ImportSettingsFrom( otherBoard );
464
465 if( importDlg.m_MaskAndPasteOpt->GetValue() )
466 RESOLVE_PAGE( PANEL_SETUP_MASK_AND_PASTE, m_maskAndPastePage )->ImportSettingsFrom( otherBoard );
467
468 if( importDlg.m_ZoneHatchingOffsetsOpt->GetValue() )
469 RESOLVE_PAGE( PANEL_SETUP_ZONE_HATCH_OFFSETS, m_zoneHatchOffsetsPage )->ImportSettingsFrom( otherBoard );
470
471 if( importDlg.m_CustomRulesOpt->GetValue() )
472 RESOLVE_PAGE( PANEL_SETUP_RULES, m_customRulesPage )->ImportSettingsFrom( otherBoard );
473
474 if( importDlg.m_SeveritiesOpt->GetValue() )
475 {
476 BOARD_DESIGN_SETTINGS& otherSettings = otherBoard->GetDesignSettings();
477
479 m_severitiesPage )->ImportSettingsFrom( otherSettings.m_DRCSeverities );
480 }
481
482 if( importDlg.m_TuningProfilesOpt->GetValue() )
483 {
484 PROJECT_FILE& otherProjectFile = otherPrj->GetProjectFile();
485
487 m_tuningProfilesPage )->ImportSettingsFrom( otherProjectFile.TuningProfileParameters() );
488 }
489
490 if( otherPrj != &m_frame->Prj() )
491 otherBoard->ClearProject();
492 }
493
494 // Clean up and free memory before leaving
495 if( otherPrj != &m_frame->Prj() )
496 m_frame->GetSettingsManager()->UnloadProject( otherPrj, false );
497
498 delete otherBoard;
499}
Container for design settings for a BOARD object.
std::map< int, SEVERITY > m_DRCSeverities
PNS::MEANDER_SETTINGS m_DiffPairMeanderSettings
PNS::MEANDER_SETTINGS m_SingleTrackMeanderSettings
PNS::MEANDER_SETTINGS m_SkewMeanderSettings
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:322
std::set< wxString > GetNetClassAssignmentCandidates() const
Return the set of netname candidates for netclass assignment.
Definition board.cpp:2477
const FOOTPRINTS & Footprints() const
Definition board.h:363
void SetProject(PROJECT *aProject, bool aReferenceOnly=false)
Link a board to a given project.
Definition board.cpp:200
void ClearProject()
Definition board.cpp:238
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition board.cpp:1082
DIALOG_BOARD_SETUP(PCB_EDIT_FRAME *aFrame, wxWindow *aWindow=nullptr)
PCB_EDIT_FRAME * m_frame
PANEL_SETUP_TUNING_PROFILES * m_tuningProfiles
void onAuxiliaryAction(wxCommandEvent &aEvent) override
PANEL_SETUP_BOARD_STACKUP * m_physicalStackup
PANEL_SETUP_BOARD_FINISH * m_boardFinish
PANEL_SETUP_LAYERS * m_layers
PANEL_SETUP_ZONE_HATCH_OFFSETS * m_zoneHatchOffsets
void onPageChanged(wxBookCtrlEvent &aEvent) override
PANEL_SETUP_NETCLASSES * m_netClasses
void finishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
int ShowModal() override
static std::vector< std::reference_wrapper< RC_ITEM > > GetItemsWithSeverities()
Definition drc_item.h:141
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?
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
WX_TREEBOOK * GetTreebook()
WX_INFOBAR * m_infoBar
PAGED_DIALOG(wxWindow *aParent, const wxString &aTitle, bool aShowReset, bool aShowOpenFolder, const wxString &aAuxiliaryAction=wxEmptyString, const wxSize &aInitialSize=wxDefaultSize)
WX_TREEBOOK * m_treebook
virtual void onPageChanged(wxBookCtrlEvent &aEvent)
The main frame for Pcbnew.
@ KICAD_SEXP
S-expression Pcbnew file format.
Definition pcb_io_mgr.h:58
static PCB_IO * FindPlugin(PCB_FILE_T aFileType)
Return a #PLUGIN which the caller can use to import, export, save, or load design documents.
The backing store for a PROJECT, in JSON format.
std::shared_ptr< NET_SETTINGS > m_NetSettings
Net settings for this project (owned here)
std::shared_ptr< TUNING_PROFILES > & TuningProfileParameters()
std::shared_ptr< COMPONENT_CLASS_SETTINGS > m_ComponentClassSettings
Component class settings for the project (owned here)
Container for project specific data.
Definition project.h:65
virtual PROJECT_FILE & GetProjectFile() const
Definition project.h:203
Multi-thread safe progress reporter dialog, intended for use of tasks that parallel reporting back of...
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition confirm.cpp:202
This file is part of the common library.
#define RESOLVE_PAGE(T, pageIndex)
#define _(s)
static const std::string ProjectFileExtension
std::unique_ptr< T > IO_RELEASER
Helper to hold and release an IO_BASE object when exceptions are thrown.
Definition io_mgr.h:33
KICOMMON_API void Disable(wxWindow *aWindow)
Makes a window read-only.
#define NO_MARGINS
Definition of file extensions used in Kicad.
#define PR_CAN_ABORT