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-2016 Chris Pavlina <pavlina.chris@gmail.com>
5  * Copyright (C) 2015-2017 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
25 #include <schframe.h>
26 #include <sch_component.h>
27 #include <invoke_sch_dialog.h>
29 #include <kiface_i.h>
30 #include <class_library.h>
31 #include <class_libentry.h>
32 #include <set>
33 #include <vector>
34 #include <project_rescue.h>
35 #include <eeschema_config.h>
36 
38 {
39 public:
49  DIALOG_RESCUE_EACH( SCH_EDIT_FRAME* aParent, RESCUER& aRescuer, bool aAskShowAgain );
50 
52 
53 private:
55  wxConfigBase* m_Config;
58 
59  bool TransferDataToWindow() override;
60  bool TransferDataFromWindow() override;
61  void PopulateConflictList();
62  void PopulateInstanceList();
63  void OnConflictSelect( wxDataViewEvent& event ) override;
64  void OnNeverShowClick( wxCommandEvent& event ) override;
65  void OnCancelClick( wxCommandEvent& event ) override;
66  void OnHandleCachePreviewRepaint( wxPaintEvent& aRepaintEvent ) override;
67  void OnHandleLibraryPreviewRepaint( wxPaintEvent& aRepaintEvent ) override;
68  void OnDialogResize( wxSizeEvent& aSizeEvent ) override;
69  void renderPreview( LIB_PART* aComponent, int aUnit, wxPanel* panel );
70 };
71 
72 
74  bool aAskShowAgain )
75  : DIALOG_RESCUE_EACH_BASE( aParent ),
76  m_Parent( aParent ),
77  m_Rescuer( &aRescuer ),
78  m_AskShowAgain( aAskShowAgain )
79 {
81  m_stdButtonsOK->SetDefault();
82 
83  // Set the info message, customized to include the proper suffix.
84  wxString info =
85  _( "This schematic was made using older symbol libraries which may break the "
86  "schematic. Some symbols may need to be linked to a different symbol name. "
87  "Some symbols may need to be \"rescued\" (copied and renamed) into a new library.\n\n"
88  "The following changes are recommended to update the project." );
89  m_htmlPrompt->AppendToPage( info );
90 
91  // wxDataViewListCtrl seems to do a poor job of laying itself out so help it along here.
92  wxString header = _( "Accept" );
93  wxFont font = m_ListOfConflicts->GetFont();
94 
95  font.MakeBold();
96 
97  wxClientDC dc( this );
98 
99  dc.SetFont( font );
100 
101  int padding = 30;
102  int width = dc.GetTextExtent( header ).GetWidth();
103 
104  m_ListOfConflicts->AppendToggleColumn( header, wxDATAVIEW_CELL_ACTIVATABLE, width,
105  wxALIGN_CENTER );
106 
107  header = _( "Symbol Name" );
108  width = dc.GetTextExtent( header ).GetWidth() + padding;
109  m_ListOfConflicts->AppendTextColumn( header, wxDATAVIEW_CELL_INERT, width );
110 
111  header = _( "Action Taken" );
112  width = dc.GetTextExtent( header ).GetWidth() + padding;
113  m_ListOfConflicts->AppendTextColumn( header, wxDATAVIEW_CELL_INERT, width );
114 
115  header = _( "Reference" );
116  width = dc.GetTextExtent( header ).GetWidth() + padding;
117  m_ListOfInstances->AppendTextColumn( header, wxDATAVIEW_CELL_INERT, width );
118 
119  header = _( "Value" );
120  width = dc.GetTextExtent( header ).GetWidth() + padding;
121  m_ListOfInstances->AppendTextColumn( header, wxDATAVIEW_CELL_INERT, width );
122 
123  m_componentViewOld->SetLayoutDirection( wxLayout_LeftToRight );
124  m_componentViewNew->SetLayoutDirection( wxLayout_LeftToRight );
125 }
126 
127 
129 {
130 }
131 
132 
134 {
135  if( !wxDialog::TransferDataToWindow() )
136  return false;
137 
140 
141  if( !m_AskShowAgain )
142  m_btnNeverShowAgain->Hide();
143 
144  GetSizer()->Layout();
145  GetSizer()->Fit( this );
146  GetSizer()->SetSizeHints( this );
147  Centre();
148 
149  return true;
150 }
151 
152 
154 {
155  wxVector<wxVariant> data;
156  for( RESCUE_CANDIDATE& each_candidate : m_Rescuer->m_all_candidates )
157  {
158  data.clear();
159  data.push_back( wxVariant( true ) );
160  data.push_back( each_candidate.GetRequestedName() );
161  data.push_back( each_candidate.GetActionDescription() );
162 
163  m_ListOfConflicts->AppendItem( data );
164  }
165 
166  if( !m_Rescuer->m_all_candidates.empty() )
167  {
168  // Select the first choice
169  m_ListOfConflicts->SelectRow( 0 );
170  }
171 }
172 
173 
175 {
176  m_ListOfInstances->DeleteAllItems();
177 
178  int row = m_ListOfConflicts->GetSelectedRow();
179 
180  if( row == wxNOT_FOUND )
181  row = 0;
182 
183  RESCUE_CANDIDATE& selected_part = m_Rescuer->m_all_candidates[row];
184 
185  wxVector<wxVariant> data;
186  int count = 0;
187 
188  for( SCH_COMPONENT* each_component : *m_Rescuer->GetComponents() )
189  {
190  if( each_component->GetLibId().Format() != UTF8( selected_part.GetRequestedName() ) )
191  continue;
192 
193  SCH_FIELD* valueField = each_component->GetField( 1 );
194 
195  data.clear();
196  data.push_back( each_component->GetRef( & m_Parent->GetCurrentSheet() ) );
197  data.push_back( valueField ? valueField->GetText() : wxT( "" ) );
198  m_ListOfInstances->AppendItem( data );
199  count++;
200  }
201 
202  m_titleInstances->SetLabelText( wxString::Format(
203  _( "Instances of this symbol (%d items):" ), count ) );
204 }
205 
206 
207 void DIALOG_RESCUE_EACH::OnHandleCachePreviewRepaint( wxPaintEvent& aRepaintEvent )
208 {
209  int row = m_ListOfConflicts->GetSelectedRow();
210 
211  if( row == wxNOT_FOUND )
212  row = 0;
213 
214  RESCUE_CANDIDATE& selected_part = m_Rescuer->m_all_candidates[row];
215 
216  if( selected_part.GetCacheCandidate() )
217  renderPreview( selected_part.GetCacheCandidate(), 0, m_componentViewOld );
218 }
219 
220 
221 void DIALOG_RESCUE_EACH::OnHandleLibraryPreviewRepaint( wxPaintEvent& aRepaintEvent )
222 {
223  int row = m_ListOfConflicts->GetSelectedRow();
224 
225  if( row == wxNOT_FOUND )
226  row = 0;
227 
228  RESCUE_CANDIDATE& selected_part = m_Rescuer->m_all_candidates[row];
229 
230  if( selected_part.GetLibCandidate() )
231  renderPreview( selected_part.GetLibCandidate(), 0, m_componentViewNew );
232 }
233 
234 
235 void DIALOG_RESCUE_EACH::OnDialogResize( wxSizeEvent& aSizeEvent )
236 {
237  // Placeholder - I was previously doing some extra reflow here.
239 }
240 
241 
242 // Render the preview in our m_componentView. If this gets more complicated, we should
243 // probably have a derived class from wxPanel; but this keeps things local.
244 // Call it only from a Paint Event, because we are using a wxPaintDC to draw the component
245 void DIALOG_RESCUE_EACH::renderPreview( LIB_PART* aComponent, int aUnit, wxPanel* aPanel )
246 {
247  wxPaintDC dc( aPanel );
248  wxColour bgColor = m_Parent->GetDrawBgColor().ToColour();
249 
250  dc.SetBackground( wxBrush( bgColor ) );
251  dc.Clear();
252 
253  if( aComponent == NULL )
254  return;
255 
256  if( aUnit <= 0 )
257  aUnit = 1;
258 
259  const wxSize dc_size = dc.GetSize();
260  dc.SetDeviceOrigin( dc_size.x / 2, dc_size.y / 2 );
261 
262  // Find joint bounding box for everything we are about to draw.
263  EDA_RECT bBox = aComponent->GetUnitBoundingBox( aUnit, /* deMorganConvert */ 1 );
264  const double xscale = (double) dc_size.x / bBox.GetWidth();
265  const double yscale = (double) dc_size.y / bBox.GetHeight();
266  const double scale = std::min( xscale, yscale ) * 0.85;
267 
268  dc.SetUserScale( scale, scale );
269 
270  wxPoint offset = - bBox.Centre();
271 
272  // Avoid rendering when either dimension is zero
273  int width, height;
274 
275  dc.GetSize( &width, &height );
276  if( !width || !height )
277  return;
278 
279  aComponent->Draw( NULL, &dc, offset, aUnit, 1, PART_DRAW_OPTIONS::Default() );
280 }
281 
282 
283 void DIALOG_RESCUE_EACH::OnConflictSelect( wxDataViewEvent& aEvent )
284 {
285  // wxformbuilder connects this event to the _dialog_, not the data view.
286  // Make sure the correct item triggered it, otherwise we trigger recursively
287  // and get a stack overflow.
288  if( aEvent.GetEventObject() != m_ListOfConflicts )
289  return;
290 
292 
293  m_componentViewOld->Refresh();
294  m_componentViewNew->Refresh();
295 }
296 
297 
299 {
300  if( !wxDialog::TransferDataFromWindow() )
301  return false;
302 
303  for( size_t index = 0; index < m_Rescuer->GetCandidateCount(); ++index )
304  {
305  wxVariant val;
306  m_ListOfConflicts->GetValue( val, index, 0 );
307  bool rescue_part = val.GetBool();
308 
309  if( rescue_part )
311  }
312  return true;
313 }
314 
315 
316 void DIALOG_RESCUE_EACH::OnNeverShowClick( wxCommandEvent& aEvent )
317 {
318  wxMessageDialog dlg( m_Parent,
319  _( "Stop showing this tool?\n"
320  "No changes will be made.\n\n"
321  "This setting can be changed from the \"Symbol Libraries\" dialog,\n"
322  "and the tool can be activated manually from the \"Tools\" menu." ),
323  _( "Rescue Symbols" ), wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION );
324  int resp = dlg.ShowModal ();
325 
326  if( resp == wxID_YES )
327  {
328  m_Config->Write( RescueNeverShowEntry, true );
330  Close();
331  }
332 }
333 
334 
335 void DIALOG_RESCUE_EACH::OnCancelClick( wxCommandEvent& aEvent )
336 {
339 }
340 
341 
342 int InvokeDialogRescueEach( SCH_EDIT_FRAME* aCaller, RESCUER& aRescuer, bool aAskShowAgain )
343 {
344  DIALOG_RESCUE_EACH dlg( aCaller, aRescuer, aAskShowAgain );
345  return dlg.ShowModal();
346 }
Class UTF8 is an 8 bit string that is assuredly encoded in UTF8, and supplies special conversion supp...
Definition: utf8.h:73
virtual LIB_PART * GetLibCandidate() const
Get the part the would be loaded from the libraries, if possible, or else NULL.
Class SCH_FIELD instances are attached to a component and provide a place for the component's value...
Definition: sch_field.h:56
void Draw(EDA_DRAW_PANEL *aPanel, wxDC *aDc, const wxPoint &aOffset, int aMulti, int aConvert, const PART_DRAW_OPTIONS &aOpts)
Draw part.
const EDA_RECT GetUnitBoundingBox(int aUnit, int aConvert) const
Get the bounding box for the symbol.
virtual LIB_PART * GetCacheCandidate() const
Get the part that can be loaded from the project cache, if possible, or else NULL.
SCH_EDIT_FRAME * m_Parent
virtual wxString GetActionDescription() const =0
Get a description of the action proposed, for displaying in the UI.
void OnNeverShowClick(wxCommandEvent &event) override
bool TransferDataFromWindow() override
Class DIALOG_RESCUE_EACH_BASE.
int GetHeight() const
const wxChar RescueNeverShowEntry[]
int InvokeDialogRescueEach(SCH_EDIT_FRAME *aCaller, RESCUER &aRescuer, bool aAskShowAgain)
Function InvokeDialogRescueEach This dialog asks the user which rescuable, cached parts he wants to r...
Schematic editor (Eeschema) main window.
Definition: schframe.h:118
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
void OnHandleCachePreviewRepaint(wxPaintEvent &aRepaintEvent) override
Class LIB_ITEM definition.
const wxString & GetText() const
Function GetText returns the string associated with the text object.
Definition: eda_text.h:130
SCH_SHEET_PATH & GetCurrentSheet()
Definition: schframe.cpp:577
size_t GetCandidateCount()
Returen the number of rescue candidates found.
Define a library symbol object.
wxConfigBase * KifaceSettings() const
Definition: kiface_i.h:103
void OnHandleLibraryPreviewRepaint(wxPaintEvent &aRepaintEvent) override
wxPoint Centre() const
static PART_DRAW_OPTIONS Default()
COLOR4D GetDrawBgColor() const override
void renderPreview(LIB_PART *aComponent, int aUnit, wxPanel *panel)
Definition the SCH_COMPONENT class for Eeschema.
std::vector< RESCUE_CANDIDATE * > m_chosen_candidates
const int scale
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
virtual void OnDialogResize(wxSizeEvent &event)
void OnConflictSelect(wxDataViewEvent &event) override
Class EDA_RECT handles the component boundary box.
Class SCH_COMPONENT describes a real schematic component.
Definition: sch_component.h:69
int GetWidth() const
std::vector< SCH_COMPONENT * > * GetComponents()
Get the list of symbols that need rescued.
wxDataViewListCtrl * m_ListOfConflicts
DIALOG_RESCUE_EACH(SCH_EDIT_FRAME *aParent, RESCUER &aRescuer, bool aAskShowAgain)
This dialog asks the user which rescuable, cached parts he wants to rescue.
void OnCancelClick(wxCommandEvent &event) override
Definition for part library class.
virtual wxString GetRequestedName() const
Get the name that was originally requested in the schematic.
#define min(a, b)
Definition: auxiliary.h:85
wxDataViewListCtrl * m_ListOfInstances
void OnDialogResize(wxSizeEvent &aSizeEvent) override