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>
27#include <confirm.h>
29#include <kiface_base.h>
30#include <drc/drc_item.h>
32#include <pcb_io/pcb_io.h>
33#include <pcb_io/pcb_io_mgr.h>
43#include <project.h>
49
50#include "dialog_board_setup.h"
51
52#include <advanced_config.h>
53#include <footprint.h>
54
55
56#define RESOLVE_PAGE( T, pageIndex ) static_cast<T*>( m_treebook->ResolvePage( pageIndex ) )
57
58DIALOG_BOARD_SETUP::DIALOG_BOARD_SETUP( PCB_EDIT_FRAME* aFrame, wxWindow* aParentWindow ) :
59 PAGED_DIALOG( aParentWindow ? aParentWindow : aFrame, _( "Board Setup" ), false, false,
60 _( "Import Settings from Another Board..." ), wxSize( 980, 600 ) ),
61 m_frame( aFrame ),
62 m_layers( nullptr ),
63 m_boardFinish( nullptr ),
64 m_physicalStackup( nullptr ),
65 m_timeDomainParameters( nullptr ),
66 m_netClasses( nullptr ),
67 m_currentPage( 0 ),
68 m_layersPage( 0 ),
76 m_teardropsPage( 0 ),
82{
83 SetEvtHandlerEnabled( false );
84
85 /*
86 * WARNING: If you change page names you MUST update calls to ShowBoardSetupDialog().
87 */
88
89 m_treebook->AddPage( new wxPanel( GetTreebook() ), _( "Board Stackup" ) );
90
91 /*
92 * WARNING: Code currently relies on the layers setup coming before the physical stackup panel,
93 * and thus transferring data to the board first. See comment in
94 * PANEL_SETUP_BOARD_STACKUP::TransferDataFromWindow and rework this logic if it is determined
95 * that the order of these pages should be changed.
96 */
97 m_layersPage = m_treebook->GetPageCount();
98 m_treebook->AddLazySubPage(
99 [this]( wxWindow* aParent ) -> wxWindow*
100 {
101 return new PANEL_SETUP_LAYERS( aParent, m_frame );
102 }, _( "Board Editor Layers" ) );
103
104 m_physicalStackupPage = m_treebook->GetPageCount();
105 m_treebook->AddLazySubPage(
106 [this]( wxWindow* aParent ) -> wxWindow*
107 {
111 }, _( "Physical Stackup" ) );
112
113 m_boardFinishPage = m_treebook->GetPageCount();
114 m_treebook->AddLazySubPage(
115 [this]( wxWindow* aParent ) -> wxWindow*
116 {
117 return new PANEL_SETUP_BOARD_FINISH( aParent, m_frame );
118 }, _( "Board Finish" ) );
119
120 m_maskAndPagePage = m_treebook->GetPageCount();
121 m_treebook->AddLazySubPage(
122 [this]( wxWindow* aParent ) -> wxWindow*
123 {
124 return new PANEL_SETUP_MASK_AND_PASTE( aParent, m_frame );
125 }, _( "Solder Mask/Paste" ) );
126
127 m_treebook->AddPage( new wxPanel( GetTreebook() ), _( "Text & Graphics" ) );
128
129 m_textAndGraphicsPage = m_treebook->GetPageCount();
130 m_treebook->AddLazySubPage(
131 [this]( wxWindow* aParent ) -> wxWindow*
132 {
133 return new PANEL_SETUP_TEXT_AND_GRAPHICS( aParent, m_frame );
134 }, _( "Defaults" ) );
135
136 m_formattingPage = m_treebook->GetPageCount();
137 m_treebook->AddLazySubPage(
138 [this]( wxWindow* aParent ) -> wxWindow*
139 {
140 return new PANEL_SETUP_FORMATTING( aParent, m_frame );
141 }, _( "Formatting" ) );
142
143 m_treebook->AddLazySubPage(
144 [this]( wxWindow* aParent ) -> wxWindow*
145 {
146 return new PANEL_TEXT_VARIABLES( aParent, &Prj() );
147 }, _( "Text Variables" ) );
148
149 m_treebook->AddPage( new wxPanel( GetTreebook() ), _( "Design Rules" ) );
150
151 m_constraintsPage = m_treebook->GetPageCount();
152 m_treebook->AddLazySubPage(
153 [this]( wxWindow* aParent ) -> wxWindow*
154 {
155 return new PANEL_SETUP_CONSTRAINTS( aParent, m_frame );
156 }, _( "Constraints" ) );
157
158 m_tracksAndViasPage = m_treebook->GetPageCount();
159 m_treebook->AddLazySubPage(
160 [this]( wxWindow* aParent ) -> wxWindow*
161 {
162 return new PANEL_SETUP_TRACKS_AND_VIAS( aParent, m_frame );
163 }, _( "Pre-defined Sizes" ) );
164
165 m_teardropsPage = m_treebook->GetPageCount();
166 m_treebook->AddLazySubPage(
167 [this]( wxWindow* aParent ) -> wxWindow*
168 {
169 return new PANEL_SETUP_TEARDROPS( aParent, m_frame );
170 }, _( "Teardrops" ) );
171
172 m_tuningPatternsPage = m_treebook->GetPageCount();
173 m_treebook->AddLazySubPage(
174 [this]( wxWindow* aParent ) -> wxWindow*
175 {
176 BOARD_DESIGN_SETTINGS& bds = m_frame->GetBoard()->GetDesignSettings();
177
178 return new PANEL_SETUP_TUNING_PATTERNS( aParent, m_frame,
182 }, _( "Length-tuning Patterns" ) );
183
184 m_netclassesPage = m_treebook->GetPageCount();
185 m_treebook->AddLazySubPage(
186 [this]( wxWindow* aParent ) -> wxWindow*
187 {
188 BOARD* board = m_frame->GetBoard();
189 return new PANEL_SETUP_NETCLASSES( aParent, m_frame,
190 m_frame->Prj().GetProjectFile().NetSettings(),
192 false );
193 }, _( "Net Classes" ) );
194
195 m_componentClassesPage = m_treebook->GetPageCount();
196 m_treebook->AddLazySubPage(
197 [this]( wxWindow* aParent ) -> wxWindow*
198 {
199 // Construct the panel
201 aParent, m_frame, m_frame->Prj().GetProjectFile().ComponentClassSettings(),
202 this );
203 },
204 _( "Component Classes" ) );
205
206 m_timeDomainParametersPage = m_treebook->GetPageCount();
207 m_treebook->AddLazySubPage(
208 [this]( wxWindow* aParent ) -> wxWindow*
209 {
210 BOARD* board = m_frame->GetBoard();
212 aParent, m_frame, board, m_frame->Prj().GetProjectFile().TimeDomainParameters() );
213 },
214 _( "Time Domain Parameters" ) );
215
216 m_customRulesPage = m_treebook->GetPageCount();
217 m_treebook->AddLazySubPage(
218 [this]( wxWindow* aParent ) -> wxWindow*
219 {
220 return new PANEL_SETUP_RULES( aParent, m_frame );
221 },
222 _( "Custom Rules" ) );
223
224 m_severitiesPage = m_treebook->GetPageCount();
225 m_treebook->AddLazySubPage(
226 [this]( wxWindow* aParent ) -> wxWindow*
227 {
228 BOARD* board = m_frame->GetBoard();
231 },
232 _( "Violation Severity" ) );
233
234 m_treebook->AddPage( new wxPanel( GetTreebook() ), _( "Board Data" ) );
235 m_embeddedFilesPage = m_treebook->GetPageCount();
236 m_treebook->AddLazySubPage(
237 [this]( wxWindow* aParent ) -> wxWindow*
238 {
239 return new PANEL_EMBEDDED_FILES( aParent, m_frame->GetBoard() );
240 },
241 _( "Embedded Files" ) );
242
243 for( size_t i = 0; i < m_treebook->GetPageCount(); ++i )
244 m_treebook->ExpandNode( i );
245
246 SetEvtHandlerEnabled( true );
247
249
250 if( Prj().IsReadOnly() )
251 {
252 m_infoBar->ShowMessage( _( "Project is missing or read-only. Some settings will not "
253 "be editable." ),
254 wxICON_WARNING );
255 }
256
257 wxBookCtrlEvent evt( wxEVT_TREEBOOK_PAGE_CHANGED, wxID_ANY, 0 );
258
259 wxQueueEvent( m_treebook, evt.Clone() );
260}
261
262
266
267
268void DIALOG_BOARD_SETUP::onPageChanged( wxBookCtrlEvent& aEvent )
269{
271
272 size_t page = aEvent.GetSelection();
273
274 if( m_physicalStackupPage > 0 ) // Don't run this during initialization
275 {
277 || page == m_physicalStackupPage || page == m_timeDomainParametersPage || page == m_netclassesPage )
278 {
283 }
284
285 // Ensure layer page always gets updated even if we aren't moving towards it
287 {
288 m_layers->SyncCopperLayers( m_physicalStackup->GetCopperLayerCount() );
289
290 // Avoid calling SyncCopperLayers twice if moving from stackup to time domain directly
291 m_timeDomainParameters->SyncCopperLayers( m_physicalStackup->GetCopperLayerCount() );
292 }
293
294 if( page == m_physicalStackupPage )
295 {
296 m_physicalStackup->OnLayersOptionsChanged( m_layers->GetUILayerMask() );
297 }
299 {
300 m_netClasses->UpdateDelayProfileNames( m_timeDomainParameters->GetDelayProfileNames() );
301 }
302 else if( page == m_timeDomainParametersPage )
303 {
304 m_timeDomainParameters->SyncCopperLayers( m_physicalStackup->GetCopperLayerCount() );
305 }
306
307 if( Prj().IsReadOnly() )
308 {
309 KIUI::Disable( m_treebook->GetPage( page ) );
310 }
311 }
312
313 m_currentPage = page;
314}
315
316
317void DIALOG_BOARD_SETUP::onAuxiliaryAction( wxCommandEvent& aEvent )
318{
319 DIALOG_IMPORT_SETTINGS importDlg( this, m_frame );
320
321 if( importDlg.ShowModal() == wxID_CANCEL )
322 return;
323
324 wxFileName boardFn( importDlg.GetFilePath() );
325 wxFileName projectFn( boardFn );
326
327 projectFn.SetExt( FILEEXT::ProjectFileExtension );
328
329 if( !m_frame->GetSettingsManager()->LoadProject( projectFn.GetFullPath(), false ) )
330 {
331 wxString msg = wxString::Format( _( "Error importing settings from board:\n"
332 "Associated project file %s could not be loaded" ),
333 projectFn.GetFullPath() );
334 DisplayErrorMessage( this, msg );
335
336 return;
337 }
338
342
343 // Flag so user can stop work if it will result in deleted inner copper layers
344 // and still clean up this function properly.
345 bool okToProceed = true;
346
347 PROJECT* otherPrj = m_frame->GetSettingsManager()->GetProject( projectFn.GetFullPath() );
348
350 BOARD* otherBoard = nullptr;
351
352 try
353 {
354 WX_PROGRESS_REPORTER progressReporter( this, _( "Load PCB" ), 1, PR_CAN_ABORT );
355
356 pi->SetProgressReporter( &progressReporter );
357
358 otherBoard = pi->LoadBoard( boardFn.GetFullPath(), nullptr );
359
360 if( importDlg.m_LayersOpt->GetValue() )
361 {
362 BOARD* loadedBoard = m_frame->GetBoard();
363
364 // Check if "Import Settings" board has more layers than the current board.
365 okToProceed = m_layers->CheckCopperLayerCount( loadedBoard, otherBoard );
366 }
367 }
368 catch( const IO_ERROR& ioe )
369 {
370 // You wouldn't think boardFn.GetFullPath() would throw, but we get a stack buffer
371 // underflow from ASAN. While it's probably an ASAN error, a second try/catch doesn't
372 // cost us much.
373 try
374 {
375 if( ioe.Problem() != wxT( "CANCEL" ) )
376 {
377 wxString msg = wxString::Format( _( "Error loading board file:\n%s" ),
378 boardFn.GetFullPath() );
379 DisplayErrorMessage( this, msg, ioe.What() );
380 }
381
382 if( otherPrj != &m_frame->Prj() )
383 m_frame->GetSettingsManager()->UnloadProject( otherPrj, false );
384 }
385 catch(...)
386 {
387 // That was already our best-efforts
388 }
389
390 return;
391 }
392
393 if( okToProceed )
394 {
395 otherBoard->SetProject( otherPrj );
396
397 // If layers options are imported, import also the stackup
398 // layers options and stackup are linked, so they cannot be imported
399 // separately, and stackup can be imported only after layers options
400 if( importDlg.m_LayersOpt->GetValue() )
401 {
402 m_physicalStackup->ImportSettingsFrom( otherBoard );
403 m_layers->ImportSettingsFrom( otherBoard );
404 m_boardFinish->ImportSettingsFrom( otherBoard );
405 }
406
407 if( importDlg.m_TextAndGraphicsOpt->GetValue() )
408 {
410 m_textAndGraphicsPage )->ImportSettingsFrom( otherBoard );
411 }
412
413 if( importDlg.m_FormattingOpt->GetValue() )
414 {
416 m_formattingPage )->ImportSettingsFrom( otherBoard );
417 }
418
419 if( importDlg.m_ConstraintsOpt->GetValue() )
420 {
422 m_constraintsPage )->ImportSettingsFrom( otherBoard );
423 }
424
425 if( importDlg.m_NetclassesOpt->GetValue() )
426 {
427 PROJECT_FILE& otherProjectFile = otherPrj->GetProjectFile();
428
430 m_netclassesPage )->ImportSettingsFrom( otherProjectFile.m_NetSettings );
431 }
432
433 if( importDlg.m_ComponentClassesOpt->GetValue() )
434 {
435 PROJECT_FILE& otherProjectFile = otherPrj->GetProjectFile();
436
438 ->ImportSettingsFrom( otherProjectFile.m_ComponentClassSettings );
439 }
440
441 if( importDlg.m_TracksAndViasOpt->GetValue() )
442 {
444 m_tracksAndViasPage )->ImportSettingsFrom( otherBoard );
445 }
446
447 if( importDlg.m_TeardropsOpt->GetValue() )
448 {
450 m_teardropsPage )->ImportSettingsFrom( otherBoard );
451 }
452
453 if( importDlg.m_TuningPatternsOpt->GetValue() )
454 {
456 m_tuningPatternsPage )->ImportSettingsFrom( otherBoard );
457 }
458
459 if( importDlg.m_MaskAndPasteOpt->GetValue() )
460 {
462 m_maskAndPagePage )->ImportSettingsFrom( otherBoard );
463 }
464
465 if( importDlg.m_CustomRulesOpt->GetValue() )
466 {
468 m_customRulesPage )->ImportSettingsFrom( otherBoard );
469 }
470
471 if( importDlg.m_SeveritiesOpt->GetValue() )
472 {
473 BOARD_DESIGN_SETTINGS& otherSettings = otherBoard->GetDesignSettings();
474
476 m_severitiesPage )->ImportSettingsFrom( otherSettings.m_DRCSeverities );
477 }
478
479 if( importDlg.m_TimeDomainParametersOpt->GetValue() )
480 {
481 PROJECT_FILE& otherProjectFile = otherPrj->GetProjectFile();
482
484 ->ImportSettingsFrom( otherProjectFile.TimeDomainParameters() );
485 }
486
487 if( otherPrj != &m_frame->Prj() )
488 otherBoard->ClearProject();
489 }
490
491 // Clean up and free memory before leaving
492 if( otherPrj != &m_frame->Prj() )
493 m_frame->GetSettingsManager()->UnloadProject( otherPrj, false );
494
495 delete otherBoard;
496}
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:317
std::set< wxString > GetNetClassAssignmentCandidates() const
Return the set of netname candidates for netclass assignment.
Definition board.cpp:2260
void SetProject(PROJECT *aProject, bool aReferenceOnly=false)
Link a board to a given project.
Definition board.cpp:198
void ClearProject()
Definition board.cpp:236
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition board.cpp:1040
DIALOG_BOARD_SETUP(PCB_EDIT_FRAME *aFrame, wxWindow *aWindow=nullptr)
PCB_EDIT_FRAME * m_frame
void onAuxiliaryAction(wxCommandEvent &aEvent) override
PANEL_SETUP_BOARD_STACKUP * m_physicalStackup
PANEL_SETUP_BOARD_FINISH * m_boardFinish
PANEL_SETUP_LAYERS * m_layers
PANEL_SETUP_TIME_DOMAIN_PARAMETERS * m_timeDomainParameters
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:133
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.
static PCB_IO * PluginFind(PCB_FILE_T aFileType)
Return a #PLUGIN which the caller can use to import, export, save, or load design documents.
@ KICAD_SEXP
S-expression Pcbnew file format.
Definition pcb_io_mgr.h:58
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< TIME_DOMAIN_PARAMETERS > & TimeDomainParameters()
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:204
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:194
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.
Definition of file extensions used in Kicad.
#define PR_CAN_ABORT