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-2020 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_libentry.h>
26 #include <class_library.h>
28 #include <eeschema_settings.h>
29 #include <invoke_sch_dialog.h>
30 #include <kiface_i.h>
31 #include <project_rescue.h>
32 #include <sch_component.h>
33 #include <sch_edit_frame.h>
34 #include <set>
35 #include <symbol_preview_widget.h>
36 #include <vector>
37 
38 
40 {
41 public:
53  DIALOG_RESCUE_EACH( wxWindow* aParent, RESCUER& aRescuer, SCH_SHEET_PATH* aCurrentSheet,
54  EDA_DRAW_PANEL_GAL::GAL_TYPE aGalBackEndType, bool aAskShowAgain );
55 
57 
58 private:
64 
65  bool TransferDataToWindow() override;
66  bool TransferDataFromWindow() override;
67  void PopulateConflictList();
68  void PopulateInstanceList();
69  void OnConflictSelect( wxDataViewEvent& aEvent ) override;
70  void OnNeverShowClick( wxCommandEvent& aEvent ) override;
71  void OnCancelClick( wxCommandEvent& aEvent ) override;
72 
73  // Display the 2 items (old in cache and new in library) corresponding to the
74  // selected conflict in m_ListOfConflicts
76 };
77 
78 
80  RESCUER& aRescuer,
81  SCH_SHEET_PATH* aCurrentSheet,
82  EDA_DRAW_PANEL_GAL::GAL_TYPE aGalBackEndType,
83  bool aAskShowAgain )
84  : DIALOG_RESCUE_EACH_BASE( aParent ),
85  m_Rescuer( &aRescuer ),
86  m_currentSheet( aCurrentSheet ),
87  m_AskShowAgain( aAskShowAgain )
88 {
89  wxASSERT( aCurrentSheet );
90 
92  m_SizerOldPanel->Add( m_previewOldWidget, 1, wxEXPAND | wxALL, 5 );
93 
95  m_SizerNewPanel->Add( m_previewNewWidget, 1, wxEXPAND | wxALL, 5 );
96 
97  m_stdButtonsOK->SetDefault();
98 
99  // Set the info message, customized to include the proper suffix.
100  wxString info =
101  _( "This schematic was made using older symbol libraries which may break the "
102  "schematic. Some symbols may need to be linked to a different symbol name. "
103  "Some symbols may need to be \"rescued\" (copied and renamed) into a new library.\n\n"
104  "The following changes are recommended to update the project." );
105  m_htmlPrompt->AppendToPage( info );
106 
107  // wxDataViewListCtrl seems to do a poor job of laying itself out so help it along here.
108  wxString header = _( "Accept" );
109  wxFont font = m_ListOfConflicts->GetFont();
110 
111  font.MakeBold();
112 
113  wxClientDC dc( this );
114 
115  dc.SetFont( font );
116 
117  int width = dc.GetTextExtent( header ).GetWidth();
118 
119  m_ListOfConflicts->AppendToggleColumn( header, wxDATAVIEW_CELL_ACTIVATABLE, width,
120  wxALIGN_CENTER );
121 
122  header = _( "Symbol Name" );
123  width = dc.GetTextExtent( header ).GetWidth() * 2;
124  m_ListOfConflicts->AppendTextColumn( header, wxDATAVIEW_CELL_INERT, width );
125 
126  header = _( "Action Taken" );
127  width = dc.GetTextExtent( header ).GetWidth() * 10;
128  m_ListOfConflicts->AppendTextColumn( header, wxDATAVIEW_CELL_INERT, width );
129 
130  header = _( "Reference" );
131  width = dc.GetTextExtent( header ).GetWidth() * 2;
132  m_ListOfInstances->AppendTextColumn( header, wxDATAVIEW_CELL_INERT, width );
133 
134  header = _( "Value" );
135  width = dc.GetTextExtent( header ).GetWidth() * 10;
136  m_ListOfInstances->AppendTextColumn( header, wxDATAVIEW_CELL_INERT, width );
137 
138  m_previewOldWidget->SetLayoutDirection( wxLayout_LeftToRight );
139  m_previewNewWidget->SetLayoutDirection( wxLayout_LeftToRight );
140 
141  Layout();
142  SetSizeInDU( 480, 360 );
143 
144  // Make sure the HTML window is large enough. Some fun size juggling and
145  // fudge factors here but it does seem to work pretty reliably.
146  auto info_size = m_htmlPrompt->GetTextExtent( info );
147  auto prompt_size = m_htmlPrompt->GetSize();
148  auto font_size = m_htmlPrompt->GetTextExtent( "X" );
149  auto approx_info_height = ( 2 * info_size.x / prompt_size.x ) * font_size.y;
150  m_htmlPrompt->SetSizeHints( 2 * prompt_size.x / 3, approx_info_height );
151  Layout();
152  GetSizer()->SetSizeHints( this );
153  SetSizeInDU( 480, 360 );
154  Center();
155 }
156 
157 
159 {
160 }
161 
162 
164 {
165  if( !wxDialog::TransferDataToWindow() )
166  return false;
167 
170 
171  if( !m_AskShowAgain )
172  m_btnNeverShowAgain->Hide();
173 
174  return true;
175 }
176 
177 
179 {
180  wxVector<wxVariant> data;
181  for( RESCUE_CANDIDATE& each_candidate : m_Rescuer->m_all_candidates )
182  {
183  data.clear();
184  data.push_back( wxVariant( true ) );
185  data.push_back( each_candidate.GetRequestedName() );
186  data.push_back( each_candidate.GetActionDescription() );
187 
188  m_ListOfConflicts->AppendItem( data );
189  }
190 
191  if( !m_Rescuer->m_all_candidates.empty() )
192  {
193  // Select the first choice
194  m_ListOfConflicts->SelectRow( 0 );
195  // Ensure this choice is displayed:
197  }
198 }
199 
200 
202 {
203  m_ListOfInstances->DeleteAllItems();
204 
205  int row = m_ListOfConflicts->GetSelectedRow();
206 
207  if( row == wxNOT_FOUND )
208  row = 0;
209 
210  RESCUE_CANDIDATE& selected_part = m_Rescuer->m_all_candidates[row];
211 
212  wxVector<wxVariant> data;
213  int count = 0;
214 
215  for( SCH_COMPONENT* each_component : *m_Rescuer->GetComponents() )
216  {
217  if( each_component->GetLibId().Format() != UTF8( selected_part.GetRequestedName() ) )
218  continue;
219 
220  SCH_FIELD* valueField = each_component->GetField( 1 );
221 
222  data.clear();
223  data.push_back( each_component->GetRef( m_currentSheet ) );
224  data.push_back( valueField ? valueField->GetText() : wxT( "" ) );
225  m_ListOfInstances->AppendItem( data );
226  count++;
227  }
228 
229  wxString msg = wxString::Format( _( "Instances of this symbol (%d items):" ), count );
230  m_titleInstances->SetLabelText( msg );
231 }
232 
233 
235 {
236  int row = m_ListOfConflicts->GetSelectedRow();
237 
238  if( row < 0 )
239  {
240  m_previewOldWidget->DisplayPart( nullptr, 0 );
241  m_previewNewWidget->DisplayPart( nullptr, 0 );
242  }
243  else
244  {
245  RESCUE_CANDIDATE& selected_part = m_Rescuer->m_all_candidates[row];
246 
248  selected_part.GetUnit(),
249  selected_part.GetConvert() );
251  selected_part.GetUnit(),
252  selected_part.GetConvert() );
253  }
254 }
255 
256 
257 void DIALOG_RESCUE_EACH::OnConflictSelect( wxDataViewEvent& aEvent )
258 {
259  // wxformbuilder connects this event to the _dialog_, not the data view.
260  // Make sure the correct item triggered it, otherwise we trigger recursively
261  // and get a stack overflow.
262  if( aEvent.GetEventObject() != m_ListOfConflicts )
263  return;
264 
267 }
268 
269 
271 {
272  if( !wxDialog::TransferDataFromWindow() )
273  return false;
274 
275  for( size_t index = 0; index < m_Rescuer->GetCandidateCount(); ++index )
276  {
277  wxVariant val;
278  m_ListOfConflicts->GetValue( val, index, 0 );
279  bool rescue_part = val.GetBool();
280 
281  if( rescue_part )
283  }
284  return true;
285 }
286 
287 
288 void DIALOG_RESCUE_EACH::OnNeverShowClick( wxCommandEvent& aEvent )
289 {
290  wxMessageDialog dlg( GetParent(),
291  _( "Stop showing this tool?\n"
292  "No changes will be made.\n\n"
293  "This setting can be changed from the \"Symbol Libraries\" dialog,\n"
294  "and the tool can be activated manually from the \"Tools\" menu." ),
295  _( "Rescue Symbols" ), wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION );
296  int resp = dlg.ShowModal ();
297 
298  if( resp == wxID_YES )
299  {
300  auto cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
301 
302  if( cfg )
303  cfg->m_RescueNeverShow = true;
304 
306  Close();
307  }
308 }
309 
310 
311 void DIALOG_RESCUE_EACH::OnCancelClick( wxCommandEvent& aEvent )
312 {
315 }
316 
317 
318 int InvokeDialogRescueEach( wxWindow* aParent, RESCUER& aRescuer, SCH_SHEET_PATH* aCurrentSheet,
319  EDA_DRAW_PANEL_GAL::GAL_TYPE aGalBackEndType, bool aAskShowAgain )
320 {
321  DIALOG_RESCUE_EACH dlg( aParent, aRescuer, aCurrentSheet, aGalBackEndType, aAskShowAgain );
322  return dlg.ShowQuasiModal();
323 }
UTF8 is an 8 bit string that is assuredly encoded in UTF8, and supplies special conversion support to...
Definition: utf8.h:73
SCH_FIELD instances are attached to a component and provide a place for the component's value,...
Definition: sch_field.h:52
KIWAY & Kiway() const
Function Kiway returns 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
SYMBOL_PREVIEW_WIDGET * m_previewOldWidget
int ShowQuasiModal()
int GetUnit() const
KIFACE_I & Kiface()
Global KIFACE_I "get" accessor.
size_t GetCandidateCount()
Returen 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.
void SetSizeInDU(int x, int y)
Set the dialog to the given dimensions in "dialog units".
SCH_SHEET_PATH.
std::vector< RESCUE_CANDIDATE * > m_chosen_candidates
void OnConflictSelect(wxDataViewEvent &aEvent) override
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:201
#define _(s)
Definition: 3d_actions.cpp:33
Schematic symbol object.
Definition: sch_component.h:80
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:127
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