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:
48  DIALOG_RESCUE_EACH( SCH_EDIT_FRAME* aParent, RESCUER& aRescuer, bool aAskShowAgain );
49 
51 
52 private:
54  wxConfigBase* m_Config;
57 
58  bool TransferDataToWindow() override;
59  bool TransferDataFromWindow() override;
60  void PopulateConflictList();
61  void PopulateInstanceList();
62  void OnConflictSelect( wxDataViewEvent& event ) override;
63  void OnNeverShowClick( wxCommandEvent& event ) override;
64  void OnCancelClick( wxCommandEvent& event ) override;
65  void OnHandleCachePreviewRepaint( wxPaintEvent& aRepaintEvent ) override;
66  void OnHandleLibraryPreviewRepaint( wxPaintEvent& aRepaintEvent ) override;
67  void OnDialogResize( wxSizeEvent& aSizeEvent ) override;
68  void renderPreview( LIB_PART* aComponent, int aUnit, wxPanel* panel );
69 };
70 
71 
73  bool aAskShowAgain )
74  : DIALOG_RESCUE_EACH_BASE( aParent ),
75  m_Parent( aParent ),
76  m_Rescuer( &aRescuer ),
77  m_AskShowAgain( aAskShowAgain )
78 {
80  m_stdButtonsOK->SetDefault();
81 
82  // Set the info message, customized to include the proper suffix.
83  wxString info_message =
84  _( "It looks like this project was made using older schematic component libraries.\n"
85  "Some parts may need to be relinked to a different symbol name, and some symbols\n"
86  "may need to be \"rescued\" (cloned and renamed) into a new library.\n"
87  "\n"
88  "The following changes are recommended to update the project." );
89  m_lblInfo->SetLabel( info_message );
90 
91  m_componentViewOld->SetLayoutDirection( wxLayout_LeftToRight );
92  m_componentViewNew->SetLayoutDirection( wxLayout_LeftToRight );
93 }
94 
95 
97 {
98 }
99 
100 
102 {
103  if( !wxDialog::TransferDataToWindow() )
104  return false;
105 
106  m_ListOfConflicts->AppendToggleColumn( _( "Accept" ) );
107  m_ListOfConflicts->AppendTextColumn( _( "Symbol" ) );
108  m_ListOfConflicts->AppendTextColumn( _( "Action" ) );
109  m_ListOfInstances->AppendTextColumn( _( "Reference" ) );
110  m_ListOfInstances->AppendTextColumn( _( "Value" ) );
113 
114  if( !m_AskShowAgain )
115  m_btnNeverShowAgain->Hide();
116 
117  GetSizer()->Layout();
118  GetSizer()->Fit( this );
119  GetSizer()->SetSizeHints( this );
120  Centre();
121 
122  return true;
123 }
124 
125 
127 {
128  wxVector<wxVariant> data;
129  for( RESCUE_CANDIDATE& each_candidate : m_Rescuer->m_all_candidates )
130  {
131  data.clear();
132  data.push_back( wxVariant( true ) );
133  data.push_back( each_candidate.GetRequestedName() );
134  data.push_back( each_candidate.GetActionDescription() );
135 
136  m_ListOfConflicts->AppendItem( data );
137  }
138 
139  if( !m_Rescuer->m_all_candidates.empty() )
140  {
141  // Select the first choice
142  m_ListOfConflicts->SelectRow( 0 );
143  }
144 }
145 
146 
148 {
149  m_ListOfInstances->DeleteAllItems();
150 
151  int row = m_ListOfConflicts->GetSelectedRow();
152 
153  if( row == wxNOT_FOUND )
154  row = 0;
155 
156  RESCUE_CANDIDATE& selected_part = m_Rescuer->m_all_candidates[row];
157 
158  wxVector<wxVariant> data;
159  int count = 0;
160  for( SCH_COMPONENT* each_component : *m_Rescuer->GetComponents() )
161  {
162  if( each_component->GetLibId().Format() != TO_UTF8( selected_part.GetRequestedName() ) )
163  continue;
164 
165  SCH_FIELD* valueField = each_component->GetField( 1 );
166 
167  data.clear();
168  data.push_back( each_component->GetRef( & m_Parent->GetCurrentSheet() ) );
169  data.push_back( valueField ? valueField->GetText() : wxT( "" ) );
170  m_ListOfInstances->AppendItem( data );
171  count++;
172  }
173 
174  m_titleInstances->SetLabelText( wxString::Format(
175  _( "Instances of this symbol (%d items):" ), count ) );
176 }
177 
178 
179 void DIALOG_RESCUE_EACH::OnHandleCachePreviewRepaint( wxPaintEvent& aRepaintEvent )
180 {
181  int row = m_ListOfConflicts->GetSelectedRow();
182 
183  if( row == wxNOT_FOUND )
184  row = 0;
185 
186  RESCUE_CANDIDATE& selected_part = m_Rescuer->m_all_candidates[row];
187 
188  if( selected_part.GetCacheCandidate() )
189  renderPreview( selected_part.GetCacheCandidate(), 0, m_componentViewOld );
190 }
191 
192 
193 void DIALOG_RESCUE_EACH::OnHandleLibraryPreviewRepaint( wxPaintEvent& aRepaintEvent )
194 {
195  int row = m_ListOfConflicts->GetSelectedRow();
196 
197  if( row == wxNOT_FOUND )
198  row = 0;
199 
200  RESCUE_CANDIDATE& selected_part = m_Rescuer->m_all_candidates[row];
201 
202  if( selected_part.GetLibCandidate() )
203  renderPreview( selected_part.GetLibCandidate(), 0, m_componentViewNew );
204 }
205 
206 
207 void DIALOG_RESCUE_EACH::OnDialogResize( wxSizeEvent& aSizeEvent )
208 {
209  // Placeholer - I was previously doing some extra reflow here.
211 }
212 
213 
214 // Render the preview in our m_componentView. If this gets more complicated, we should
215 // probably have a derived class from wxPanel; but this keeps things local.
216 // Call it only from a Paint Event, because we are using a wxPaintDC to draw the component
217 void DIALOG_RESCUE_EACH::renderPreview( LIB_PART* aComponent, int aUnit, wxPanel* aPanel )
218 {
219  wxPaintDC dc( aPanel );
220  wxColour bgColor = m_Parent->GetDrawBgColor().ToColour();
221 
222  dc.SetBackground( wxBrush( bgColor ) );
223  dc.Clear();
224 
225  if( aComponent == NULL )
226  return;
227 
228  if( aUnit <= 0 )
229  aUnit = 1;
230 
231  const wxSize dc_size = dc.GetSize();
232  dc.SetDeviceOrigin( dc_size.x / 2, dc_size.y / 2 );
233 
234  // Find joint bounding box for everything we are about to draw.
235  EDA_RECT bBox = aComponent->GetUnitBoundingBox( aUnit, /* deMorganConvert */ 1 );
236  const double xscale = (double) dc_size.x / bBox.GetWidth();
237  const double yscale = (double) dc_size.y / bBox.GetHeight();
238  const double scale = std::min( xscale, yscale ) * 0.85;
239 
240  dc.SetUserScale( scale, scale );
241 
242  wxPoint offset = - bBox.Centre();
243 
244  // Avoid rendering when either dimension is zero
245  int width, height;
246 
247  dc.GetSize( &width, &height );
248  if( !width || !height )
249  return;
250 
251  aComponent->Draw( NULL, &dc, offset, aUnit, 1, PART_DRAW_OPTIONS::Default() );
252 }
253 
254 
255 void DIALOG_RESCUE_EACH::OnConflictSelect( wxDataViewEvent& aEvent )
256 {
257  // wxformbuilder connects this event to the _dialog_, not the data view.
258  // Make sure the correct item triggered it, otherwise we trigger recursively
259  // and get a stack overflow.
260  if( aEvent.GetEventObject() != m_ListOfConflicts )
261  return;
262 
264 
265  m_componentViewOld->Refresh();
266  m_componentViewNew->Refresh();
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( m_Parent,
291  _( "Stop showing this tool?\n"
292  "No changes will be made.\n\n"
293  "This setting can be changed from the \"Component Libraries\" dialog,\n"
294  "and the tool can be activated manually from the \"Tools\" menu." ),
295  _( "Rescue Components" ), wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION );
296  int resp = dlg.ShowModal ();
297 
298  if( resp == wxID_YES )
299  {
300  m_Config->Write( RescueNeverShowEntry, true );
302  Close();
303  }
304 }
305 
306 
307 void DIALOG_RESCUE_EACH::OnCancelClick( wxCommandEvent& aEvent )
308 {
311 }
312 
313 
314 int InvokeDialogRescueEach( SCH_EDIT_FRAME* aCaller, RESCUER& aRescuer, bool aAskShowAgain )
315 {
316  DIALOG_RESCUE_EACH dlg( aCaller, aRescuer, aAskShowAgain );
317  return dlg.ShowModal();
318 }
virtual LIB_PART * GetLibCandidate() const
Function GetLibCandidate 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
Function GetBoundingBox.
virtual LIB_PART * GetCacheCandidate() const
Function GetCacheCandidate 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
Function GetActionDescription 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:117
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
#define TO_UTF8(wxstring)
Macro TO_UTF8 converts a wxString to a UTF8 encoded C string for all wxWidgets build modes...
Definition: macros.h:47
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:565
size_t GetCandidateCount()
Function GetCandidateCount.
Class LIB_PART defines a library part object.
virtual wxString GetRequestedName() const =0
Function GetRequestedName Get the name that was originally requested in the schematic.
wxConfigBase * KifaceSettings() const
Definition: kiface_i.h:101
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:68
int GetWidth() const
std::vector< SCH_COMPONENT * > * GetComponents()
Function GetComponents.
wxDataViewListCtrl * m_ListOfConflicts
DIALOG_RESCUE_EACH(SCH_EDIT_FRAME *aParent, RESCUER &aRescuer, bool aAskShowAgain)
Constructor This dialog asks the user which rescuable, cached parts he wants to rescue.
void OnCancelClick(wxCommandEvent &event) override
Definition for part library class.
#define min(a, b)
Definition: auxiliary.h:85
wxDataViewListCtrl * m_ListOfInstances
void OnDialogResize(wxSizeEvent &aSizeEvent) override