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-2019 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 <sch_edit_frame.h>
25 #include <sch_component.h>
26 #include <invoke_sch_dialog.h>
28 #include <kiface_i.h>
29 #include <class_library.h>
30 #include <class_libentry.h>
31 #include <set>
32 #include <vector>
33 #include <project_rescue.h>
34 #include <eeschema_config.h>
35 #include <symbol_preview_widget.h>
36 #include <class_draw_panel_gal.h>
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:
61  wxConfigBase* m_Config;
65 
66  bool TransferDataToWindow() override;
67  bool TransferDataFromWindow() override;
68  void PopulateConflictList();
69  void PopulateInstanceList();
70  void OnConflictSelect( wxDataViewEvent& aEvent ) override;
71  void OnNeverShowClick( wxCommandEvent& aEvent ) override;
72  void OnCancelClick( wxCommandEvent& aEvent ) override;
73 
74  // Display the 2 items (old in cache and new in library) corresponding to the
75  // selected conflict in m_ListOfConflicts
77 };
78 
79 
81  RESCUER& aRescuer,
82  SCH_SHEET_PATH* aCurrentSheet,
83  EDA_DRAW_PANEL_GAL::GAL_TYPE aGalBackEndType,
84  bool aAskShowAgain )
85  : DIALOG_RESCUE_EACH_BASE( aParent ),
86  m_Rescuer( &aRescuer ),
87  m_currentSheet( aCurrentSheet ),
88  m_AskShowAgain( aAskShowAgain )
89 {
90  wxASSERT( aCurrentSheet );
91 
93  m_SizerOldPanel->Add( m_previewOldWidget, 1, wxEXPAND | wxALL, 5 );
94 
96  m_SizerNewPanel->Add( m_previewNewWidget, 1, wxEXPAND | wxALL, 5 );
97 
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( 1 );
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  m_previewOldWidget->DisplayPart( selected_part.GetCacheCandidate(), 0 );
249  m_previewNewWidget->DisplayPart( selected_part.GetLibCandidate(), 0 );
250  }
251 }
252 
253 
254 void DIALOG_RESCUE_EACH::OnConflictSelect( wxDataViewEvent& aEvent )
255 {
256  // wxformbuilder connects this event to the _dialog_, not the data view.
257  // Make sure the correct item triggered it, otherwise we trigger recursively
258  // and get a stack overflow.
259  if( aEvent.GetEventObject() != m_ListOfConflicts )
260  return;
261 
264 }
265 
266 
268 {
269  if( !wxDialog::TransferDataFromWindow() )
270  return false;
271 
272  for( size_t index = 0; index < m_Rescuer->GetCandidateCount(); ++index )
273  {
274  wxVariant val;
275  m_ListOfConflicts->GetValue( val, index, 0 );
276  bool rescue_part = val.GetBool();
277 
278  if( rescue_part )
280  }
281  return true;
282 }
283 
284 
285 void DIALOG_RESCUE_EACH::OnNeverShowClick( wxCommandEvent& aEvent )
286 {
287  wxMessageDialog dlg( GetParent(),
288  _( "Stop showing this tool?\n"
289  "No changes will be made.\n\n"
290  "This setting can be changed from the \"Symbol Libraries\" dialog,\n"
291  "and the tool can be activated manually from the \"Tools\" menu." ),
292  _( "Rescue Symbols" ), wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION );
293  int resp = dlg.ShowModal ();
294 
295  if( resp == wxID_YES )
296  {
297  m_Config->Write( RescueNeverShowEntry, true );
299  Close();
300  }
301 }
302 
303 
304 void DIALOG_RESCUE_EACH::OnCancelClick( wxCommandEvent& aEvent )
305 {
308 }
309 
310 
311 int InvokeDialogRescueEach( wxWindow* aParent, RESCUER& aRescuer, SCH_SHEET_PATH* aCurrentSheet,
312  EDA_DRAW_PANEL_GAL::GAL_TYPE aGalBackEndType, bool aAskShowAgain )
313 {
314  DIALOG_RESCUE_EACH dlg( aParent, aRescuer, aCurrentSheet, aGalBackEndType, aAskShowAgain );
315  return dlg.ShowQuasiModal();
316 }
Class UTF8 is an 8 bit string that is assuredly encoded in UTF8, and supplies special conversion supp...
Definition: utf8.h:73
Class SCH_FIELD instances are attached to a component and provide a place for the component's value,...
Definition: sch_field.h:56
KIWAY & Kiway() const
Function Kiway returns a reference to the KIWAY that this object has an opportunity to participate in...
Definition: kiway_player.h:60
virtual LIB_PART * GetLibCandidate() const
Get the part the would be loaded from the libraries, if possible, or else NULL.
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.
wxConfigBase * KifaceSettings() const
Definition: kiface_i.h:103
bool TransferDataFromWindow() override
Class DIALOG_RESCUE_EACH_BASE.
const wxChar RescueNeverShowEntry[]
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.
virtual void OnCancelClick(wxCommandEvent &event)
KIFACE_I & Kiface()
Global KIFACE_I "get" accessor.
Definition: kicad.cpp:52
boost::ptr_vector< RESCUE_CANDIDATE > m_all_candidates
bool TransferDataToWindow() override
const wxString & GetText() const
Function GetText returns the string associated with the text object.
Definition: eda_text.h:143
SYMBOL_PREVIEW_WIDGET * m_previewOldWidget
int ShowQuasiModal()
Class LIB_ITEM definition.
void DisplayPart(LIB_PART *aPart, int aUnit)
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".
Class SCH_SHEET_PATH.
Definition the SCH_COMPONENT class for Eeschema.
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:205
Class SCH_COMPONENT describes a real schematic component.
Definition: sch_component.h:70
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
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