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 <fctsys.h>
28 #include <pgm_base.h>
29 #include <kiway.h>
30 #include <gr_basic.h>
31 #include <sch_draw_panel.h>
32 #include <confirm.h>
33 #include <sch_edit_frame.h>
34 #include <msgpanel.h>
35 #include <tool/tool_manager.h>
36 #include <tools/ee_actions.h>
37 #include <general.h>
38 #include <class_library.h>
39 #include <sch_component.h>
40 #include <lib_edit_frame.h>
41 #include <viewlib_frame.h>
42 #include <eeschema_id.h>
43 #include <symbol_lib_table.h>
44 
47 
48 
50  wxTopLevelWindow* aParent, const SCHLIB_FILTER* aFilter, const LIB_ID& aPreselectedLibId,
51  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  const SCHLIB_FILTER* aFilter,
96  std::vector<COMPONENT_SELECTION>& aHistoryList,
97  bool aUseLibBrowser,
98  int aUnit,
99  int aConvert,
100  bool aShowFootprints,
101  const LIB_ID* aHighlight,
102  bool aAllowFields )
103 {
104  std::unique_lock<std::mutex> dialogLock( DIALOG_CHOOSE_COMPONENT::g_Mutex, std::defer_lock );
105  wxString dialogTitle;
106  SYMBOL_LIB_TABLE* libs = Prj().SchSymbolLibTable();
107 
108  // One CHOOSE_COMPONENT dialog at a time. User probaby can't handle more anyway.
109  if( !dialogLock.try_lock() )
110  return COMPONENT_SELECTION();
111 
112  auto adapterPtr( SYMBOL_TREE_MODEL_ADAPTER::Create( libs ) );
113  auto adapter = static_cast<SYMBOL_TREE_MODEL_ADAPTER*>( adapterPtr.get() );
114  bool loaded = false;
115 
116  if( aFilter )
117  {
118  const wxArrayString& liblist = aFilter->GetAllowedLibList();
119 
120  for( unsigned ii = 0; ii < liblist.GetCount(); ii++ )
121  {
122  if( libs->HasLibrary( liblist[ii], true ) )
123  {
124  loaded = true;
125  adapter->AddLibrary( liblist[ii] );
126  }
127  }
128 
129  adapter->AssignIntrinsicRanks();
130 
131  if( aFilter->GetFilterPowerParts() )
132  adapter->SetFilter( SYMBOL_TREE_MODEL_ADAPTER::CMP_FILTER_POWER );
133  }
134 
135  std::vector< LIB_TREE_ITEM* > history_list;
136 
137  for( auto const& i : aHistoryList )
138  {
139  LIB_ALIAS* alias = GetLibAlias( i.LibId );
140 
141  // This can be null, for example when a symbol has been deleted from a library
142  if( alias )
143  history_list.push_back( alias );
144  }
145 
146  adapter->DoAddLibrary( "-- " + _( "Recently Used" ) + " --", wxEmptyString, history_list, true );
147 
148  if( !aHistoryList.empty() )
149  adapter->SetPreselectNode( aHistoryList[0].LibId, aHistoryList[0].Unit );
150 
151  const std::vector< wxString > libNicknames = libs->GetLogicalLibs();
152 
153  if( !loaded )
154  adapter->AddLibraries( libNicknames, this );
155 
156  if( aHighlight && aHighlight->IsValid() )
157  adapter->SetPreselectNode( *aHighlight, /* aUnit */ 0 );
158 
159  if( adapter->GetFilter() == SYMBOL_TREE_MODEL_ADAPTER::CMP_FILTER_POWER )
160  dialogTitle.Printf( _( "Choose Power Symbol (%d items loaded)" ), adapter->GetItemCount() );
161  else
162  dialogTitle.Printf( _( "Choose Symbol (%d items loaded)" ), adapter->GetItemCount() );
163 
164  DIALOG_CHOOSE_COMPONENT dlg( this, dialogTitle, adapterPtr, aConvert,
165  aAllowFields, aShowFootprints, aUseLibBrowser );
166 
167  if( dlg.ShowQuasiModal() == wxID_CANCEL )
168  return COMPONENT_SELECTION();
169 
171  LIB_ID id = dlg.GetSelectedLibId( &sel.Unit );
172 
173  if( dlg.IsExternalBrowserSelected() ) // User requested component browser.
174  {
175  sel = SelectComponentFromLibBrowser( this, aFilter, id, sel.Unit, sel.Convert );
176  id = sel.LibId;
177  }
178 
179  if( !id.IsValid() ) // Dialog closed by OK button,
180  // or the selection by lib browser was requested,
181  // but no symbol selected
182  return COMPONENT_SELECTION();
183 
184  if( sel.Unit == 0 )
185  sel.Unit = 1;
186 
187  sel.Fields = dlg.GetFields();
188  sel.LibId = id;
189 
190  if( sel.LibId.IsValid() )
191  {
192  aHistoryList.erase(
193  std::remove_if(
194  aHistoryList.begin(),
195  aHistoryList.end(),
196  [ &sel ]( COMPONENT_SELECTION const& i ){ return i.LibId == sel.LibId; } ),
197  aHistoryList.end() );
198 
199  aHistoryList.insert( aHistoryList.begin(), sel );
200  }
201 
202  return sel;
203 }
204 
205 
206 void SCH_EDIT_FRAME::SelectUnit( SCH_COMPONENT* aComponent, int aUnit )
207 {
208  LIB_PART* part = GetLibPart( aComponent->GetLibId() );
209 
210  if( !part )
211  return;
212 
213  int unitCount = part->GetUnitCount();
214 
215  if( unitCount <= 1 || aComponent->GetUnit() == aUnit )
216  return;
217 
218  if( aUnit > unitCount )
219  aUnit = unitCount;
220 
221  STATUS_FLAGS savedFlags = aComponent->GetFlags();
222 
223  if( !aComponent->GetEditFlags() ) // No command in progress: save in undo list
224  SaveCopyInUndoList( aComponent, UR_CHANGED );
225 
226  /* Update the unit number. */
227  aComponent->SetUnitSelection( g_CurrentSheet, aUnit );
228  aComponent->SetUnit( aUnit );
229  aComponent->ClearFlags();
230  aComponent->SetFlags( savedFlags ); // Restore m_Flag modified by SetUnit()
231 
232  if( !aComponent->GetEditFlags() ) // No command in progress: update schematic
233  {
234  if( m_autoplaceFields )
235  aComponent->AutoAutoplaceFields( GetScreen() );
236 
238 
239  RefreshItem( aComponent );
240  OnModify();
241  }
242 }
243 
244 
246 {
247  if( !aComponent )
248  return;
249 
250  LIB_ID id = aComponent->GetLibId();
251  LIB_PART* part = GetLibPart( id );
252 
253  if( part )
254  {
255  wxString msg;
256 
257  if( !part->HasConversion() )
258  {
259  msg.Printf( _( "No alternate body style found for symbol \"%s\" in library \"%s\"." ),
260  id.GetLibItemName().wx_str(), id.GetLibNickname().wx_str() );
261  DisplayError( this, msg );
262  return;
263  }
264 
265  STATUS_FLAGS savedFlags = aComponent->GetFlags();
266 
267  aComponent->SetConvert( aComponent->GetConvert() + 1 );
268 
269  // ensure m_Convert = 1 or 2
270  // 1 = shape 1 = not converted
271  // 2 = shape 2 = first converted shape
272  // > 2 is not used but could be used for more shapes
273  // like multiple shapes for a programmable component
274  // When m_Convert = val max, return to the first shape
275  if( aComponent->GetConvert() > LIB_ITEM::LIB_CONVERT::DEMORGAN )
276  aComponent->SetConvert( LIB_ITEM::LIB_CONVERT::BASE );
277 
278  // The alternate symbol may cause a change in the connection status so test the
279  // connections so the connection indicators are drawn correctly.
280  aComponent->UpdatePins();
282  aComponent->ClearFlags();
283  aComponent->SetFlags( savedFlags ); // Restore m_Flags (modified by SetConvert())
284 
285  // If selected make sure all the now-included pins are selected
286  if( aComponent->IsSelected() )
287  m_toolManager->RunAction( EE_ACTIONS::addItemToSel, true, aComponent );
288 
289  RefreshItem( aComponent );
290  OnModify();
291  }
292 }
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:236
static void UpdatePins(const EE_COLLECTOR &aComponents)
Update the pin cache for all components in aComponents.
int GetUnitCount() const
void SetFilter(const SCHLIB_FILTER *aFilter)
Set a filter to display only libraries and/or components which match the filter.
void AutoAutoplaceFields(SCH_SCREEN *aScreen)
Autoplace fields only if correct to do so automatically.
Part library alias object definition.
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:233
This file is part of the common library.
void Parse(void *yyp, int yymajor, ParseTOKENTYPE yyminor ParseARG_PDECL)
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:49
bool HasConversion() const
Test if part has more than one body conversion type (DeMorgan).
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:109
LIB_PART * GetLibPart(const LIB_ID &aLibId, bool aUseCacheLib=false, bool aShowErrorMsg=false)
bool TestDanglingEnds()
Test all of the connectable objects in the schematic for unused connection points.
void SetUnitSelection(SCH_SHEET_PATH *aSheet, int aUnitSelection)
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.
Definition: viewlib_frame.h:43
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:265
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...
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:321
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
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:270
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:156
const UTF8 & GetLibNickname() const
Return the logical library name portion of a LIB_ID.
Definition: lib_id.h:97
LIB_ALIAS * GetLibAlias(const LIB_ID &aLibId, bool aUseCacheLib=false, bool aShowError=false)
Load symbol from symbol library table.
void SetUnit(int aUnit)
Change the unit number to aUnit.
#define _(s)
bool GetFilterPowerParts() const
std::vector< std::pair< int, wxString > > Fields
void SelectUnit(SCH_COMPONENT *aComponent, int aUnit)
Definition: getpart.cpp:206
bool m_autoplaceFields
automatically place component fields
static PTR Create(LIB_TABLE *aLibs)
Factory function: create a model adapter in a reference-counting container.
see class PGM_BASE
void RefreshItem(EDA_ITEM *aItem, bool isAddOrDelete=false)
Mark an item for refresh.
size_t i
Definition: json11.cpp:597
Class SCH_COMPONENT describes a real schematic component.
Definition: sch_component.h:73
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:266
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.
Message panel definition file.
STATUS_FLAGS GetFlags() const
Definition: base_struct.h:267
const LIB_ID & GetLibId() const
void ConvertPart(SCH_COMPONENT *aComponent)
Definition: getpart.cpp:245
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.