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-2022 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
25#include <symbol_library.h>
27#include <eeschema_settings.h>
28#include <invoke_sch_dialog.h>
29#include <kiface_base.h>
30#include <project_rescue.h>
31#include <sch_symbol.h>
32#include <sch_edit_frame.h>
33#include <set>
35#include <vector>
36
37#include <wx/msgdlg.h>
38#include <wx/dcclient.h>
39
40
42{
43public:
55 DIALOG_RESCUE_EACH( wxWindow* aParent, RESCUER& aRescuer, SCH_SHEET_PATH* aCurrentSheet,
56 EDA_DRAW_PANEL_GAL::GAL_TYPE aGalBackEndType, bool aAskShowAgain );
57
59
60private:
66
67 bool TransferDataToWindow() override;
68 bool TransferDataFromWindow() override;
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 // 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." );
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() * 1.25;
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 // Make sure the HTML window is large enough. Some fun size juggling and
142 // fudge factors here but it does seem to work pretty reliably.
143 wxSize info_size = m_htmlPrompt->GetTextExtent( info );
144 wxSize prompt_size = m_htmlPrompt->GetSize();
145 wxSize font_size = m_htmlPrompt->GetTextExtent( "X" );
146 int approx_info_height = ( 2 * info_size.x / prompt_size.x ) * font_size.y;
147 m_htmlPrompt->SetSizeHints( 2 * prompt_size.x / 3, approx_info_height );
148
150 m_stdButtonsOK->SetLabel( _( "Rescue Symbols" ) );
151 m_stdButtonsCancel->SetLabel( _( "Skip Symbol Rescue" ) );
152 m_stdButtons->Layout();
153 GetSizer()->SetSizeHints( this );
154
155 Layout();
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
184 for( RESCUE_CANDIDATE& each_candidate : m_Rescuer->m_all_candidates )
185 {
186 data.clear();
187 data.push_back( wxVariant( true ) );
188 data.push_back( each_candidate.GetRequestedName() );
189 data.push_back( each_candidate.GetActionDescription() );
190
191 m_ListOfConflicts->AppendItem( data );
192 }
193
194 if( !m_Rescuer->m_all_candidates.empty() )
195 {
196 // Select the first choice
197 m_ListOfConflicts->SelectRow( 0 );
198
199 // Ensure this choice is displayed:
201 }
202}
203
204
206{
207 m_ListOfInstances->DeleteAllItems();
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 wxVector<wxVariant> data;
217 int count = 0;
218
219 for( SCH_SYMBOL* eachSymbol : *m_Rescuer->GetSymbols() )
220 {
221 if( eachSymbol->GetLibId().Format() != UTF8( selected_part.GetRequestedName() ) )
222 continue;
223
224 SCH_FIELD* valueField = eachSymbol->GetField( VALUE_FIELD );
225
226 data.clear();
227 data.push_back( eachSymbol->GetRef( m_currentSheet ) );
228 data.push_back( valueField ? valueField->GetText() : wxT( "" ) );
229 m_ListOfInstances->AppendItem( data );
230 count++;
231 }
232
233 wxString msg = wxString::Format( _( "Instances of this symbol (%d items):" ), count );
234 m_titleInstances->SetLabelText( msg );
235}
236
237
239{
240 int row = m_ListOfConflicts->GetSelectedRow();
241
242 if( row < 0 )
243 {
244 m_previewOldWidget->DisplayPart( nullptr, 0 );
245 m_previewNewWidget->DisplayPart( nullptr, 0 );
246 }
247 else
248 {
249 RESCUE_CANDIDATE& selected_part = m_Rescuer->m_all_candidates[row];
250
252 selected_part.GetUnit(),
253 selected_part.GetConvert() );
255 selected_part.GetUnit(),
256 selected_part.GetConvert() );
257 }
258}
259
260
261void DIALOG_RESCUE_EACH::OnConflictSelect( wxDataViewEvent& aEvent )
262{
263 // wxformbuilder connects this event to the _dialog_, not the data view.
264 // Make sure the correct item triggered it, otherwise we trigger recursively
265 // and get a stack overflow.
266 if( aEvent.GetEventObject() != m_ListOfConflicts )
267 return;
268
271}
272
273
275{
276 if( !wxDialog::TransferDataFromWindow() )
277 return false;
278
279 for( size_t index = 0; index < m_Rescuer->GetCandidateCount(); ++index )
280 {
281 wxVariant val;
282 m_ListOfConflicts->GetValue( val, index, 0 );
283 bool rescue_part = val.GetBool();
284
285 if( rescue_part )
287 }
288
289 return true;
290}
291
292
293void DIALOG_RESCUE_EACH::OnNeverShowClick( wxCommandEvent& aEvent )
294{
295 wxMessageDialog dlg( GetParent(),
296 _( "Stop showing this tool?\n"
297 "No changes will be made.\n\n"
298 "This setting can be changed from the \"Symbol Libraries\" dialog,\n"
299 "and the tool can be activated manually from the \"Tools\" menu." ),
300 _( "Rescue Symbols" ), wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION );
301 int resp = dlg.ShowModal ();
302
303 if( resp == wxID_YES )
304 {
305 auto cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
306
307 if( cfg )
308 cfg->m_RescueNeverShow = true;
309
311 Close();
312 }
313}
314
315
316void DIALOG_RESCUE_EACH::OnCancelClick( wxCommandEvent& aEvent )
317{
320}
321
322
323int InvokeDialogRescueEach( wxWindow* aParent, RESCUER& aRescuer, SCH_SHEET_PATH* aCurrentSheet,
324 EDA_DRAW_PANEL_GAL::GAL_TYPE aGalBackEndType, bool aAskShowAgain )
325{
326 DIALOG_RESCUE_EACH dlg( aParent, aRescuer, aCurrentSheet, aGalBackEndType, aAskShowAgain );
327 return dlg.ShowQuasiModal();
328}
KIFACE_BASE & Kiface()
Global KIFACE_BASE "get" accessor.
Class DIALOG_RESCUE_EACH_BASE.
virtual void OnCancelClick(wxCommandEvent &event)
wxDataViewListCtrl * m_ListOfConflicts
wxDataViewListCtrl * m_ListOfInstances
wxStdDialogButtonSizer * m_stdButtons
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.
void OnNeverShowClick(wxCommandEvent &aEvent) override
bool TransferDataToWindow() override
void OnCancelClick(wxCommandEvent &aEvent) override
SYMBOL_PREVIEW_WIDGET * m_previewNewWidget
bool TransferDataFromWindow() override
void OnConflictSelect(wxDataViewEvent &aEvent) override
SYMBOL_PREVIEW_WIDGET * m_previewOldWidget
SCH_SHEET_PATH * m_currentSheet
void SetupStandardButtons(std::map< int, wxString > aLabels={})
int ShowQuasiModal()
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:87
bool AppendToPage(const wxString &aSource)
Definition: html_window.cpp:57
APP_SETTINGS_BASE * KifaceSettings() const
Definition: kiface_base.h:93
KIWAY & Kiway() const
Return a reference to the KIWAY that this object has an opportunity to participate in.
Definition: kiway_holder.h:53
std::vector< RESCUE_CANDIDATE * > m_chosen_candidates
std::vector< SCH_SYMBOL * > * GetSymbols()
Get the list of symbols that need rescued.
size_t GetCandidateCount()
Return the number of rescue candidates found.
boost::ptr_vector< RESCUE_CANDIDATE > m_all_candidates
virtual wxString GetActionDescription() const =0
Get a description of the action proposed, for displaying in the UI.
int GetUnit() const
virtual LIB_SYMBOL * GetCacheCandidate() const
Get the part that can be loaded from the project cache, if possible, or else NULL.
virtual wxString GetRequestedName() const
Get the name that was originally requested in the schematic.
int GetConvert() const
virtual LIB_SYMBOL * GetLibCandidate() const
Get the part the would be loaded from the libraries, if possible, or else NULL.
Instances are attached to a symbol or sheet and provide a place for the symbol's value,...
Definition: sch_field.h:51
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
Schematic symbol object.
Definition: sch_symbol.h:81
void DisplayPart(LIB_SYMBOL *aSymbol, int aUnit, int aConvert=0)
An 8 bit string that is assuredly encoded in UTF8, and supplies special conversion support to and fro...
Definition: utf8.h:71
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.
#define _(s)
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
Definition for symbol library class.
@ VALUE_FIELD
Field Value of part, i.e. "3.3K".