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 (C) 2017-2023 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>
25#include <../board_stackup_manager/panel_board_stackup.h>
26#include <../board_stackup_manager/panel_board_finish.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>
40#include <project.h>
46
47#include "dialog_board_setup.h"
48
49
51
52
53#define RESOLVE_PAGE( T, pageIndex ) static_cast<T*>( m_treebook->ResolvePage( pageIndex ) )
54
56 PAGED_DIALOG( aFrame, _( "Board Setup" ), false, false,
57 _( "Import Settings from Another Board..." ), wxSize( 980, 600 ) ),
58 m_frame( aFrame ),
59 m_layers( nullptr ),
60 m_physicalStackup( nullptr ),
61 m_currentPage( 0 ),
62 m_layersPage( 0 ),
63 m_physicalStackupPage( 0 ),
64 m_boardFinishPage( 0 ),
65 m_textAndGraphicsPage( 0 ),
66 m_formattingPage( 0 ),
67 m_maskAndPagePage( 0 ),
68 m_constraintsPage( 0 ),
69 m_tracksAndViasPage( 0 ),
70 m_teardropsPage( 0 ),
71 m_tuningPatternsPage( 0 ),
72 m_netclassesPage( 0 ),
73 m_customRulesPage( 0 ),
74 m_severitiesPage( 0 )
75
76{
77 SetEvtHandlerEnabled( false );
78
79 /*
80 * WARNING: If you change page names you MUST update calls to ShowBoardSetupDialog().
81 */
82
83 m_treebook->AddPage( new wxPanel( GetTreebook() ), _( "Board Stackup" ) );
84
85 /*
86 * WARNING: Code currently relies on the layers setup coming before the physical stackup panel,
87 * and thus transferring data to the board first. See comment in
88 * PANEL_SETUP_BOARD_STACKUP::TransferDataFromWindow and rework this logic if it is determined
89 * that the order of these pages should be changed.
90 */
91 m_layersPage = m_treebook->GetPageCount();
93 [this]( wxWindow* aParent ) -> wxWindow*
94 {
95 return new PANEL_SETUP_LAYERS( aParent, m_frame );
96 }, _( "Board Editor Layers" ) );
97
98 m_physicalStackupPage = m_treebook->GetPageCount();
100 [this]( wxWindow* aParent ) -> wxWindow*
101 {
103 return new PANEL_SETUP_BOARD_STACKUP( aParent, m_frame, m_layers );
104 }, _( "Physical Stackup" ) );
105
106 m_boardFinishPage = m_treebook->GetPageCount();
108 [this]( wxWindow* aParent ) -> wxWindow*
109 {
110 return new PANEL_SETUP_BOARD_FINISH( aParent, m_frame );
111 }, _( "Board Finish" ) );
112
113 m_maskAndPagePage = m_treebook->GetPageCount();
115 [this]( wxWindow* aParent ) -> wxWindow*
116 {
117 return new PANEL_SETUP_MASK_AND_PASTE( aParent, m_frame );
118 }, _( "Solder Mask/Paste" ) );
119
120 m_treebook->AddPage( new wxPanel( GetTreebook() ), _( "Text & Graphics" ) );
121
122 m_textAndGraphicsPage = m_treebook->GetPageCount();
124 [this]( wxWindow* aParent ) -> wxWindow*
125 {
126 return new PANEL_SETUP_TEXT_AND_GRAPHICS( aParent, m_frame );
127 }, _( "Defaults" ) );
128
129 m_formattingPage = m_treebook->GetPageCount();
131 [this]( wxWindow* aParent ) -> wxWindow*
132 {
133 return new PANEL_SETUP_FORMATTING( aParent, m_frame );
134 }, _( "Formatting" ) );
135
137 [this]( wxWindow* aParent ) -> wxWindow*
138 {
139 return new PANEL_TEXT_VARIABLES( aParent, &Prj() );
140 }, _( "Text Variables" ) );
141
142 m_treebook->AddPage( new wxPanel( GetTreebook() ), _( "Design Rules" ) );
143
144 m_constraintsPage = m_treebook->GetPageCount();
146 [this]( wxWindow* aParent ) -> wxWindow*
147 {
148 return new PANEL_SETUP_CONSTRAINTS( aParent, m_frame );
149 }, _( "Constraints" ) );
150
151 m_tracksAndViasPage = m_treebook->GetPageCount();
153 [this]( wxWindow* aParent ) -> wxWindow*
154 {
155 return new PANEL_SETUP_TRACKS_AND_VIAS( aParent, m_frame );
156 }, _( "Pre-defined Sizes" ) );
157
158 m_teardropsPage = m_treebook->GetPageCount();
160 [this]( wxWindow* aParent ) -> wxWindow*
161 {
162 return new PANEL_SETUP_TEARDROPS( aParent, m_frame );
163 }, _( "Teardrops" ) );
164
165 m_tuningPatternsPage = m_treebook->GetPageCount();
167 [this]( wxWindow* aParent ) -> wxWindow*
168 {
170
171 return new PANEL_SETUP_TUNING_PATTERNS( aParent, m_frame,
175 }, _( "Length-tuning Patterns" ) );
176
177 m_netclassesPage = m_treebook->GetPageCount();
179 [this]( wxWindow* aParent ) -> wxWindow*
180 {
181 BOARD* board = m_frame->GetBoard();
182 return new PANEL_SETUP_NETCLASSES( aParent, m_frame,
185 false );
186 }, _( "Net Classes" ) );
187
188 m_customRulesPage = m_treebook->GetPageCount();
190 [this]( wxWindow* aParent ) -> wxWindow*
191 {
192 return new PANEL_SETUP_RULES( aParent, m_frame );
193 }, _( "Custom Rules" ) );
194
195 m_severitiesPage = m_treebook->GetPageCount();
197 [this]( wxWindow* aParent ) -> wxWindow*
198 {
199 BOARD* board = m_frame->GetBoard();
202 }, _( "Violation Severity" ) );
203
204 for( size_t i = 0; i < m_treebook->GetPageCount(); ++i )
205 m_treebook->ExpandNode( i );
206
207 SetEvtHandlerEnabled( true );
208
210
211 if( Prj().IsReadOnly() )
212 {
213 m_infoBar->ShowMessage( _( "Project is missing or read-only. Some settings will not "
214 "be editable." ), wxICON_WARNING );
215 }
216
217 wxBookCtrlEvent evt( wxEVT_TREEBOOK_PAGE_CHANGED, wxID_ANY, 0 );
218
219 wxQueueEvent( m_treebook, evt.Clone() );
220}
221
222
224{
225}
226
227
228void DIALOG_BOARD_SETUP::onPageChanged( wxBookCtrlEvent& aEvent )
229{
231
232 size_t page = aEvent.GetSelection();
233
234 if( m_physicalStackupPage > 0 ) // Don't run this during initialization
235 {
237 {
240 }
241
242 // Ensure layer page always gets updated even if we aren't moving towards it
245
246 if( page == m_physicalStackupPage )
248 else if( Prj().IsReadOnly() )
249 KIUI::Disable( m_treebook->GetPage( page ) );
250 }
251
252 m_currentPage = page;
253}
254
255
256void DIALOG_BOARD_SETUP::onAuxiliaryAction( wxCommandEvent& aEvent )
257{
258 DIALOG_IMPORT_SETTINGS importDlg( this, m_frame );
259
260 if( importDlg.ShowModal() == wxID_CANCEL )
261 return;
262
263 wxFileName boardFn( importDlg.GetFilePath() );
264 wxFileName projectFn( boardFn );
265
266 projectFn.SetExt( FILEEXT::ProjectFileExtension );
267
268 if( !m_frame->GetSettingsManager()->LoadProject( projectFn.GetFullPath(), false ) )
269 {
270 wxString msg = wxString::Format( _( "Error importing settings from board:\n"
271 "Associated project file %s could not be loaded" ),
272 projectFn.GetFullPath() );
273 DisplayErrorMessage( this, msg );
274
275 return;
276 }
277
280
281 // Flag so user can stop work if it will result in deleted inner copper layers
282 // and still clean up this function properly.
283 bool okToProceed = true;
284
285 PROJECT* otherPrj = m_frame->GetSettingsManager()->GetProject( projectFn.GetFullPath() );
286
288 BOARD* otherBoard = nullptr;
289
290 try
291 {
292 WX_PROGRESS_REPORTER progressReporter( this, _( "Loading PCB" ), 1 );
293
294 pi->SetProgressReporter( &progressReporter );
295
296 otherBoard = pi->LoadBoard( boardFn.GetFullPath(), nullptr );
297
298 if( importDlg.m_LayersOpt->GetValue() )
299 {
300 BOARD* loadedBoard = m_frame->GetBoard();
301
302 // Check if "Import Settings" board has more layers than the current board.
303 okToProceed = m_layers->CheckCopperLayerCount( loadedBoard, otherBoard );
304 }
305 }
306 catch( const IO_ERROR& ioe )
307 {
308 // You wouldn't think boardFn.GetFullPath() would throw, but we get a stack buffer
309 // underflow from ASAN. While it's probably an ASAN error, a second try/catch doesn't
310 // cost us much.
311 try
312 {
313 if( ioe.Problem() != wxT( "CANCEL" ) )
314 {
315 wxString msg = wxString::Format( _( "Error loading board file:\n%s" ),
316 boardFn.GetFullPath() );
317 DisplayErrorMessage( this, msg, ioe.What() );
318 }
319
320 if( otherPrj != &m_frame->Prj() )
321 m_frame->GetSettingsManager()->UnloadProject( otherPrj, false );
322 }
323 catch(...)
324 {
325 // That was already our best-efforts
326 }
327
328 return;
329 }
330
331 if( okToProceed )
332 {
333 otherBoard->SetProject( otherPrj );
334
335 // If layers options are imported, import also the stackup
336 // layers options and stackup are linked, so they cannot be imported
337 // separately, and stackup can be imported only after layers options
338 if( importDlg.m_LayersOpt->GetValue() )
339 {
341 m_layers->ImportSettingsFrom( otherBoard );
342
344 m_boardFinishPage )->ImportSettingsFrom( otherBoard );
345 }
346
347 if( importDlg.m_TextAndGraphicsOpt->GetValue() )
348 {
350 m_textAndGraphicsPage )->ImportSettingsFrom( otherBoard );
351 }
352
353 if( importDlg.m_FormattingOpt->GetValue() )
354 {
356 m_formattingPage )->ImportSettingsFrom( otherBoard );
357 }
358
359 if( importDlg.m_ConstraintsOpt->GetValue() )
360 {
362 m_constraintsPage )->ImportSettingsFrom( otherBoard );
363 }
364
365 if( importDlg.m_NetclassesOpt->GetValue() )
366 {
367 PROJECT_FILE& otherProjectFile = otherPrj->GetProjectFile();
368
370 m_netclassesPage )->ImportSettingsFrom( otherProjectFile.m_NetSettings );
371 }
372
373 if( importDlg.m_TracksAndViasOpt->GetValue() )
374 {
376 m_tracksAndViasPage )->ImportSettingsFrom( otherBoard );
377 }
378
379 if( importDlg.m_TeardropsOpt->GetValue() )
380 {
382 m_teardropsPage )->ImportSettingsFrom( otherBoard );
383 }
384
385 if( importDlg.m_TuningPatternsOpt->GetValue() )
386 {
388 m_tuningPatternsPage )->ImportSettingsFrom( otherBoard );
389 }
390
391 if( importDlg.m_MaskAndPasteOpt->GetValue() )
392 {
394 m_maskAndPagePage )->ImportSettingsFrom( otherBoard );
395 }
396
397 if( importDlg.m_CustomRulesOpt->GetValue() )
398 {
400 m_customRulesPage )->ImportSettingsFrom( otherBoard );
401 }
402
403 if( importDlg.m_SeveritiesOpt->GetValue() )
404 {
405 BOARD_DESIGN_SETTINGS& otherSettings = otherBoard->GetDesignSettings();
406
408 m_severitiesPage )->ImportSettingsFrom( otherSettings.m_DRCSeverities );
409 }
410
411 if( otherPrj != &m_frame->Prj() )
412 otherBoard->ClearProject();
413 }
414
415 // Clean up and free memory before leaving
416 if( otherPrj != &m_frame->Prj() )
417 m_frame->GetSettingsManager()->UnloadProject( otherPrj, false );
418
419 delete otherBoard;
420}
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:276
std::set< wxString > GetNetClassAssignmentCandidates() const
Return the set of netname candidates for netclass assignment.
Definition: board.cpp:1790
void SetProject(PROJECT *aProject, bool aReferenceOnly=false)
Link a board to a given project.
Definition: board.cpp:199
void ClearProject()
Definition: board.cpp:238
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:806
DIALOG_BOARD_SETUP(PCB_EDIT_FRAME *aFrame)
static std::mutex g_Mutex
PCB_EDIT_FRAME * m_frame
void onAuxiliaryAction(wxCommandEvent &aEvent) override
PANEL_SETUP_BOARD_STACKUP * m_physicalStackup
PANEL_SETUP_LAYERS * m_layers
void onPageChanged(wxBookCtrlEvent &aEvent) override
void finishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
static std::vector< std::reference_wrapper< RC_ITEM > > GetItemsWithSeverities()
Definition: drc_item.h:123
SETTINGS_MANAGER * GetSettingsManager() const
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
Definition: ki_exception.h:77
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:30
virtual const wxString Problem() const
what was the problem?
Definition: exceptions.cpp:46
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
WX_TREEBOOK * GetTreebook()
Definition: paged_dialog.h:39
WX_INFOBAR * m_infoBar
Definition: paged_dialog.h:72
WX_TREEBOOK * m_treebook
Definition: paged_dialog.h:68
virtual void onPageChanged(wxBookCtrlEvent &aEvent)
void ImportSettingsFrom(BOARD *aBoard)
void OnLayersOptionsChanged(LSET aNewLayerSet)
Must be called if the copper layers count has changed or solder mask, solder paste or silkscreen laye...
bool CheckCopperLayerCount(BOARD *aWorkingBoard, BOARD *aImportedBoard)
Check and warn if inner copper layers will be deleted.
void SyncCopperLayers(int aNumCopperLayers)
Called when switching to this tab to make sure that any changes to the copper layer count made on the...
void ImportSettingsFrom(BOARD *aBoard)
BOARD * GetBoard() const
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.
Definition: pcb_io_mgr.cpp:65
@ KICAD_SEXP
S-expression Pcbnew file format.
Definition: pcb_io_mgr.h:58
The backing store for a PROJECT, in JSON format.
Definition: project_file.h:70
std::shared_ptr< NET_SETTINGS > & NetSettings()
Definition: project_file.h:101
std::shared_ptr< NET_SETTINGS > m_NetSettings
Net settings for this project (owned here)
Definition: project_file.h:173
Container for project specific data.
Definition: project.h:62
virtual PROJECT_FILE & GetProjectFile() const
Definition: project.h:166
bool LoadProject(const wxString &aFullPath, bool aSetActive=true)
Loads a project or sets up a new project with a specified path.
PROJECT * GetProject(const wxString &aFullPath) const
Retrieves a loaded project by name.
bool UnloadProject(PROJECT *aProject, bool aSave=true)
Saves, unloads and unregisters the given PROJECT.
void ShowMessage(const wxString &aMessage, int aFlags=wxICON_INFORMATION) override
Show the info bar with the provided message and icon.
Definition: wx_infobar.cpp:154
Multi-thread safe progress reporter dialog, intended for use of tasks that parallel reporting back of...
bool AddLazySubPage(std::function< wxWindow *(wxWindow *aParent)> aLazyCtor, const wxString &text, bool bSelect=false, int imageId=NO_IMAGE)
Definition: wx_treebook.cpp:96
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition: confirm.cpp:305
This file is part of the common library.
#define 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
void Disable(wxWindow *aWindow)
Makes a window read-only.
Definition: ui_common.cpp:320
Definition of file extensions used in Kicad.