KiCad PCB EDA Suite
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-2021 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>
29 #include <board_design_settings.h>
30 #include <kiface_base.h>
31 #include <drc/drc_item.h>
32 #include <dialog_import_settings.h>
33 #include <io_mgr.h>
35 #include <panel_text_variables.h>
36 #include <project.h>
37 #include <project/project_file.h>
42 
43 #include "dialog_board_setup.h"
44 #include "panel_setup_rules.h"
45 
46 #include <wx/treebook.h>
47 
48 using std::placeholders::_1;
49 
50 
52  PAGED_DIALOG( aFrame, _( "Board Setup" ), false,
53  _( "Import Settings from Another Board..." ) ),
54  m_frame( aFrame )
55 {
56  BOARD* board = aFrame->GetBoard();
58 
59  m_layers = new PANEL_SETUP_LAYERS( this, aFrame );
61  m_constraints = new PANEL_SETUP_CONSTRAINTS( this, aFrame );
62  m_rules = new PANEL_SETUP_RULES( this, aFrame );
64  m_maskAndPaste = new PANEL_SETUP_MASK_AND_PASTE( this, aFrame );
66  m_boardFinish = new PANEL_SETUP_BOARD_FINISH( this, board );
67 
69  bds.m_DRCSeverities );
70 
72  board->GetNetClassAssignmentCandidates(), false );
73 
75 
76  /*
77  * WARNING: If you change page names you MUST update calls to ShowBoardSetupDialog().
78  */
79 
80  m_treebook->AddPage( new wxPanel( this ), _( "Board Stackup" ) );
81 
82  /*
83  * WARNING: Code currently relies on the layers setup coming before the physical stackup panel,
84  * and thus transferring data to the board first. See comment in
85  * PANEL_SETUP_BOARD_STACKUP::TransferDataFromWindow and rework this logic if it is determined
86  * that the order of these pages should be changed.
87  */
88  m_treebook->AddSubPage( m_layers, _( "Board Editor Layers" ) );
89  m_layerSetupPage = 1;
90 
91  m_treebook->AddSubPage( m_physicalStackup, _( "Physical Stackup" ) );
92  // Change this value if m_physicalStackup is not the page 2 of m_treebook
93  m_physicalStackupPage = 2; // The page number (from 0) to select the m_physicalStackup panel
94 
95  m_treebook->AddSubPage( m_boardFinish, _( "Board Finish" ) );
96  m_treebook->AddSubPage( m_maskAndPaste, _( "Solder Mask/Paste" ) );
97 
98  m_treebook->AddPage( new wxPanel( this ), _( "Text & Graphics" ) );
99  m_treebook->AddSubPage( m_textAndGraphics, _( "Defaults" ) );
100  m_treebook->AddSubPage( m_textVars, _( "Text Variables" ) );
101 
102  m_treebook->AddPage( new wxPanel( this ), _( "Design Rules" ) );
103  m_treebook->AddSubPage( m_constraints, _( "Constraints" ) );
104  m_treebook->AddSubPage( m_tracksAndVias, _( "Pre-defined Sizes" ) );
105  m_treebook->AddSubPage( m_netclasses, _( "Net Classes" ) );
106  m_treebook->AddSubPage( m_rules, _( "Custom Rules" ) );
107  m_treebook->AddSubPage( m_severities, _( "Violation Severity" ) );
108 
109  for( size_t i = 0; i < m_treebook->GetPageCount(); ++i )
110  m_macHack.push_back( true );
111 
112  m_treebook->SetMinSize( wxSize( -1, 480 ) );
113 
114  // Connect Events
115  m_treebook->Connect( wxEVT_TREEBOOK_PAGE_CHANGED,
116  wxBookCtrlEventHandler( DIALOG_BOARD_SETUP::OnPageChange ), nullptr,
117  this );
118 
120 
121  if( Prj().IsReadOnly() )
122  {
123  m_infoBar->ShowMessage( _( "Project is missing or read-only. Some settings will not "
124  "be editable." ), wxICON_WARNING );
125  }
126 }
127 
128 
130 {
131  m_treebook->Disconnect( wxEVT_TREEBOOK_PAGE_CHANGED,
132  wxBookCtrlEventHandler( DIALOG_BOARD_SETUP::OnPageChange ), nullptr,
133  this );
134 }
135 
136 
137 void DIALOG_BOARD_SETUP::OnPageChange( wxBookCtrlEvent& event )
138 {
139  int page = event.GetSelection();
140 
141  if( page == m_physicalStackupPage )
143  else if( page == m_layerSetupPage )
145  else if( Prj().IsReadOnly() )
146  KIUI::Disable( m_treebook->GetPage( page ) );
147 
148 #ifdef __WXMAC__
149  // Work around an OSX bug where the wxGrid children don't get placed correctly until
150  // the first resize event
151  if( m_macHack[ page ] )
152  {
153  wxSize pageSize = m_treebook->GetPage( page )->GetSize();
154  pageSize.x -= 1;
155  pageSize.y += 2;
156 
157  m_treebook->GetPage( page )->SetSize( pageSize );
158  m_macHack[ page ] = false;
159  }
160 #endif
161 }
162 
163 
164 void DIALOG_BOARD_SETUP::OnAuxiliaryAction( wxCommandEvent& event )
165 {
166  DIALOG_IMPORT_SETTINGS importDlg( this, m_frame );
167 
168  if( importDlg.ShowModal() == wxID_CANCEL )
169  return;
170 
171  wxFileName boardFn( importDlg.GetFilePath() );
172  wxFileName projectFn( boardFn );
173 
174  projectFn.SetExt( ProjectFileExtension );
175 
176  if( !m_frame->GetSettingsManager()->LoadProject( projectFn.GetFullPath(), false ) )
177  {
178  wxString msg = wxString::Format( _( "Error importing settings from board:\n"
179  "Associated project file %s could not be loaded" ),
180  projectFn.GetFullPath() );
181  DisplayErrorMessage( this, msg );
182 
183  return;
184  }
185 
186  // Flag so user can stop work if it will result in deleted inner copper layers
187  // and still clean up this function properly.
188  bool okToProceed = true;
189 
190  PROJECT* otherPrj = m_frame->GetSettingsManager()->GetProject( projectFn.GetFullPath() );
191 
193 
194  BOARD* otherBoard = nullptr;
195 
196  try
197  {
198  WX_PROGRESS_REPORTER progressReporter( this, _( "Loading PCB" ), 1 );
199 
200  otherBoard = pi->Load( boardFn.GetFullPath(), nullptr, nullptr, nullptr,
201  &progressReporter );
202 
203  if( importDlg.m_LayersOpt->GetValue() )
204  {
205  BOARD* loadedBoard = m_frame->GetBoard();
206 
207  // Check if "Import Settings" board has more layers than the current board.
208  okToProceed = m_layers->CheckCopperLayerCount( loadedBoard, otherBoard );
209  }
210  }
211  catch( const IO_ERROR& ioe )
212  {
213  // You wouldn't think boardFn.GetFullPath() would throw, but we get a stack buffer
214  // underflow from ASAN. While it's probably an ASAN error, a second try/catch doesn't
215  // cost us much.
216  try
217  {
218  if( ioe.Problem() != wxT( "CANCEL" ) )
219  {
220  wxString msg = wxString::Format( _( "Error loading board file:\n%s" ),
221  boardFn.GetFullPath() );
222  DisplayErrorMessage( this, msg, ioe.What() );
223  }
224 
225  if( otherPrj != &m_frame->Prj() )
226  m_frame->GetSettingsManager()->UnloadProject( otherPrj, false );
227  }
228  catch(...)
229  {
230  // That was already our best-efforts
231  }
232 
233  return;
234  }
235 
236 
237  if( okToProceed )
238  {
239  otherBoard->SetProject( otherPrj );
240 
241  // If layers options are imported, import also the stackup
242  // layers options and stackup are linked, so they cannot be imported
243  // separately, and stackup can be imported only after layers options
244  if( importDlg.m_LayersOpt->GetValue() )
245  {
246  m_layers->ImportSettingsFrom( otherBoard );
247  m_physicalStackup->ImportSettingsFrom( otherBoard );
248  }
249 
250  if( importDlg.m_TextAndGraphicsOpt->GetValue() )
251  m_textAndGraphics->ImportSettingsFrom( otherBoard );
252 
253  if( importDlg.m_ConstraintsOpt->GetValue() )
254  m_constraints->ImportSettingsFrom( otherBoard );
255 
256  if( importDlg.m_NetclassesOpt->GetValue() )
258 
259  if( importDlg.m_TracksAndViasOpt->GetValue() )
260  m_tracksAndVias->ImportSettingsFrom( otherBoard );
261 
262  if( importDlg.m_MaskAndPasteOpt->GetValue() )
263  m_maskAndPaste->ImportSettingsFrom( otherBoard );
264 
265  if( importDlg.m_SeveritiesOpt->GetValue() )
267 
268  if( otherPrj != &m_frame->Prj() )
269  otherBoard->ClearProject();
270  }
271 
272  // Clean up and free memory before leaving
273  if( otherPrj != &m_frame->Prj() )
274  m_frame->GetSettingsManager()->UnloadProject( otherPrj, false );
275 
276  delete otherBoard;
277 }
void ShowMessage(const wxString &aMessage, int aFlags=wxICON_INFORMATION) override
Show the info bar with the provided message and icon.
Definition: infobar.cpp:142
virtual bool IsReadOnly() const
Definition: project.h:124
PANEL_SETUP_RULES * m_rules
Container for project specific data.
Definition: project.h:62
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition: confirm.cpp:292
SETTINGS_MANAGER * GetSettingsManager() const
This file is part of the common library.
const std::string ProjectFileExtension
void SyncCopperLayers(int aNumCopperLayers)
Called when switching to this tab to make sure that any changes to the copper layer count made on the...
PANEL_SETUP_NETCLASSES * m_netclasses
void Disable(wxWindow *aWindow)
Makes a window read-only.
Definition: ui_common.cpp:276
PCB_EDIT_FRAME * m_frame
void ImportSettingsFrom(std::map< int, SEVERITY > &aSettings)
virtual const wxString Problem() const
what was the problem?
Definition: exceptions.cpp:46
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:590
PANEL_SETUP_BOARD_STACKUP * m_physicalStackup
void OnAuxiliaryAction(wxCommandEvent &event) override
PANEL_SETUP_SEVERITIES * m_severities
void OnLayersOptionsChanged(LSET aNewLayerSet)
Must be called if the copper layers count has changed or solder mask, solder paste or silkscreen laye...
Releases a PLUGIN in the context of a potential thrown exception through its destructor.
Definition: io_mgr.h:555
bool CheckCopperLayerCount(BOARD *aWorkingBoard, BOARD *aImportedBoard)
Check and warn if inner copper layers will be deleted.
Multi-thread safe progress reporter dialog, intended for use of tasks that parallel reporting back of...
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:30
WX_INFOBAR * m_infoBar
Definition: paged_dialog.h:66
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
void ImportSettingsFrom(BOARD *aBoard)
wxTreebook * m_treebook
Definition: paged_dialog.h:62
Definition of file extensions used in Kicad.
std::vector< wxString > GetNetClassAssignmentCandidates() const
Return a list of name candidates for netclass assignment.
Definition: board.cpp:1370
#define _(s)
NETCLASSES & GetNetClasses() const
void ClearProject()
Definition: board.cpp:173
void ImportSettingsFrom(BOARD *aBoard)
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
DIALOG_BOARD_SETUP(PCB_EDIT_FRAME *aFrame)
bool LoadProject(const wxString &aFullPath, bool aSetActive=true)
Loads a project or sets up a new project with a specified path.
void SetProject(PROJECT *aProject)
Link a board to a given project.
Definition: board.cpp:143
void finishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
PANEL_SETUP_TRACKS_AND_VIAS * m_tracksAndVias
void ImportSettingsFrom(BOARD *aBoard)
PANEL_SETUP_CONSTRAINTS * m_constraints
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:190
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
std::map< int, SEVERITY > m_DRCSeverities
bool UnloadProject(PROJECT *aProject, bool aSave=true)
Saves, unloads and unregisters the given PROJECT.
static std::vector< std::reference_wrapper< RC_ITEM > > GetItemsWithSeverities()
Definition: drc_item.h:105
The main frame for Pcbnew.
PANEL_SETUP_TEXT_AND_GRAPHICS * m_textAndGraphics
PANEL_SETUP_MASK_AND_PASTE * m_maskAndPaste
PANEL_SETUP_BOARD_FINISH * m_boardFinish
PANEL_TEXT_VARIABLES * m_textVars
BOARD * GetBoard() const
void ImportSettingsFrom(NETCLASSES *aBoard)
PANEL_SETUP_LAYERS * m_layers
std::vector< bool > m_macHack
void OnPageChange(wxBookCtrlEvent &event)
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
Definition: ki_exception.h:75
PROJECT * GetProject(const wxString &aFullPath) const
Retrieves a loaded project by name.
S-expression Pcbnew file format.
Definition: io_mgr.h:56
Container for design settings for a BOARD object.