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>
26#include <../board_stackup_manager/panel_board_stackup.h>
27#include <../board_stackup_manager/panel_board_finish.h>
28#include <confirm.h>
30#include <kiface_base.h>
31#include <drc/drc_item.h>
33#include <io_mgr.h>
36#include <project.h>
42
43#include "dialog_board_setup.h"
44#include "panel_setup_rules.h"
46
47
49
50
51#define RESOLVE_PAGE( T, pageIndex ) static_cast<T*>( m_treebook->ResolvePage( pageIndex ) )
52
54 PAGED_DIALOG( aFrame, _( "Board Setup" ), false,
55 _( "Import Settings from Another Board..." ) ),
56 m_frame( aFrame ),
57 m_layers( nullptr ),
58 m_physicalStackup( nullptr ),
59 m_currentPage( 0 ),
60 m_layersPage( 0 ),
61 m_physicalStackupPage( 0 ),
62 m_boardFinishPage( 0 ),
63 m_textAndGraphicsPage( 0 ),
64 m_formattingPage( 0 ),
65 m_maskAndPagePage( 0 ),
66 m_constraintsPage( 0 ),
67 m_tracksAndViasPage( 0 ),
68 m_teardropsPage( 0 ),
69 m_netclassesPage( 0 ),
70 m_severitiesPage( 0 )
71
72{
73 SetEvtHandlerEnabled( false );
74
75 /*
76 * WARNING: If you change page names you MUST update calls to ShowBoardSetupDialog().
77 */
78
79 m_treebook->AddPage( new wxPanel( GetTreebook() ), _( "Board Stackup" ) );
80
81 /*
82 * WARNING: Code currently relies on the layers setup coming before the physical stackup panel,
83 * and thus transferring data to the board first. See comment in
84 * PANEL_SETUP_BOARD_STACKUP::TransferDataFromWindow and rework this logic if it is determined
85 * that the order of these pages should be changed.
86 */
87 m_layersPage = m_treebook->GetPageCount();
89 [this]( wxWindow* aParent ) -> wxWindow*
90 {
91 return new PANEL_SETUP_LAYERS( aParent, m_frame );
92 }, _( "Board Editor Layers" ) );
93
94 m_physicalStackupPage = m_treebook->GetPageCount();
96 [this]( wxWindow* aParent ) -> wxWindow*
97 {
99 return new PANEL_SETUP_BOARD_STACKUP( aParent, m_frame, m_layers );
100 }, _( "Physical Stackup" ) );
101
102 m_boardFinishPage = m_treebook->GetPageCount();
104 [this]( wxWindow* aParent ) -> wxWindow*
105 {
106 return new PANEL_SETUP_BOARD_FINISH( aParent, m_frame );
107 }, _( "Board Finish" ) );
108
109 m_maskAndPagePage = m_treebook->GetPageCount();
111 [this]( wxWindow* aParent ) -> wxWindow*
112 {
113 return new PANEL_SETUP_MASK_AND_PASTE( aParent, m_frame );
114 }, _( "Solder Mask/Paste" ) );
115
116 m_treebook->AddPage( new wxPanel( GetTreebook() ), _( "Text & Graphics" ) );
117
118 m_textAndGraphicsPage = m_treebook->GetPageCount();
120 [this]( wxWindow* aParent ) -> wxWindow*
121 {
122 return new PANEL_SETUP_TEXT_AND_GRAPHICS( aParent, m_frame );
123 }, _( "Defaults" ) );
124
125 m_formattingPage = m_treebook->GetPageCount();
127 [this]( wxWindow* aParent ) -> wxWindow*
128 {
129 return new PANEL_SETUP_FORMATTING( aParent, m_frame );
130 }, _( "Formatting" ) );
131
133 [this]( wxWindow* aParent ) -> wxWindow*
134 {
135 return new PANEL_TEXT_VARIABLES( aParent, &Prj() );
136 }, _( "Text Variables" ) );
137
138 m_treebook->AddPage( new wxPanel( GetTreebook() ), _( "Design Rules" ) );
139
140 m_constraintsPage = m_treebook->GetPageCount();
142 [this]( wxWindow* aParent ) -> wxWindow*
143 {
144 return new PANEL_SETUP_CONSTRAINTS( aParent, m_frame );
145 }, _( "Constraints" ) );
146
147 m_tracksAndViasPage = m_treebook->GetPageCount();
149 [this]( wxWindow* aParent ) -> wxWindow*
150 {
151 return new PANEL_SETUP_TRACKS_AND_VIAS( aParent, m_frame );
152 }, _( "Pre-defined Sizes" ) );
153
154 m_teardropsPage = m_treebook->GetPageCount();
156 [this]( wxWindow* aParent ) -> wxWindow*
157 {
158 return new PANEL_SETUP_TEARDROPS( aParent, m_frame );
159 }, _( "Teardrops" ) );
160
161 m_netclassesPage = m_treebook->GetPageCount();
163 [this]( wxWindow* aParent ) -> wxWindow*
164 {
165 BOARD* board = m_frame->GetBoard();
166 return new PANEL_SETUP_NETCLASSES( aParent, m_frame,
169 false );
170 }, _( "Net Classes" ) );
171
173 [this]( wxWindow* aParent ) -> wxWindow*
174 {
175 return new PANEL_SETUP_RULES( aParent, m_frame );
176 }, _( "Custom Rules" ) );
177
178 m_severitiesPage = m_treebook->GetPageCount();
180 [this]( wxWindow* aParent ) -> wxWindow*
181 {
182 BOARD* board = m_frame->GetBoard();
185 }, _( "Violation Severity" ) );
186
187 for( size_t i = 0; i < m_treebook->GetPageCount(); ++i )
188 m_treebook->ExpandNode( i );
189
190 // This is unfortunate, but it's the cost of lazy-loading the panels
191 m_treebook->SetMinSize( wxSize( 980, 600 ) );
192 m_treebook->SetInitialSize( wxSize( 980, 600 ) );
193
194 SetEvtHandlerEnabled( true );
195
197
198 if( Prj().IsReadOnly() )
199 {
200 m_infoBar->ShowMessage( _( "Project is missing or read-only. Some settings will not "
201 "be editable." ), wxICON_WARNING );
202 }
203
204 wxBookCtrlEvent evt( wxEVT_TREEBOOK_PAGE_CHANGED, wxID_ANY, 0 );
205
206 wxQueueEvent( m_treebook, evt.Clone() );
207}
208
209
211{
212}
213
214
215void DIALOG_BOARD_SETUP::onPageChanged( wxBookCtrlEvent& aEvent )
216{
218
219 size_t page = aEvent.GetSelection();
220
221 if( m_physicalStackupPage > 0 ) // Don't run this during initialization
222 {
224 {
227 }
228
229 // Ensure layer page always gets updated even if we aren't moving towards it
232
233 if( page == m_physicalStackupPage )
235 else if( Prj().IsReadOnly() )
236 KIUI::Disable( m_treebook->GetPage( page ) );
237 }
238
239 m_currentPage = page;
240}
241
242
243void DIALOG_BOARD_SETUP::onAuxiliaryAction( wxCommandEvent& aEvent )
244{
245 DIALOG_IMPORT_SETTINGS importDlg( this, m_frame );
246
247 if( importDlg.ShowModal() == wxID_CANCEL )
248 return;
249
250 wxFileName boardFn( importDlg.GetFilePath() );
251 wxFileName projectFn( boardFn );
252
253 projectFn.SetExt( ProjectFileExtension );
254
255 if( !m_frame->GetSettingsManager()->LoadProject( projectFn.GetFullPath(), false ) )
256 {
257 wxString msg = wxString::Format( _( "Error importing settings from board:\n"
258 "Associated project file %s could not be loaded" ),
259 projectFn.GetFullPath() );
260 DisplayErrorMessage( this, msg );
261
262 return;
263 }
264
267
268 // Flag so user can stop work if it will result in deleted inner copper layers
269 // and still clean up this function properly.
270 bool okToProceed = true;
271
272 PROJECT* otherPrj = m_frame->GetSettingsManager()->GetProject( projectFn.GetFullPath() );
273
275 BOARD* otherBoard = nullptr;
276
277 try
278 {
279 WX_PROGRESS_REPORTER progressReporter( this, _( "Loading PCB" ), 1 );
280
281 otherBoard = pi->Load( boardFn.GetFullPath(), nullptr, nullptr, nullptr,
282 &progressReporter );
283
284 if( importDlg.m_LayersOpt->GetValue() )
285 {
286 BOARD* loadedBoard = m_frame->GetBoard();
287
288 // Check if "Import Settings" board has more layers than the current board.
289 okToProceed = m_layers->CheckCopperLayerCount( loadedBoard, otherBoard );
290 }
291 }
292 catch( const IO_ERROR& ioe )
293 {
294 // You wouldn't think boardFn.GetFullPath() would throw, but we get a stack buffer
295 // underflow from ASAN. While it's probably an ASAN error, a second try/catch doesn't
296 // cost us much.
297 try
298 {
299 if( ioe.Problem() != wxT( "CANCEL" ) )
300 {
301 wxString msg = wxString::Format( _( "Error loading board file:\n%s" ),
302 boardFn.GetFullPath() );
303 DisplayErrorMessage( this, msg, ioe.What() );
304 }
305
306 if( otherPrj != &m_frame->Prj() )
307 m_frame->GetSettingsManager()->UnloadProject( otherPrj, false );
308 }
309 catch(...)
310 {
311 // That was already our best-efforts
312 }
313
314 return;
315 }
316
317 if( okToProceed )
318 {
319 otherBoard->SetProject( otherPrj );
320
321 // If layers options are imported, import also the stackup
322 // layers options and stackup are linked, so they cannot be imported
323 // separately, and stackup can be imported only after layers options
324 if( importDlg.m_LayersOpt->GetValue() )
325 {
327 m_layers->ImportSettingsFrom( otherBoard );
328
330 m_boardFinishPage )->ImportSettingsFrom( otherBoard );
331 }
332
333 if( importDlg.m_TextAndGraphicsOpt->GetValue() )
334 {
336 m_textAndGraphicsPage )->ImportSettingsFrom( otherBoard );
337 }
338
339 if( importDlg.m_FormattingOpt->GetValue() )
340 {
342 m_formattingPage )->ImportSettingsFrom( otherBoard );
343 }
344
345 if( importDlg.m_ConstraintsOpt->GetValue() )
346 {
348 m_constraintsPage )->ImportSettingsFrom( otherBoard );
349 }
350
351 if( importDlg.m_NetclassesOpt->GetValue() )
352 {
353 PROJECT_FILE& otherProjectFile = otherPrj->GetProjectFile();
354
356 m_netclassesPage )->ImportSettingsFrom( otherProjectFile.m_NetSettings );
357 }
358
359 if( importDlg.m_TracksAndViasOpt->GetValue() )
360 {
362 m_tracksAndViasPage )->ImportSettingsFrom( otherBoard );
363 }
364
365 if( importDlg.m_TeardropsOpt->GetValue() )
366 {
368 m_teardropsPage )->ImportSettingsFrom( otherBoard );
369 }
370
371 if( importDlg.m_MaskAndPasteOpt->GetValue() )
372 {
374 m_maskAndPagePage )->ImportSettingsFrom( otherBoard );
375 }
376
377 if( importDlg.m_SeveritiesOpt->GetValue() )
378 {
379 BOARD_DESIGN_SETTINGS& otherSettings = otherBoard->GetDesignSettings();
380
382 m_severitiesPage )->ImportSettingsFrom( otherSettings.m_DRCSeverities );
383 }
384
385 if( otherPrj != &m_frame->Prj() )
386 otherBoard->ClearProject();
387 }
388
389 // Clean up and free memory before leaving
390 if( otherPrj != &m_frame->Prj() )
391 m_frame->GetSettingsManager()->UnloadProject( otherPrj, false );
392
393 delete otherBoard;
394}
Container for design settings for a BOARD object.
std::map< int, SEVERITY > m_DRCSeverities
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:270
std::set< wxString > GetNetClassAssignmentCandidates() const
Return the set of netname candidates for netclass assignment.
Definition: board.cpp:1578
void SetProject(PROJECT *aProject, bool aReferenceOnly=false)
Link a board to a given project.
Definition: board.cpp:178
void ClearProject()
Definition: board.cpp:217
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:728
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:122
SETTINGS_MANAGER * GetSettingsManager() const
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
Definition: ki_exception.h:76
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
@ KICAD_SEXP
S-expression Pcbnew file format.
Definition: io_mgr.h:56
static PLUGIN * PluginFind(PCB_FILE_T aFileType)
Return a PLUGIN which the caller can use to import, export, save, or load design documents.
Definition: io_mgr.cpp:58
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
WX_TREEBOOK * GetTreebook()
Definition: paged_dialog.h:38
WX_INFOBAR * m_infoBar
Definition: paged_dialog.h:70
WX_TREEBOOK * m_treebook
Definition: paged_dialog.h:66
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.
Releases a PLUGIN in the context of a potential thrown exception through its destructor.
Definition: io_mgr.h:562
virtual BOARD * Load(const wxString &aFileName, BOARD *aAppendToMe, const STRING_UTF8_MAP *aProperties=nullptr, PROJECT *aProject=nullptr, PROGRESS_REPORTER *aProgressReporter=nullptr)
Load information from some input file format that this PLUGIN implementation knows about into either ...
Definition: plugin.cpp:38
The backing store for a PROJECT, in JSON format.
Definition: project_file.h:65
std::shared_ptr< NET_SETTINGS > & NetSettings()
Definition: project_file.h:96
std::shared_ptr< NET_SETTINGS > m_NetSettings
Net settings for this project (owned here)
Definition: project_file.h:168
Container for project specific data.
Definition: project.h:64
virtual PROJECT_FILE & GetProjectFile() const
Definition: project.h:149
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:92
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition: confirm.cpp:308
This file is part of the common library.
#define RESOLVE_PAGE(T, pageIndex)
#define _(s)
const std::string ProjectFileExtension
void Disable(wxWindow *aWindow)
Makes a window read-only.
Definition: ui_common.cpp:321
Definition of file extensions used in Kicad.