KiCad PCB EDA Suite
Loading...
Searching...
No Matches
dialog_resolve_field_case_conflicts.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 The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or (at your
9 * option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
21
22#include <sch_edit_frame.h>
23#include <sch_symbol.h>
24#include <sch_commit.h>
25#include <wx/grid.h>
26
27
29 wxWindow* aParent, SCH_EDIT_FRAME* aFrame,
30 std::vector<FIELD_CASE_CONFLICT> aConflicts ) :
32 m_frame( aFrame ),
33 m_conflicts( std::move( aConflicts ) ),
35{
36 m_conflictsGrid->SetSelectionMode( wxGrid::wxGridSelectRows );
37
38 m_headerLabel->SetLabel( wxString::Format(
39 _( "%zu symbols have user fields whose names differ only in case. "
40 "Choose how to resolve each before opening the table." ),
41 m_conflicts.size() ) );
42
44
45 SetupStandardButtons( { { wxID_OK, _( "Apply and Continue" ) },
46 { wxID_CANCEL, _( "Cancel" ) } } );
47
49}
50
51
53{
54 wxGrid* g = m_conflictsGrid;
55 g->BeginBatch();
56
57 if( g->GetNumberRows() > 0 )
58 g->DeleteRows( 0, g->GetNumberRows() );
59
60 g->AppendRows( static_cast<int>( m_conflicts.size() ) );
61
62 for( size_t i = 0; i < m_conflicts.size(); ++i )
63 {
64 const FIELD_CASE_CONFLICT& c = m_conflicts[i];
65
66 g->SetCellValue( i, 0, c.reference );
67 g->SetCellValue( i, 1, c.sheetPath.PathHumanReadable( false ) );
68
69 wxString fieldsLabel = wxString::Format( "%s\n%s",
70 c.variants[0].first,
71 c.variants[1].first );
72
73 wxString valuesLabel = wxString::Format( "%s\n%s",
74 c.variants[0].second.IsEmpty()
75 ? wxString( _( "(empty)" ) )
76 : c.variants[0].second,
77 c.variants[1].second.IsEmpty()
78 ? wxString( _( "(empty)" ) )
79 : c.variants[1].second );
80
81 g->SetCellValue( i, 2, fieldsLabel );
82 g->SetCellValue( i, 3, valuesLabel );
83
84 wxArrayString choices;
85 choices.Add( wxString::Format( _( "Keep '%s'" ), c.variants[0].first ) );
86 choices.Add( wxString::Format( _( "Keep '%s'" ), c.variants[1].first ) );
87 choices.Add( _( "Join values" ) );
88
89 g->SetCellEditor( i, 4, new wxGridCellChoiceEditor( choices, false ) );
90 g->SetCellValue( i, 4, choices[0] );
91 }
92
93 g->AutoSizeRows();
94 g->EndBatch();
95}
96
97
98std::vector<int>
100{
101 std::vector<int> siblings;
102
103 if( aRow < 0 || static_cast<size_t>( aRow ) >= m_conflicts.size() )
104 return siblings;
105
106 const wxString& key = m_conflicts[aRow].caseFoldedKey;
107
108 for( size_t i = 0; i < m_conflicts.size(); ++i )
109 {
110 if( static_cast<int>( i ) != aRow
111 && m_conflicts[i].caseFoldedKey.IsSameAs( key, false ) )
112 {
113 siblings.push_back( static_cast<int>( i ) );
114 }
115 }
116
117 return siblings;
118}
119
120
122{
123 int row = event.GetRow();
124 int col = event.GetCol();
125
126 if( col != 4 || row < 0 || static_cast<size_t>( row ) >= m_conflicts.size() )
127 {
128 event.Skip();
129 return;
130 }
131
132 wxString choice = m_conflictsGrid->GetCellValue( row, 4 );
133 ACTION action = ACTION_KEEP_FIRST;
134
135 if( choice.Contains( m_conflicts[row].variants[1].first ) )
136 action = ACTION_KEEP_SECOND;
137 else if( choice == _( "Join values" ) )
138 action = ACTION_JOIN;
139
140 m_rowAction[row] = action;
141
142 if( m_bulkApplyCheckbox->IsChecked() )
143 {
144 for( int sibling : findSiblingRows( row ) )
145 {
146 m_rowAction[sibling] = action;
147 m_conflictsGrid->SetCellValue( sibling, 4, choice );
148 }
149 }
150
151 event.Skip();
152}
153
154
156{
158 EndModal( wxID_OK );
159}
160
161
163{
164 SCH_COMMIT commit( m_frame );
165 wxString sep = m_separatorCtrl->GetValue();
166
167 for( size_t i = 0; i < m_conflicts.size(); ++i )
168 {
170 SCH_SYMBOL* sym = c.symbol;
171
172 commit.Modify( sym, c.sheetPath.LastScreen() );
173
174 SCH_FIELD* a = sym->GetField( c.variants[0].first );
175 SCH_FIELD* b = sym->GetField( c.variants[1].first );
176
177 if( !a || !b || a == b )
178 continue;
179
180 const wxString& aValue = c.variants[0].second;
181 const wxString& bValue = c.variants[1].second;
182
183 switch( m_rowAction[i] )
184 {
186 {
187 wxString winning = aValue.IsEmpty() ? bValue : aValue;
188 a->SetText( winning );
189 sym->RemoveField( c.variants[1].first );
190 break;
191 }
193 {
194 wxString winning = bValue.IsEmpty() ? aValue : bValue;
195 b->SetText( winning );
196 sym->RemoveField( c.variants[0].first );
197 break;
198 }
199 case ACTION_JOIN:
200 {
201 wxString joined;
202
203 if( !aValue.IsEmpty() && !bValue.IsEmpty() )
204 joined = aValue + sep + bValue;
205 else
206 joined = aValue.IsEmpty() ? bValue : aValue;
207
208 a->SetText( joined );
209 sym->RemoveField( c.variants[1].first );
210 break;
211 }
212 }
213 }
214
215 commit.Push( _( "Resolve duplicate field names" ) );
216}
COMMIT & Modify(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr, RECURSE_MODE aRecurse=RECURSE_MODE::NO_RECURSE)
Modify a given item in the model.
Definition commit.h:106
DIALOG_RESOLVE_FIELD_CASE_CONFLICTS_BASE(wxWindow *parent, wxWindowID id=wxID_ANY, const wxString &title=_("Resolve Field Name Conflicts"), const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize, long style=wxDEFAULT_DIALOG_STYLE)
DIALOG_RESOLVE_FIELD_CASE_CONFLICTS(wxWindow *aParent, SCH_EDIT_FRAME *aFrame, std::vector< FIELD_CASE_CONFLICT > aConflicts)
void onApplyAndContinue(wxCommandEvent &event) override
void SetupStandardButtons(std::map< int, wxString > aLabels={})
void finishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
virtual void Push(const wxString &aMessage=wxT("A commit"), int aCommitFlags=0) override
Execute the changes.
Schematic editor (Eeschema) main window.
void SetText(const wxString &aText) override
SCH_SCREEN * LastScreen()
wxString PathHumanReadable(bool aUseShortRootName=true, bool aStripTrailingSeparator=false, bool aEscapeSheetNames=false) const
Return the sheet path in a human readable form made from the sheet names.
Schematic symbol object.
Definition sch_symbol.h:76
void RemoveField(const wxString &aFieldName)
Remove a user field from the symbol.
SCH_FIELD * GetField(FIELD_T aFieldType)
Return a mandatory field in this symbol.
#define _(s)
STL namespace.
SCH_SHEET_PATH sheetPath
std::vector< std::pair< wxString, wxString > > variants