KiCad PCB EDA Suite
dialog_rescue_each.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) 2015-2021 KiCad Developers, see AUTHORS.txt for contributors.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, you may find one here:
18  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19  * or you may search the http://www.gnu.org website for the version 2 license,
20  * or you may write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22  */
23 
24 #include <class_draw_panel_gal.h>
25 #include <class_library.h>
27 #include <eeschema_settings.h>
28 #include <invoke_sch_dialog.h>
29 #include <kiface_i.h>
30 #include <project_rescue.h>
31 #include <sch_symbol.h>
32 #include <sch_edit_frame.h>
33 #include <set>
34 #include <symbol_preview_widget.h>
35 #include <vector>
36 
37 #include <wx/msgdlg.h>
38 #include <wx/dcclient.h>
39 
40 
42 {
43 public:
55  DIALOG_RESCUE_EACH( wxWindow* aParent, RESCUER& aRescuer, SCH_SHEET_PATH* aCurrentSheet,
56  EDA_DRAW_PANEL_GAL::GAL_TYPE aGalBackEndType, bool aAskShowAgain );
57 
59 
60 private:
66 
67  bool TransferDataToWindow() override;
68  bool TransferDataFromWindow() override;
69  void PopulateConflictList();
70  void PopulateInstanceList();
71  void OnConflictSelect( wxDataViewEvent& aEvent ) override;
72  void OnNeverShowClick( wxCommandEvent& aEvent ) override;
73  void OnCancelClick( wxCommandEvent& aEvent ) override;
74 
75  // Display the 2 items (old in cache and new in library) corresponding to the
76  // selected conflict in m_ListOfConflicts
78 };
79 
80 
82  RESCUER& aRescuer,
83  SCH_SHEET_PATH* aCurrentSheet,
84  EDA_DRAW_PANEL_GAL::GAL_TYPE aGalBackEndType,
85  bool aAskShowAgain )
86  : DIALOG_RESCUE_EACH_BASE( aParent ),
87  m_Rescuer( &aRescuer ),
88  m_currentSheet( aCurrentSheet ),
89  m_AskShowAgain( aAskShowAgain )
90 {
91  wxASSERT( aCurrentSheet );
92 
94  m_SizerOldPanel->Add( m_previewOldWidget, 1, wxEXPAND | wxALL, 5 );
95 
97  m_SizerNewPanel->Add( m_previewNewWidget, 1, wxEXPAND | wxALL, 5 );
98 
99  m_stdButtonsOK->SetDefault();
100 
101  // Set the info message, customized to include the proper suffix.
102  wxString info =
103  _( "This schematic was made using older symbol libraries which may break the "
104  "schematic. Some symbols may need to be linked to a different symbol name. "
105  "Some symbols may need to be \"rescued\" (copied and renamed) into a new library.\n\n"
106  "The following changes are recommended to update the project." );
107  m_htmlPrompt->AppendToPage( info );
108 
109  // wxDataViewListCtrl seems to do a poor job of laying itself out so help it along here.
110  wxString header = _( "Accept" );
111  wxFont font = m_ListOfConflicts->GetFont();
112 
113  font.MakeBold();
114 
115  wxClientDC dc( this );
116 
117  dc.SetFont( font );
118 
119  int width = dc.GetTextExtent( header ).GetWidth();
120 
121  m_ListOfConflicts->AppendToggleColumn( header, wxDATAVIEW_CELL_ACTIVATABLE, width,
122  wxALIGN_CENTER );
123 
124  header = _( "Symbol Name" );
125  width = dc.GetTextExtent( header ).GetWidth() * 2;
126  m_ListOfConflicts->AppendTextColumn( header, wxDATAVIEW_CELL_INERT, width );
127 
128  header = _( "Action Taken" );
129  width = dc.GetTextExtent( header ).GetWidth() * 10;
130  m_ListOfConflicts->AppendTextColumn( header, wxDATAVIEW_CELL_INERT, width );
131 
132  header = _( "Reference" );
133  width = dc.GetTextExtent( header ).GetWidth() * 2;
134  m_ListOfInstances->AppendTextColumn( header, wxDATAVIEW_CELL_INERT, width );
135 
136  header = _( "Value" );
137  width = dc.GetTextExtent( header ).GetWidth() * 10;
138  m_ListOfInstances->AppendTextColumn( header, wxDATAVIEW_CELL_INERT, width );
139 
140  m_previewOldWidget->SetLayoutDirection( wxLayout_LeftToRight );
141  m_previewNewWidget->SetLayoutDirection( wxLayout_LeftToRight );
142 
143  Layout();
144  setSizeInDU( 480, 360 );
145 
146  // Make sure the HTML window is large enough. Some fun size juggling and
147  // fudge factors here but it does seem to work pretty reliably.
148  auto info_size = m_htmlPrompt->GetTextExtent( info );
149  auto prompt_size = m_htmlPrompt->GetSize();
150  auto font_size = m_htmlPrompt->GetTextExtent( "X" );
151  auto approx_info_height = ( 2 * info_size.x / prompt_size.x ) * font_size.y;
152  m_htmlPrompt->SetSizeHints( 2 * prompt_size.x / 3, approx_info_height );
153  Layout();
154  GetSizer()->SetSizeHints( this );
155  setSizeInDU( 480, 360 );
156  Center();
157 }
158 
159 
161 {
162 }
163 
164 
166 {
167  if( !wxDialog::TransferDataToWindow() )
168  return false;
169 
172 
173  if( !m_AskShowAgain )
174  m_btnNeverShowAgain->Hide();
175 
176  return true;
177 }
178 
179 
181 {
182  wxVector<wxVariant> data;
183  for( RESCUE_CANDIDATE& each_candidate : m_Rescuer->m_all_candidates )
184  {
185  data.clear();
186  data.push_back( wxVariant( true ) );
187  data.push_back( each_candidate.GetRequestedName() );
188  data.push_back( each_candidate.GetActionDescription() );
189 
190  m_ListOfConflicts->AppendItem( data );
191  }
192 
193  if( !m_Rescuer->m_all_candidates.empty() )
194  {
195  // Select the first choice
196  m_ListOfConflicts->SelectRow( 0 );
197  // Ensure this choice is displayed:
199  }
200 }
201 
202 
204 {
205  m_ListOfInstances->DeleteAllItems();
206 
207  int row = m_ListOfConflicts->GetSelectedRow();
208 
209  if( row == wxNOT_FOUND )
210  row = 0;
211 
212  RESCUE_CANDIDATE& selected_part = m_Rescuer->m_all_candidates[row];
213 
214  wxVector<wxVariant> data;
215  int count = 0;
216 
217  for( SCH_COMPONENT* each_component : *m_Rescuer->GetComponents() )
218  {
219  if( each_component->GetLibId().Format() != UTF8( selected_part.GetRequestedName() ) )
220  continue;
221 
222  SCH_FIELD* valueField = each_component->GetField( VALUE_FIELD );
223 
224  data.clear();
225  data.push_back( each_component->GetRef( m_currentSheet ) );
226  data.push_back( valueField ? valueField->GetText() : wxT( "" ) );
227  m_ListOfInstances->AppendItem( data );
228  count++;
229  }
230 
231  wxString msg = wxString::Format( _( "Instances of this symbol (%d items):" ), count );
232  m_titleInstances->SetLabelText( msg );
233 }
234 
235 
237 {
238  int row = m_ListOfConflicts->GetSelectedRow();
239 
240  if( row < 0 )
241  {
242  m_previewOldWidget->DisplayPart( nullptr, 0 );
243  m_previewNewWidget->DisplayPart( nullptr, 0 );
244  }
245  else
246  {
247  RESCUE_CANDIDATE& selected_part = m_Rescuer->m_all_candidates[row];
248 
250  selected_part.GetUnit(),
251  selected_part.GetConvert() );
253  selected_part.GetUnit(),
254  selected_part.GetConvert() );
255  }
256 }
257 
258 
259 void DIALOG_RESCUE_EACH::OnConflictSelect( wxDataViewEvent& aEvent )
260 {
261  // wxformbuilder connects this event to the _dialog_, not the data view.
262  // Make sure the correct item triggered it, otherwise we trigger recursively
263  // and get a stack overflow.
264  if( aEvent.GetEventObject() != m_ListOfConflicts )
265  return;
266 
269 }
270 
271 
273 {
274  if( !wxDialog::TransferDataFromWindow() )
275  return false;
276 
277  for( size_t index = 0; index < m_Rescuer->GetCandidateCount(); ++index )
278  {
279  wxVariant val;
280  m_ListOfConflicts->GetValue( val, index, 0 );
281  bool rescue_part = val.GetBool();
282 
283  if( rescue_part )
285  }
286  return true;
287 }
288 
289 
290 void DIALOG_RESCUE_EACH::OnNeverShowClick( wxCommandEvent& aEvent )
291 {
292  wxMessageDialog dlg( GetParent(),
293  _( "Stop showing this tool?\n"
294  "No changes will be made.\n\n"
295  "This setting can be changed from the \"Symbol Libraries\" dialog,\n"
296  "and the tool can be activated manually from the \"Tools\" menu." ),
297  _( "Rescue Symbols" ), wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION );
298  int resp = dlg.ShowModal ();
299 
300  if( resp == wxID_YES )
301  {
302  auto cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
303 
304  if( cfg )
305  cfg->m_RescueNeverShow = true;
306 
308  Close();
309  }
310 }
311 
312 
313 void DIALOG_RESCUE_EACH::OnCancelClick( wxCommandEvent& aEvent )
314 {
317 }
318 
319 
320 int InvokeDialogRescueEach( wxWindow* aParent, RESCUER& aRescuer, SCH_SHEET_PATH* aCurrentSheet,
321  EDA_DRAW_PANEL_GAL::GAL_TYPE aGalBackEndType, bool aAskShowAgain )
322 {
323  DIALOG_RESCUE_EACH dlg( aParent, aRescuer, aCurrentSheet, aGalBackEndType, aAskShowAgain );
324  return dlg.ShowQuasiModal();
325 }
An 8 bit string that is assuredly encoded in UTF8, and supplies special conversion support to and fro...
Definition: utf8.h:70
Instances are attached to a symbol or sheet and provide a place for the symbol's value,...
Definition: sch_field.h:50
void setSizeInDU(int x, int y)
Set the dialog to the given dimensions in "dialog units".
KIWAY & Kiway() const
Return a reference to the KIWAY that this object has an opportunity to participate in.
Definition: kiway_holder.h:56
virtual LIB_PART * GetLibCandidate() const
Get the part the would be loaded from the libraries, if possible, or else NULL.
void DisplayPart(LIB_PART *aPart, int aUnit, int aConvert=0)
virtual wxString GetActionDescription() const =0
Get a description of the action proposed, for displaying in the UI.
virtual wxString GetRequestedName() const
Get the name that was originally requested in the schematic.
bool TransferDataFromWindow() override
Class DIALOG_RESCUE_EACH_BASE.
SCH_SHEET_PATH * m_currentSheet
int InvokeDialogRescueEach(wxWindow *aParent, RESCUER &aRescuer, SCH_SHEET_PATH *aCurrentSheet, EDA_DRAW_PANEL_GAL::GAL_TYPE aGalBackEndType, bool aAskShowAgain)
This dialog asks the user which rescuable, cached parts he wants to rescue.
int GetConvert() const
virtual void OnCancelClick(wxCommandEvent &event)
boost::ptr_vector< RESCUE_CANDIDATE > m_all_candidates
bool TransferDataToWindow() override
Field Value of part, i.e. "3.3K".
SYMBOL_PREVIEW_WIDGET * m_previewOldWidget
int ShowQuasiModal()
int GetUnit() const
KIFACE_I & Kiface()
Global KIFACE_I "get" accessor.
size_t GetCandidateCount()
Return the number of rescue candidates found.
virtual LIB_PART * GetCacheCandidate() const
Get the part that can be loaded from the project cache, if possible, or else NULL.
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
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
std::vector< RESCUE_CANDIDATE * > m_chosen_candidates
void OnConflictSelect(wxDataViewEvent &aEvent) override
#define _(s)
Definition: 3d_actions.cpp:33
Schematic symbol object.
Definition: sch_symbol.h:78
void OnNeverShowClick(wxCommandEvent &aEvent) override
std::vector< SCH_COMPONENT * > * GetComponents()
Get the list of symbols that need rescued.
void OnCancelClick(wxCommandEvent &aEvent) override
wxDataViewListCtrl * m_ListOfConflicts
Definition for part library class.
SYMBOL_PREVIEW_WIDGET * m_previewNewWidget
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:133
DIALOG_RESCUE_EACH(wxWindow *aParent, RESCUER &aRescuer, SCH_SHEET_PATH *aCurrentSheet, EDA_DRAW_PANEL_GAL::GAL_TYPE aGalBackEndType, bool aAskShowAgain)
This dialog asks the user which rescuable, cached parts he wants to rescue.
wxDataViewListCtrl * m_ListOfInstances