KiCad PCB EDA Suite
Loading...
Searching...
No Matches
lib_table_grid_data_model.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#include <string_utils.h>
23#include <widgets/grid_button.h>
24#include <bitmaps.h>
26
27
29 const LIBRARY_TABLE& aTableToEdit,
31 const wxArrayString& aPluginChoices,
32 wxString* aMRUDirectory, const wxString& aProjectPath ) :
33 m_table( aTableToEdit ),
34 m_readOnly( m_table.IsReadOnly() ),
35 m_adapter( aAdapter )
36{
37 m_uriEditor = new wxGridCellAttr;
38 m_uriEditor->SetEditor( new GRID_CELL_PATH_EDITOR( aDialog, aGrid, aMRUDirectory, !aProjectPath.IsEmpty(),
39 aProjectPath,
40 [this]( WX_GRID* aCurrGrid, int aRow ) -> wxString
41 {
42 return getFileTypes( aCurrGrid, aRow );
43 } ) );
44
45 m_typesEditor = new wxGridCellAttr;
46 m_typesEditor->SetEditor( new wxGridCellChoiceEditor( aPluginChoices ) );
47
48 m_boolAttr = new wxGridCellAttr;
49 m_boolAttr->SetRenderer( new wxGridCellBoolRenderer() );
50 m_boolAttr->SetReadOnly(); // not really; we delegate interactivity to GRID_TRICKS
51 m_boolAttr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
52
53 m_readOnlyAttr = new wxGridCellAttr;
54 m_readOnlyAttr->SetReadOnly();
55
56 m_warningAttr = new wxGridCellAttr;
58 m_warningAttr->SetReadOnly();
59 m_warningAttr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
60
61 m_noStatusAttr = new wxGridCellAttr;
62 m_noStatusAttr->SetReadOnly();
63 m_noStatusAttr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
64
65 m_editSettingsAttr = new wxGridCellAttr;
67 m_editSettingsAttr->SetReadOnly(); // not really; we delegate interactivity to GRID_TRICKS
68 m_editSettingsAttr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
69
70 m_openTableAttr = new wxGridCellAttr;
72 m_openTableAttr->SetReadOnly(); // not really; we delegate interactivity to GRID_TRICKS
73 m_openTableAttr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
74}
75
76
78{
79 m_uriEditor->DecRef();
80 m_typesEditor->DecRef();
81 m_boolAttr->DecRef();
82 m_readOnlyAttr->DecRef();
83 m_warningAttr->DecRef();
84 m_noStatusAttr->DecRef();
85 m_editSettingsAttr->DecRef();
86 m_openTableAttr->DecRef();
87}
88
89
90bool LIB_TABLE_GRID_DATA_MODEL::badCoords( int aRow, int aCol )
91{
92 if( aRow < 0 || aRow >= (int) size() )
93 return true;
94
95 if( aCol < 0 || aCol >= GetNumberCols() )
96 return true;
97
98 return false;
99}
100
101
102wxString LIB_TABLE_GRID_DATA_MODEL::GetValue( int aRow, int aCol )
103{
104 if( badCoords( aRow, aCol ) )
105 return wxEmptyString;
106
107 const LIBRARY_TABLE_ROW& r = at( aRow );
108
109 switch( aCol )
110 {
111 case COL_NICKNAME: return UnescapeString( r.Nickname() );
112 case COL_URI: return r.URI();
113 case COL_TYPE: return r.Type();
114 case COL_OPTIONS: return r.Options();
115 case COL_DESCR: return r.Description();
116 case COL_ENABLED: return r.Disabled() ? wxT( "0" ) : wxT( "1" );
117 case COL_VISIBLE: return r.Hidden() ? wxT( "0" ) : wxT( "1" );
118
119 case COL_STATUS:
120 if( !r.IsOk() )
121 return r.ErrorDescription();
122
123 if( m_adapter->SupportsConfigurationDialog( r.Nickname() ) )
124 return _( "Edit settings" );
126 return _( "Open library table" );
127
128 return wxEmptyString;
129
130 default:
131 return wxEmptyString;
132 }
133}
134
135
136wxGridCellAttr* LIB_TABLE_GRID_DATA_MODEL::GetAttr( int aRow, int aCol, wxGridCellAttr::wxAttrKind aKind )
137{
138 if( badCoords( aRow, aCol ) )
139 return enhanceAttr( nullptr, aRow, aCol, aKind );
140
141 LIBRARY_TABLE_ROW& tableRow = at( aRow );
142 bool readOnly = m_readOnly;
143
144 switch( aCol )
145 {
146 case COL_URI:
147 if( readOnly )
148 {
149 m_readOnlyAttr->IncRef();
150 return enhanceAttr( m_readOnlyAttr, aRow, aCol, aKind );
151 }
152
153 m_uriEditor->IncRef();
154 return enhanceAttr( m_uriEditor, aRow, aCol, aKind );
155
156 case COL_TYPE:
157 if( readOnly )
158 {
159 m_readOnlyAttr->IncRef();
160 return enhanceAttr( m_readOnlyAttr, aRow, aCol, aKind );
161 }
162
163 m_typesEditor->IncRef();
164 return enhanceAttr( m_typesEditor, aRow, aCol, aKind );
165
166 case COL_ENABLED:
167 case COL_VISIBLE:
168 m_boolAttr->IncRef();
169 return enhanceAttr( m_boolAttr, aRow, aCol, aKind );
170
171 case COL_STATUS:
172 if( !tableRow.IsOk() )
173 {
174 m_warningAttr->IncRef();
175 return enhanceAttr( m_warningAttr, aRow, aCol, aKind );
176 }
177
178 if( m_adapter->SupportsConfigurationDialog( tableRow.Nickname() ) )
179 {
180 m_editSettingsAttr->IncRef();
181 return enhanceAttr( m_editSettingsAttr, aRow, aCol, aKind );
182 }
183 else if( tableRow.Type() == LIBRARY_TABLE_ROW::TABLE_TYPE_NAME )
184 {
185 m_openTableAttr->IncRef();
186 return enhanceAttr( m_openTableAttr, aRow, aCol, aKind );
187 }
188
189 m_noStatusAttr->IncRef();
190 return enhanceAttr( m_noStatusAttr, aRow, aCol, aKind );
191
192 case COL_NICKNAME:
193 case COL_OPTIONS:
194 case COL_DESCR:
195 default:
196 if( readOnly )
197 {
198 m_readOnlyAttr->IncRef();
199 return enhanceAttr( m_readOnlyAttr, aRow, aCol, aKind );
200 }
201
202 return enhanceAttr( nullptr, aRow, aCol, aKind );
203 }
204}
205
206
207bool LIB_TABLE_GRID_DATA_MODEL::CanGetValueAs( int aRow, int aCol, const wxString& aTypeName )
208{
209 if( badCoords( aRow, aCol ) )
210 return false;
211
212 switch( aCol )
213 {
214 case COL_ENABLED:
215 case COL_VISIBLE:
216 return aTypeName == wxGRID_VALUE_BOOL;
217
218 default:
219 return aTypeName == wxGRID_VALUE_STRING;
220 }
221}
222
223
225{
226 if( badCoords( aRow, aCol ) )
227 return false;
228
229 if( aCol == COL_ENABLED )
230 return !at( aRow ).Disabled();
231 else if( aCol == COL_VISIBLE )
232 return !at( aRow ).Hidden();
233 else
234 return false;
235}
236
237
238void LIB_TABLE_GRID_DATA_MODEL::SetValue( int aRow, int aCol, const wxString& aValue )
239{
240 if( badCoords( aRow, aCol ) )
241 return;
242
243 // For read-only tables, only enable/visible changes are allowed
244 if( m_readOnly && aCol != COL_ENABLED && aCol != COL_VISIBLE )
245 return;
246
247 LIBRARY_TABLE_ROW& lrow = at( aRow );
248
249 switch( aCol )
250 {
251 case COL_NICKNAME: lrow.SetNickname( EscapeString( aValue, CTX_LIBID ) ); break;
252 case COL_URI: lrow.SetURI( aValue ); break;
253 case COL_TYPE: lrow.SetType( aValue ); break;
254 case COL_OPTIONS: lrow.SetOptions( aValue ); break;
255 case COL_DESCR: lrow.SetDescription( aValue ); break;
256 case COL_ENABLED: lrow.SetDisabled( aValue == wxT( "0" ) ); break;
257 case COL_VISIBLE: lrow.SetHidden( aValue == wxT( "0" ) ); break;
258 case COL_STATUS: break;
259 }
260
261 if( aCol == COL_URI || aCol == COL_TYPE || aCol == COL_OPTIONS )
262 {
263 GetView()->CallAfter(
264 [this, aRow, aCol]()
265 {
266 if( badCoords( aRow, aCol ) )
267 return;
268
269 LIBRARY_TABLE_ROW& r = at( aRow );
270
271 m_adapter->CheckTableRow( r );
272
273 GetView()->RefreshBlock( aRow, COL_STATUS, aRow, COL_STATUS );
274 } );
275 }
276
277 if( m_changeCallback )
279}
280
281
282void LIB_TABLE_GRID_DATA_MODEL::SetValueAsBool( int aRow, int aCol, bool aValue )
283{
284 if( badCoords( aRow, aCol ) )
285 return;
286
287 if( aCol == COL_ENABLED )
288 at( aRow ).SetDisabled( !aValue );
289 else if( aCol == COL_VISIBLE )
290 at( aRow ).SetHidden( !aValue );
291
292 if( m_changeCallback )
294}
295
296
297bool LIB_TABLE_GRID_DATA_MODEL::InsertRows( size_t aPos, size_t aNumRows )
298{
299 if( m_readOnly )
300 return false;
301
302 if( aPos < size() )
303 {
304 for( size_t i = 0; i < aNumRows; i++ )
305 insert( begin() + i, makeNewRow() );
306
307 // use the (wxGridStringTable) source Luke.
308 if( GetView() )
309 {
310 wxGridTableMessage msg( this, wxGRIDTABLE_NOTIFY_ROWS_INSERTED, aPos, aNumRows );
311 GetView()->ProcessTableMessage( msg );
312 }
313
314 if( m_changeCallback )
316
317 return true;
318 }
319
320 return false;
321}
322
323
325{
326 if( m_readOnly )
327 return false;
328
329 // do not modify aNumRows, original value needed for wxGridTableMessage below
330 for( int i = aNumRows; i; --i )
332
333 if( GetView() )
334 {
335 wxGridTableMessage msg( this, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, aNumRows );
336 GetView()->ProcessTableMessage( msg );
337 }
338
339 if( m_changeCallback )
341
342 return true;
343}
344
345
346bool LIB_TABLE_GRID_DATA_MODEL::DeleteRows( size_t aPos, size_t aNumRows )
347{
348 if( m_readOnly )
349 return false;
350
351 // aPos may be a large positive, e.g. size_t(-1), and the sum of
352 // aPos+aNumRows may wrap here, so both ends of the range are tested.
353 if( aPos < size() && aPos + aNumRows <= size() )
354 {
355 LIBRARY_TABLE_ROWS_ITER start = begin() + aPos;
356 erase( start, start + aNumRows );
357
358 if( GetView() )
359 {
360 wxGridTableMessage msg( this, wxGRIDTABLE_NOTIFY_ROWS_DELETED, aPos, aNumRows );
361 GetView()->ProcessTableMessage( msg );
362 }
363
364 if( m_changeCallback )
366
367 return true;
368 }
369
370 return false;
371}
372
373
375{
376 switch( aCol )
377 {
378 case COL_NICKNAME: return _( "Nickname" );
379 case COL_URI: return _( "Library Path" );
380
381 // keep this "Library Format" text fairly long so column is sized wide enough
382 case COL_TYPE: return _( "Library Format" );
383 case COL_OPTIONS: return _( "Options" );
384 case COL_DESCR: return _( "Description" );
385 case COL_ENABLED: return _( "Enable" );
386 case COL_VISIBLE: return _( "Show" );
387 case COL_STATUS: return wxS( " " );
388
389 default: return wxEmptyString;
390 }
391}
392
393
394bool LIB_TABLE_GRID_DATA_MODEL::ContainsNickname( const wxString& aNickname )
395{
396 for( size_t i = 0; i < size(); ++i )
397 {
398 LIBRARY_TABLE_ROW& row = at( i );
399
400 if( row.Nickname() == aNickname )
401 return true;
402 }
403 return false;
404}
405
406
408{
409 if( !m_adapter )
410 return;
411
412 for( size_t row = 0; row < size(); ++row )
413 m_adapter->CheckTableRow( at( row ) );
414
415 if( GetView() && GetNumberRows() > 0 )
416 GetView()->RefreshBlock( 0, COL_STATUS, GetNumberRows() - 1, COL_STATUS );
417}
418
419
421{
422 return m_table.Rows().at( aIndex );
423}
424
425
427{
428 return m_table.Rows().size();
429}
430
431
436
437
442
443
445 const LIBRARY_TABLE_ROW& aRow )
446{
447 return m_table.Rows().insert( aIterator, aRow );
448}
449
450
452{
453 m_table.Rows().push_back( aRow );
454}
455
456
459{
460 return m_table.Rows().erase( aFirst, aLast );
461}
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
Definition bitmap.cpp:110
@ small_new_window
Dialog helper object to sit in the inheritance tree between wxDialog and any class written by wxFormB...
Definition dialog_shim.h:69
Editor for wxGrid cells that adds a file/folder browser to the grid input field.
The interface used by the classes that actually can load IO plugins for the different parts of KiCad ...
void SetOptions(const wxString &aOptions)
void SetNickname(const wxString &aNickname)
void SetType(const wxString &aType)
bool Disabled() const
const wxString & ErrorDescription() const
void SetDescription(const wxString &aDescription)
const wxString & Type() const
static const wxString TABLE_TYPE_NAME
void SetURI(const wxString &aUri)
const wxString & Description() const
void SetDisabled(bool aDisabled=true)
bool Hidden() const
void SetHidden(bool aHidden=true)
bool IsOk() const
const wxString & URI() const
const wxString & Nickname() const
const wxString & Options() const
virtual LIBRARY_TABLE_ROWS_ITER begin()
bool AppendRows(size_t aNumRows=1) override
virtual LIBRARY_TABLE_ROW & at(size_t aIndex)
bool ContainsNickname(const wxString &aNickname)
virtual LIBRARY_TABLE_ROWS_ITER erase(LIBRARY_TABLE_ROWS_ITER aFirst, LIBRARY_TABLE_ROWS_ITER aLast)
void SetValueAsBool(int aRow, int aCol, bool aValue) override
virtual LIBRARY_TABLE_ROWS_ITER insert(LIBRARY_TABLE_ROWS_ITER aIterator, const LIBRARY_TABLE_ROW &aRow)
wxString GetValue(int aRow, int aCol) override
wxString GetColLabelValue(int aCol) override
wxGridCellAttr * GetAttr(int aRow, int aCol, wxGridCellAttr::wxAttrKind aKind) override
std::function< void()> m_changeCallback
bool m_readOnly
Cached read-only state of the underlying table file.
bool CanGetValueAs(int aRow, int aCol, const wxString &aTypeName) override
bool GetValueAsBool(int aRow, int aCol) override
bool DeleteRows(size_t aPos, size_t aNumRows) override
virtual void push_back(const LIBRARY_TABLE_ROW &aRow)
bool InsertRows(size_t aPos=0, size_t aNumRows=1) override
LIBRARY_MANAGER_ADAPTER * m_adapter
Handle to the adapter for the type of table this grid represents (may be null)
void SetValue(int aRow, int aCol, const wxString &aValue) override
LIBRARY_TABLE m_table
Working copy of a table.
LIB_TABLE_GRID_DATA_MODEL(DIALOG_SHIM *aParent, WX_GRID *aGrid, const LIBRARY_TABLE &aTableToEdit, LIBRARY_MANAGER_ADAPTER *aAdapter, const wxArrayString &aPluginChoices, wxString *aMRUDirectory, const wxString &aProjectPath)
virtual LIBRARY_TABLE_ROW makeNewRow()
wxGridCellAttr * enhanceAttr(wxGridCellAttr *aInputAttr, int aRow, int aCol, wxGridCellAttr::wxAttrKind aKind)
Definition wx_grid.cpp:47
#define _(s)
std::deque< LIBRARY_TABLE_ROW >::iterator LIBRARY_TABLE_ROWS_ITER
wxString UnescapeString(const wxString &aSource)
wxString EscapeString(const wxString &aSource, ESCAPE_CONTEXT aContext)
The Escape/Unescape routines use HTML-entity-reference-style encoding to handle characters which are:...
@ CTX_LIBID