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 <general.h>
31 #include <kiway.h>
32 #include <lib_view_frame.h>
33 #include <pgm_base.h>
34 #include <sch_component.h>
35 #include <sch_edit_frame.h>
36 #include <symbol_lib_table.h>
37 #include <tool/tool_manager.h>
38 #include <tools/ee_actions.h>
39 
42 
44  const SCHLIB_FILTER* aFilter,
45  const LIB_ID& aPreselectedLibId,
46  int aUnit, int aConvert )
47 {
48  // Close any open non-modal Lib browser, and open a new one, in "modal" mode:
49  LIB_VIEW_FRAME* viewlibFrame = (LIB_VIEW_FRAME*) Kiway().Player( FRAME_SCH_VIEWER, false );
50 
51  if( viewlibFrame )
52  viewlibFrame->Destroy();
53 
54  viewlibFrame = (LIB_VIEW_FRAME*) Kiway().Player( FRAME_SCH_VIEWER_MODAL, true, aParent );
55 
56  if( aFilter )
57  viewlibFrame->SetFilter( aFilter );
58 
59  if( aPreselectedLibId.IsValid() )
60  {
61  viewlibFrame->SetSelectedLibrary( aPreselectedLibId.GetLibNickname() );
62  viewlibFrame->SetSelectedComponent( aPreselectedLibId.GetLibItemName() );
63  }
64 
65  viewlibFrame->SetUnitAndConvert( aUnit, aConvert );
66 
67  viewlibFrame->Refresh();
68 
69  PICKED_SYMBOL sel;
70  wxString symbol;
71 
72  if( viewlibFrame->ShowModal( &symbol, aParent ) )
73  {
74  LIB_ID id;
75 
76  if( id.Parse( symbol, LIB_ID::ID_SCH ) == -1 )
77  sel.LibId = id;
78 
79  sel.Unit = viewlibFrame->GetUnit();
80  sel.Convert = viewlibFrame->GetConvert();
81  }
82 
83  viewlibFrame->Destroy();
84 
85  return sel;
86 }
87 
88 
90  std::vector<PICKED_SYMBOL>& aHistoryList,
91  bool aUseLibBrowser,
92  int aUnit, int aConvert,
93  bool aShowFootprints,
94  const LIB_ID* aHighlight,
95  bool aAllowFields )
96 {
97  std::unique_lock<std::mutex> dialogLock( DIALOG_CHOOSE_COMPONENT::g_Mutex, std::defer_lock );
98  wxString dialogTitle;
99  SYMBOL_LIB_TABLE* libs = Prj().SchSymbolLibTable();
100 
101  // One CHOOSE_COMPONENT dialog at a time. User probaby can't handle more anyway.
102  if( !dialogLock.try_lock() )
103  return PICKED_SYMBOL();
104 
105  wxObjectDataPtr<LIB_TREE_MODEL_ADAPTER> adapter = SYMBOL_TREE_MODEL_ADAPTER::Create( this, libs );
106  bool loaded = false;
107 
108  if( aFilter )
109  {
110  const wxArrayString& liblist = aFilter->GetAllowedLibList();
111 
112  for( unsigned ii = 0; ii < liblist.GetCount(); ii++ )
113  {
114  if( libs->HasLibrary( liblist[ii], true ) )
115  {
116  loaded = true;
117  static_cast<SYMBOL_TREE_MODEL_ADAPTER*>( adapter.get() )->AddLibrary( liblist[ii] );
118  }
119  }
120 
121  adapter->AssignIntrinsicRanks();
122 
123  if( aFilter->GetFilterPowerParts() )
124  adapter->SetFilter( SYMBOL_TREE_MODEL_ADAPTER::CMP_FILTER_POWER );
125  }
126 
127  std::vector< LIB_TREE_ITEM* > history_list;
128 
129  for( const PICKED_SYMBOL& i : aHistoryList )
130  {
131  LIB_PART* symbol = GetLibPart( i.LibId );
132 
133  // This can be null, for example when a symbol has been deleted from a library
134  if( symbol )
135  history_list.push_back( symbol );
136  }
137 
138  adapter->DoAddLibrary( "-- " + _( "Recently Used" ) + " --", wxEmptyString, history_list, true );
139 
140  if( !aHistoryList.empty() )
141  adapter->SetPreselectNode( aHistoryList[0].LibId, aHistoryList[0].Unit );
142 
143  const std::vector< wxString > libNicknames = libs->GetLogicalLibs();
144 
145  if( !loaded )
146  static_cast<SYMBOL_TREE_MODEL_ADAPTER*>( adapter.get() )->AddLibraries( libNicknames, this );
147 
148  if( aHighlight && aHighlight->IsValid() )
149  adapter->SetPreselectNode( *aHighlight, /* aUnit */ 0 );
150 
151  if( adapter->GetFilter() == SYMBOL_TREE_MODEL_ADAPTER::CMP_FILTER_POWER )
152  dialogTitle.Printf( _( "Choose Power Symbol (%d items loaded)" ), adapter->GetItemCount() );
153  else
154  dialogTitle.Printf( _( "Choose Symbol (%d items loaded)" ), adapter->GetItemCount() );
155 
156  DIALOG_CHOOSE_COMPONENT dlg( this, dialogTitle, adapter, aConvert, aAllowFields,
157  aShowFootprints, aUseLibBrowser );
158 
159  if( dlg.ShowModal() == wxID_CANCEL )
160  return PICKED_SYMBOL();
161 
162  PICKED_SYMBOL sel;
163  LIB_ID id = dlg.GetSelectedLibId( &sel.Unit );
164 
165  if( dlg.IsExternalBrowserSelected() ) // User requested component browser.
166  {
167  sel = PickSymbolFromLibBrowser( this, aFilter, id, sel.Unit, sel.Convert );
168  id = sel.LibId;
169  }
170 
171  if( !id.IsValid() ) // Dialog closed by OK button,
172  // or the selection by lib browser was requested,
173  // but no symbol selected
174  return PICKED_SYMBOL();
175 
176  if( sel.Unit == 0 )
177  sel.Unit = 1;
178 
179  sel.Fields = dlg.GetFields();
180  sel.LibId = id;
181 
182  if( sel.LibId.IsValid() )
183  {
184  aHistoryList.erase( std::remove_if( aHistoryList.begin(), aHistoryList.end(),
185  [ &sel ]( PICKED_SYMBOL const& i )
186  {
187  return i.LibId == sel.LibId;
188  } ),
189  aHistoryList.end() );
190 
191  aHistoryList.insert( aHistoryList.begin(), sel );
192  }
193 
194  return sel;
195 }
196 
197 
198 void SCH_EDIT_FRAME::SelectUnit( SCH_COMPONENT* aComponent, int aUnit )
199 {
200  LIB_PART* part = GetLibPart( aComponent->GetLibId() );
201 
202  if( !part )
203  return;
204 
205  int unitCount = part->GetUnitCount();
206 
207  if( unitCount <= 1 || aComponent->GetUnit() == aUnit )
208  return;
209 
210  if( aUnit > unitCount )
211  aUnit = unitCount;
212 
213  STATUS_FLAGS savedFlags = aComponent->GetFlags();
214 
215  if( !aComponent->GetEditFlags() ) // No command in progress: save in undo list
216  SaveCopyInUndoList( GetScreen(), aComponent, UNDO_REDO::CHANGED, false );
217 
218  /* Update the unit number. */
219  aComponent->SetUnitSelection( &GetCurrentSheet(), aUnit );
220  aComponent->SetUnit( aUnit );
221  aComponent->ClearFlags();
222  aComponent->SetFlags( savedFlags ); // Restore m_Flag modified by SetUnit()
223 
224  if( !aComponent->GetEditFlags() ) // No command in progress: update schematic
225  {
227  aComponent->AutoAutoplaceFields( GetScreen() );
228 
230 
231  UpdateItem( aComponent );
232  OnModify();
233  }
234 }
235 
236 
238 {
239  if( !aComponent || !aComponent->GetPartRef() )
240  return;
241 
242  wxString msg;
243 
244  if( !aComponent->GetPartRef()->HasConversion() )
245  {
246  LIB_ID id = aComponent->GetPartRef()->GetLibId();
247 
248  msg.Printf( _( "No alternate body style found for symbol \"%s\" in library \"%s\"." ),
249  id.GetLibItemName().wx_str(), id.GetLibNickname().wx_str() );
250  DisplayError( this, msg );
251  return;
252  }
253 
254  STATUS_FLAGS savedFlags = aComponent->GetFlags();
255 
256  aComponent->SetConvert( aComponent->GetConvert() + 1 );
257 
258  // ensure m_Convert = 1 or 2
259  // 1 = shape 1 = not converted
260  // 2 = shape 2 = first converted shape
261  // > 2 is not used but could be used for more shapes
262  // like multiple shapes for a programmable component
263  // When m_Convert = val max, return to the first shape
264  if( aComponent->GetConvert() > LIB_ITEM::LIB_CONVERT::DEMORGAN )
265  aComponent->SetConvert( LIB_ITEM::LIB_CONVERT::BASE );
266 
268  aComponent->ClearFlags();
269  aComponent->SetFlags( savedFlags ); // Restore m_flags (modified by SetConvert())
270 
271  // If selected make sure all the now-included pins are selected
272  if( aComponent->IsSelected() )
273  m_toolManager->RunAction( EE_ACTIONS::addItemToSel, true, aComponent );
274 
275  UpdateItem( aComponent );
276  OnModify();
277 }
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:240
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
void UpdateItem(EDA_ITEM *aItem, bool isAddOrDelete=false)
Mark an item for refresh.
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: eda_item.h:191
This file is part of the common library.
void AutoAutoplaceFields(SCH_SCREEN *aScreen)
Autoplace fields only if correct to do so automatically.
Definition: sch_item.h:467
int GetUnit() const
static wxObjectDataPtr< LIB_TREE_MODEL_ADAPTER > Create(EDA_BASE_FRAME *aParent, LIB_TABLE *aLibs)
Factory function: create a model adapter in a reference-counting container.
bool RunAction(const std::string &aActionName, bool aNow=false, T aParam=NULL)
Function RunAction() Runs the specified action.
Definition: tool_manager.h:141
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.
int GetConvert() const
void SetConvert(int aConvert)
EESCHEMA_SETTINGS * eeconfig() const
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.
AUTOPLACE_FIELDS m_AutoplaceFields
void SetFlags(STATUS_FLAGS aMask)
Definition: eda_item.h:220
static TOOL_ACTION addItemToSel
Selects an item (specified as the event parameter).
Definition: ee_actions.h:59
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:345
std::vector< std::pair< int, wxString > > GetFields() const
Get a list of fields edited by the user.
STATUS_FLAGS GetEditFlags() const
Definition: eda_item.h:225
PICKED_SYMBOL PickSymbolFromLibTree(const SCHLIB_FILTER *aFilter, std::vector< PICKED_SYMBOL > &aHistoryList, bool aUseLibBrowser, int aUnit, int aConvert, bool aShowFootprints, const LIB_ID *aHighlight=nullptr, bool aAllowFields=true)
Function PickSymbolFromLibTree Calls the library viewer to select component to import into schematic.
Definition: getpart.cpp:89
PROJECT & Prj() const
Function Prj returns a reference to the PROJECT "associated with" this KIWAY.
Define a library symbol object.
void SaveCopyInUndoList(SCH_SCREEN *aScreen, SCH_ITEM *aItemToCopy, UNDO_REDO aTypeCommand, bool aAppend, const wxPoint &aTransformPoint=wxPoint(0, 0))
Create a copy of the current schematic item, and put it in the undo list.
unsigned STATUS_FLAGS
Definition: eda_item.h:142
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.
std::unique_ptr< LIB_PART > & GetPartRef()
bool GetFilterPowerParts() const
void SelectUnit(SCH_COMPONENT *aComponent, int aUnit)
Definition: getpart.cpp:198
PICKED_SYMBOL PickSymbolFromLibBrowser(wxTopLevelWindow *aParent, const SCHLIB_FILTER *aFilter, const LIB_ID &aPreselectedLibId, int aUnit, int aConvert)
Function PickSymbolFromLibBrowser Calls the library viewer to select component to import into schemat...
Definition: getpart.cpp:43
void SetUnitSelection(const SCH_SHEET_PATH *aSheet, int aUnitSelection)
TOOL_MANAGER * m_toolManager
Definition: tools_holder.h:48
see class PGM_BASE
#define _(s)
Definition: 3d_actions.cpp:33
Schematic symbol object.
Definition: sch_component.h:79
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: eda_item.h:221
SCH_SHEET_PATH & GetCurrentSheet() const
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...
Definition for part library class.
LIB_ID LibId
Definition: sch_screen.h:82
STATUS_FLAGS GetFlags() const
Definition: eda_item.h:222
const LIB_ID & GetLibId() const
void ConvertPart(SCH_COMPONENT *aComponent)
Definition: getpart.cpp:237
std::vector< std::pair< int, wxString > > Fields
Definition: sch_screen.h:86
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.