KiCad PCB EDA Suite
getpart.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 Jean-Pierre Charras, jp.charras at wanadoo.fr
5  * Copyright (C) 2008 Wayne Stambaugh <stambaughw@gmail.com>
6  * Copyright (C) 2004-2019 KiCad Developers, see AUTHORS.txt for contributors.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, you may find one here:
20  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21  * or you may search the http://www.gnu.org website for the version 2 license,
22  * or you may write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24  */
25 
26 #include <algorithm>
27 #include <class_library.h>
28 #include <confirm.h>
29 #include <eeschema_id.h>
30 #include <fctsys.h>
31 #include <general.h>
32 #include <gr_basic.h>
33 #include <kiway.h>
34 #include <lib_edit_frame.h>
35 #include <lib_view_frame.h>
36 #include <msgpanel.h>
37 #include <pgm_base.h>
38 #include <project.h>
39 #include <sch_component.h>
40 #include <sch_draw_panel.h>
41 #include <sch_edit_frame.h>
42 #include <symbol_lib_table.h>
43 #include <tool/tool_manager.h>
44 #include <tools/ee_actions.h>
45 
48 
49 
51  const SCHLIB_FILTER* aFilter, const LIB_ID& aPreselectedLibId, int aUnit, int aConvert )
52 {
53  // Close any open non-modal Lib browser, and open a new one, in "modal" mode:
54  LIB_VIEW_FRAME* viewlibFrame = (LIB_VIEW_FRAME*) Kiway().Player( FRAME_SCH_VIEWER, false );
55 
56  if( viewlibFrame )
57  viewlibFrame->Destroy();
58 
59  viewlibFrame = (LIB_VIEW_FRAME*) Kiway().Player( FRAME_SCH_VIEWER_MODAL, true, aParent );
60 
61  if( aFilter )
62  viewlibFrame->SetFilter( aFilter );
63 
64  if( aPreselectedLibId.IsValid() )
65  {
66  viewlibFrame->SetSelectedLibrary( aPreselectedLibId.GetLibNickname() );
67  viewlibFrame->SetSelectedComponent( aPreselectedLibId.GetLibItemName() );
68  }
69 
70  viewlibFrame->SetUnitAndConvert( aUnit, aConvert );
71 
72  viewlibFrame->Refresh();
73 
75  wxString symbol;
76 
77  if( viewlibFrame->ShowModal( &symbol, aParent ) )
78  {
79  LIB_ID id;
80 
81  if( id.Parse( symbol, LIB_ID::ID_SCH ) == -1 )
82  sel.LibId = id;
83 
84  sel.Unit = viewlibFrame->GetUnit();
85  sel.Convert = viewlibFrame->GetConvert();
86  }
87 
88  viewlibFrame->Destroy();
89 
90  return sel;
91 }
92 
93 
95  std::vector<COMPONENT_SELECTION>& aHistoryList, bool aUseLibBrowser, int aUnit,
96  int aConvert, bool aShowFootprints, const LIB_ID* aHighlight, bool aAllowFields )
97 {
98  std::unique_lock<std::mutex> dialogLock( DIALOG_CHOOSE_COMPONENT::g_Mutex, std::defer_lock );
99  wxString dialogTitle;
100  SYMBOL_LIB_TABLE* libs = Prj().SchSymbolLibTable();
101 
102  // One CHOOSE_COMPONENT dialog at a time. User probaby can't handle more anyway.
103  if( !dialogLock.try_lock() )
104  return COMPONENT_SELECTION();
105 
106  auto adapterPtr( SYMBOL_TREE_MODEL_ADAPTER::Create( this, libs ) );
107  auto adapter = static_cast<SYMBOL_TREE_MODEL_ADAPTER*>( adapterPtr.get() );
108  bool loaded = false;
109 
110  if( aFilter )
111  {
112  const wxArrayString& liblist = aFilter->GetAllowedLibList();
113 
114  for( unsigned ii = 0; ii < liblist.GetCount(); ii++ )
115  {
116  if( libs->HasLibrary( liblist[ii], true ) )
117  {
118  loaded = true;
119  adapter->AddLibrary( liblist[ii] );
120  }
121  }
122 
123  adapter->AssignIntrinsicRanks();
124 
125  if( aFilter->GetFilterPowerParts() )
126  adapter->SetFilter( SYMBOL_TREE_MODEL_ADAPTER::CMP_FILTER_POWER );
127  }
128 
129  std::vector< LIB_TREE_ITEM* > history_list;
130 
131  for( auto const& i : aHistoryList )
132  {
133  LIB_PART* symbol = GetLibPart( i.LibId );
134 
135  // This can be null, for example when a symbol has been deleted from a library
136  if( symbol )
137  history_list.push_back( symbol );
138  }
139 
140  adapter->DoAddLibrary( "-- " + _( "Recently Used" ) + " --", wxEmptyString, history_list,
141  true );
142 
143  if( !aHistoryList.empty() )
144  adapter->SetPreselectNode( aHistoryList[0].LibId, aHistoryList[0].Unit );
145 
146  const std::vector< wxString > libNicknames = libs->GetLogicalLibs();
147 
148  if( !loaded )
149  adapter->AddLibraries( libNicknames, this );
150 
151  if( aHighlight && aHighlight->IsValid() )
152  adapter->SetPreselectNode( *aHighlight, /* aUnit */ 0 );
153 
154  if( adapter->GetFilter() == SYMBOL_TREE_MODEL_ADAPTER::CMP_FILTER_POWER )
155  dialogTitle.Printf( _( "Choose Power Symbol (%d items loaded)" ), adapter->GetItemCount() );
156  else
157  dialogTitle.Printf( _( "Choose Symbol (%d items loaded)" ), adapter->GetItemCount() );
158 
159  DIALOG_CHOOSE_COMPONENT dlg( this, dialogTitle, adapterPtr, aConvert,
160  aAllowFields, aShowFootprints, aUseLibBrowser );
161 
162  if( dlg.ShowQuasiModal() == wxID_CANCEL )
163  return COMPONENT_SELECTION();
164 
166  LIB_ID id = dlg.GetSelectedLibId( &sel.Unit );
167 
168  if( dlg.IsExternalBrowserSelected() ) // User requested component browser.
169  {
170  sel = SelectComponentFromLibBrowser( this, aFilter, id, sel.Unit, sel.Convert );
171  id = sel.LibId;
172  }
173 
174  if( !id.IsValid() ) // Dialog closed by OK button,
175  // or the selection by lib browser was requested,
176  // but no symbol selected
177  return COMPONENT_SELECTION();
178 
181 
182  if( sel.Unit == 0 )
183  sel.Unit = 1;
184 
185  sel.Fields = dlg.GetFields();
186  sel.LibId = id;
187 
188  if( sel.LibId.IsValid() )
189  {
190  aHistoryList.erase(
191  std::remove_if(
192  aHistoryList.begin(),
193  aHistoryList.end(),
194  [ &sel ]( COMPONENT_SELECTION const& i ){ return i.LibId == sel.LibId; } ),
195  aHistoryList.end() );
196 
197  aHistoryList.insert( aHistoryList.begin(), sel );
198  }
199 
200  return sel;
201 }
202 
203 
204 void SCH_EDIT_FRAME::SelectUnit( SCH_COMPONENT* aComponent, int aUnit )
205 {
206  LIB_PART* part = GetLibPart( aComponent->GetLibId() );
207 
208  if( !part )
209  return;
210 
211  int unitCount = part->GetUnitCount();
212 
213  if( unitCount <= 1 || aComponent->GetUnit() == aUnit )
214  return;
215 
216  if( aUnit > unitCount )
217  aUnit = unitCount;
218 
219  STATUS_FLAGS savedFlags = aComponent->GetFlags();
220 
221  if( !aComponent->GetEditFlags() ) // No command in progress: save in undo list
222  SaveCopyInUndoList( aComponent, UR_CHANGED );
223 
224  /* Update the unit number. */
225  aComponent->SetUnitSelection( g_CurrentSheet, aUnit );
226  aComponent->SetUnit( aUnit );
227  aComponent->ClearFlags();
228  aComponent->SetFlags( savedFlags ); // Restore m_Flag modified by SetUnit()
229 
230  if( !aComponent->GetEditFlags() ) // No command in progress: update schematic
231  {
232  if( m_autoplaceFields )
233  aComponent->AutoAutoplaceFields( GetScreen() );
234 
236 
237  RefreshItem( aComponent );
238  OnModify();
239  }
240 }
241 
242 
244 {
245  if( !aComponent )
246  return;
247 
248  LIB_ID id = aComponent->GetLibId();
249  LIB_PART* part = GetLibPart( id );
250 
251  if( part )
252  {
253  wxString msg;
254 
255  if( !part->HasConversion() )
256  {
257  msg.Printf( _( "No alternate body style found for symbol \"%s\" in library \"%s\"." ),
258  id.GetLibItemName().wx_str(), id.GetLibNickname().wx_str() );
259  DisplayError( this, msg );
260  return;
261  }
262 
263  STATUS_FLAGS savedFlags = aComponent->GetFlags();
264 
265  aComponent->SetConvert( aComponent->GetConvert() + 1 );
266 
267  // ensure m_Convert = 1 or 2
268  // 1 = shape 1 = not converted
269  // 2 = shape 2 = first converted shape
270  // > 2 is not used but could be used for more shapes
271  // like multiple shapes for a programmable component
272  // When m_Convert = val max, return to the first shape
273  if( aComponent->GetConvert() > LIB_ITEM::LIB_CONVERT::DEMORGAN )
274  aComponent->SetConvert( LIB_ITEM::LIB_CONVERT::BASE );
275 
276  // The alternate symbol may cause a change in the connection status so test the
277  // connections so the connection indicators are drawn correctly.
278  aComponent->UpdatePins();
280  aComponent->ClearFlags();
281  aComponent->SetFlags( savedFlags ); // Restore m_Flags (modified by SetConvert())
282 
283  // If selected make sure all the now-included pins are selected
284  if( aComponent->IsSelected() )
285  m_toolManager->RunAction( EE_ACTIONS::addItemToSel, true, aComponent );
286 
287  RefreshItem( aComponent );
288  OnModify();
289  }
290 }
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:239
void SetFilter(const SCHLIB_FILTER *aFilter)
Set a filter to display only libraries and/or components which match the filter.
const UTF8 & GetLibItemName() const
Definition: lib_id.h:114
KIWAY & Kiway() const
Function Kiway returns a reference to the KIWAY that this object has an opportunity to participate in...
Definition: kiway_holder.h:56
bool HasLibrary(const wxString &aNickname, bool aCheckEnabled=false) const
Test for the existence of aNickname in the library table.
void SetUnitAndConvert(int aUnit, int aConvert)
Set unit and convert, and set flag preventing them from automatically resetting to 1.
bool ShowModal(wxString *aSymbol, wxWindow *aParent) override
Function ShowModal.
bool IsSelected() const
Definition: base_struct.h:225
This file is part of the common library.
void Parse(void *yyp, int yymajor, ParseTOKENTYPE yyminor ParseARG_PDECL)
bool HasConversion() const
Test if part has more than one body conversion type (DeMorgan).
void AutoAutoplaceFields(SCH_SCREEN *aScreen)
Autoplace fields only if correct to do so automatically.
Definition: sch_item.h:419
int GetUnit() const
bool RunAction(const std::string &aActionName, bool aNow=false, T aParam=NULL)
Function RunAction() Runs the specified action.
Definition: tool_manager.h:139
LIB_PART * GetLibPart(const LIB_ID &aLibId, bool aUseCacheLib=false, bool aShowErrorMsg=false)
Load symbol from symbol library table.
bool TestDanglingEnds()
Test all of the connectable objects in the schematic for unused connection points.
A logical library item identifier and consists of various portions much like a URI.
Definition: lib_id.h:51
bool IsValid() const
Definition: lib_id.h:171
void SetSelectedComponent(const wxString &aComponentName)
Set the selected component.
Symbol library viewer main window.
static PTR Create(EDA_BASE_FRAME *aParent, LIB_TABLE *aLibs)
Factory function: create a model adapter in a reference-counting container.
int GetConvert() const
void SetConvert(int aConvert)
SCH_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
Dialog class to select a component from the libraries.
bool IsExternalBrowserSelected() const
Function IsExternalBrowserSelected.
void SetFlags(STATUS_FLAGS aMask)
Definition: base_struct.h:257
static TOOL_ACTION addItemToSel
Selects an item (specified as the event parameter).
Definition: ee_actions.h:61
SCH_SHEET_PATH * g_CurrentSheet
With the new connectivity algorithm, many more places than before want to know what the current sheet...
int GetUnitCount() const override
For items with units, return the number of units.
VTBL_ENTRY KIWAY_PLAYER * Player(FRAME_T aFrameType, bool doCreate=true, wxTopLevelWindow *aParent=NULL)
Function Player returns the KIWAY_PLAYER* given a FRAME_T.
Definition: kiway.cpp:341
std::vector< std::pair< int, wxString > > GetFields() const
Get a list of fields edited by the user.
STATUS_FLAGS GetEditFlags() const
Definition: base_struct.h:262
int ShowQuasiModal()
PROJECT & Prj() const
Function Prj returns a reference to the PROJECT "associated with" this KIWAY.
void SaveCopyInUndoList(SCH_ITEM *aItemToCopy, UNDO_REDO_T aTypeCommand, bool aAppend=false, const wxPoint &aTransformPoint=wxPoint(0, 0))
Create a copy of the current schematic item, and put it in the undo list.
Define a library symbol object.
unsigned STATUS_FLAGS
Definition: base_struct.h:159
const UTF8 & GetLibNickname() const
Return the logical library name portion of a LIB_ID.
Definition: lib_id.h:97
void SetUnit(int aUnit)
Change the unit number to aUnit.
COMPONENT_SELECTION SelectCompFromLibTree(const SCHLIB_FILTER *aFilter, std::vector< COMPONENT_SELECTION > &aHistoryList, bool aUseLibBrowser, int aUnit, int aConvert, bool aShowFootprints, const LIB_ID *aHighlight=nullptr, bool aAllowFields=true)
Function SelectComponentFromLib Calls the library viewer to select component to import into schematic...
Definition: getpart.cpp:94
bool GetFilterPowerParts() const
void SetUseAllUnits(bool aUseAll)
Sets whether to utilize all units of a component when placing.
COMPONENT_SELECTION SelectComponentFromLibBrowser(wxTopLevelWindow *aParent, const SCHLIB_FILTER *aFilter, const LIB_ID &aPreselectedLibid, int aUnit, int aConvert)
Function SelectComponentFromLibBrowser Calls the library viewer to select component to import into sc...
Definition: getpart.cpp:50
void SelectUnit(SCH_COMPONENT *aComponent, int aUnit)
Definition: getpart.cpp:204
bool m_autoplaceFields
automatically place component fields
bool GetUseAllUnits() const
To be called after this dialog returns from ShowModal()
void SetUnitSelection(const SCH_SHEET_PATH *aSheet, int aUnitSelection)
see class PGM_BASE
void RefreshItem(EDA_ITEM *aItem, bool isAddOrDelete=false)
Mark an item for refresh.
#define _(s)
Definition: 3d_actions.cpp:33
bool GetKeepSymbol() const
To be called after this dialog returns from ShowModal()
SCH_COMPONENT describes a real schematic component.
Definition: sch_component.h:99
const wxArrayString & GetAllowedLibList() const
bool Destroy() override
Our version of Destroy() which is virtual from wxWidgets.
void ClearFlags(STATUS_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition: base_struct.h:258
std::vector< std::pair< int, wxString > > Fields
Definition: sch_screen.h:78
int GetConvert() const
void OnModify() override
Must be called after a schematic change in order to set the "modify" flag of the current screen and u...
TOOL_MANAGER * m_toolManager
Definition for part library class.
void UpdatePins()
Updates the cache of SCH_PIN objects for each pin.
Message panel definition file.
STATUS_FLAGS GetFlags() const
Definition: base_struct.h:259
const LIB_ID & GetLibId() const
void ConvertPart(SCH_COMPONENT *aComponent)
Definition: getpart.cpp:243
void SetRepeatComponent(bool aRepeat)
If true, keep placing new copies of the same symbol on each click.
LIB_ID GetSelectedLibId(int *aUnit=nullptr) const
To be called after this dialog returns from ShowModal().
std::vector< wxString > GetLogicalLibs()
Return the logical library names, all of them that are pertinent to a look up done on this LIB_TABLE.
void SetSelectedLibrary(const wxString &aLibName)
Set the selected library in the library window.