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 <kicad_device_context.h>
35 #include <msgpanel.h>
36 #include <tool/tool_manager.h>
37 #include <tools/ee_actions.h>
38 #include <general.h>
39 #include <class_library.h>
40 #include <sch_component.h>
41 #include <lib_edit_frame.h>
42 #include <viewlib_frame.h>
43 #include <eeschema_id.h>
44 #include <symbol_lib_table.h>
45 
48 
49 
51  wxTopLevelWindow* aParent, const SCHLIB_FILTER* aFilter, const LIB_ID& aPreselectedLibId,
52  int aUnit, int aConvert )
53 {
54  // Close any open non-modal Lib browser, and open a new one, in "modal" mode:
55  LIB_VIEW_FRAME* viewlibFrame = (LIB_VIEW_FRAME*) Kiway().Player( FRAME_SCH_VIEWER, false );
56 
57  if( viewlibFrame )
58  viewlibFrame->Destroy();
59 
60  viewlibFrame = (LIB_VIEW_FRAME*) Kiway().Player( FRAME_SCH_VIEWER_MODAL, true, aParent );
61 
62  if( aFilter )
63  viewlibFrame->SetFilter( aFilter );
64 
65  if( aPreselectedLibId.IsValid() )
66  {
67  viewlibFrame->SetSelectedLibrary( aPreselectedLibId.GetLibNickname() );
68  viewlibFrame->SetSelectedComponent( aPreselectedLibId.GetLibItemName() );
69  }
70 
71  viewlibFrame->SetUnitAndConvert( aUnit, aConvert );
72 
73  viewlibFrame->Refresh();
74 
76  wxString symbol;
77 
78  if( viewlibFrame->ShowModal( &symbol, aParent ) )
79  {
80  LIB_ID id;
81 
82  if( id.Parse( symbol, LIB_ID::ID_SCH ) == -1 )
83  sel.LibId = id;
84 
85  sel.Unit = viewlibFrame->GetUnit();
86  sel.Convert = viewlibFrame->GetConvert();
87  }
88 
89  viewlibFrame->Destroy();
90 
91  return sel;
92 }
93 
94 
96  const SCHLIB_FILTER* aFilter,
97  std::vector<COMPONENT_SELECTION>& aHistoryList,
98  bool aUseLibBrowser,
99  int aUnit,
100  int aConvert,
101  bool aShowFootprints,
102  const LIB_ID* aHighlight,
103  bool aAllowFields )
104 {
105  std::unique_lock<std::mutex> dialogLock( DIALOG_CHOOSE_COMPONENT::g_Mutex, std::defer_lock );
106  wxString dialogTitle;
107  SYMBOL_LIB_TABLE* libs = Prj().SchSymbolLibTable();
108 
109  // One CHOOSE_COMPONENT dialog at a time. User probaby can't handle more anyway.
110  if( !dialogLock.try_lock() )
111  return COMPONENT_SELECTION();
112 
113  auto adapterPtr( SYMBOL_TREE_MODEL_ADAPTER::Create( libs ) );
114  auto adapter = static_cast<SYMBOL_TREE_MODEL_ADAPTER*>( adapterPtr.get() );
115  bool loaded = false;
116 
117  if( aFilter )
118  {
119  const wxArrayString& liblist = aFilter->GetAllowedLibList();
120 
121  for( unsigned ii = 0; ii < liblist.GetCount(); ii++ )
122  {
123  if( libs->HasLibrary( liblist[ii], true ) )
124  {
125  loaded = true;
126  adapter->AddLibrary( liblist[ii] );
127  }
128  }
129 
130  adapter->AssignIntrinsicRanks();
131 
132  if( aFilter->GetFilterPowerParts() )
133  adapter->SetFilter( SYMBOL_TREE_MODEL_ADAPTER::CMP_FILTER_POWER );
134  }
135 
136  std::vector< LIB_TREE_ITEM* > history_list;
137 
138  for( auto const& i : aHistoryList )
139  {
140  LIB_ALIAS* alias = GetLibAlias( i.LibId );
141 
142  // This can be null, for example when a symbol has been deleted from a library
143  if( alias )
144  history_list.push_back( alias );
145  }
146 
147  adapter->DoAddLibrary( "-- " + _( "Recently Used" ) + " --", wxEmptyString, history_list, true );
148 
149  if( !aHistoryList.empty() )
150  adapter->SetPreselectNode( aHistoryList[0].LibId, aHistoryList[0].Unit );
151 
152  const std::vector< wxString > libNicknames = libs->GetLogicalLibs();
153 
154  if( !loaded )
155  adapter->AddLibraries( libNicknames, this );
156 
157  if( aHighlight && aHighlight->IsValid() )
158  adapter->SetPreselectNode( *aHighlight, /* aUnit */ 0 );
159 
160  if( adapter->GetFilter() == SYMBOL_TREE_MODEL_ADAPTER::CMP_FILTER_POWER )
161  dialogTitle.Printf( _( "Choose Power Symbol (%d items loaded)" ), adapter->GetItemCount() );
162  else
163  dialogTitle.Printf( _( "Choose Symbol (%d items loaded)" ), adapter->GetItemCount() );
164 
165  DIALOG_CHOOSE_COMPONENT dlg( this, dialogTitle, adapterPtr, aConvert,
166  aAllowFields, aShowFootprints, aUseLibBrowser );
167 
168  if( dlg.ShowQuasiModal() == wxID_CANCEL )
169  return COMPONENT_SELECTION();
170 
172  LIB_ID id = dlg.GetSelectedLibId( &sel.Unit );
173 
174  if( dlg.IsExternalBrowserSelected() ) // User requested component browser.
175  {
176  sel = SelectComponentFromLibBrowser( this, aFilter, id, sel.Unit, sel.Convert );
177  id = sel.LibId;
178  }
179 
180  if( !id.IsValid() ) // Dialog closed by OK button,
181  // or the selection by lib browser was requested,
182  // but no symbol selected
183  return COMPONENT_SELECTION();
184 
185  if( sel.Unit == 0 )
186  sel.Unit = 1;
187 
188  sel.Fields = dlg.GetFields();
189  sel.LibId = id;
190 
191  if( sel.LibId.IsValid() )
192  {
193  aHistoryList.erase(
194  std::remove_if(
195  aHistoryList.begin(),
196  aHistoryList.end(),
197  [ &sel ]( COMPONENT_SELECTION const& i ){ return i.LibId == sel.LibId; } ),
198  aHistoryList.end() );
199 
200  aHistoryList.insert( aHistoryList.begin(), sel );
201  }
202 
203  return sel;
204 }
205 
206 
207 void SCH_EDIT_FRAME::SelectUnit( SCH_COMPONENT* aComponent, int aUnit )
208 {
210 
211  LIB_PART* part = GetLibPart( aComponent->GetLibId() );
212 
213  if( !part )
214  return;
215 
216  int unitCount = part->GetUnitCount();
217 
218  if( unitCount <= 1 || aComponent->GetUnit() == aUnit )
219  return;
220 
221  if( aUnit > unitCount )
222  aUnit = unitCount;
223 
224  STATUS_FLAGS savedFlags = aComponent->GetFlags();
225 
226  if( !aComponent->GetEditFlags() ) // No command in progress: save in undo list
227  SaveCopyInUndoList( aComponent, UR_CHANGED );
228 
229  /* Update the unit number. */
230  aComponent->SetUnitSelection( g_CurrentSheet, aUnit );
231  aComponent->SetUnit( aUnit );
232  aComponent->ClearFlags();
233  aComponent->SetFlags( savedFlags ); // Restore m_Flag modified by SetUnit()
234 
235  if( !aComponent->GetEditFlags() ) // No command in progress: update schematic
236  {
237  if( m_autoplaceFields )
238  aComponent->AutoAutoplaceFields( GetScreen() );
239 
241 
242  RefreshItem( aComponent );
243  OnModify();
244  }
245 }
246 
247 
249 {
250  if( !aComponent )
251  return;
252 
253  LIB_ID id = aComponent->GetLibId();
254  LIB_PART* part = GetLibPart( id );
255 
256  if( part )
257  {
258  wxString msg;
259 
260  if( !part->HasConversion() )
261  {
262  msg.Printf( _( "No alternate body style found for symbol \"%s\" in library \"%s\"." ),
263  id.GetLibItemName().wx_str(), id.GetLibNickname().wx_str() );
264  DisplayError( this, msg );
265  return;
266  }
267 
268  STATUS_FLAGS savedFlags = aComponent->GetFlags();
269 
270  aComponent->SetConvert( aComponent->GetConvert() + 1 );
271 
272  // ensure m_Convert = 1 or 2
273  // 1 = shape 1 = not converted
274  // 2 = shape 2 = first converted shape
275  // > 2 is not used but could be used for more shapes
276  // like multiple shapes for a programmable component
277  // When m_Convert = val max, return to the first shape
278  if( aComponent->GetConvert() > LIB_ITEM::LIB_CONVERT::DEMORGAN )
279  aComponent->SetConvert( LIB_ITEM::LIB_CONVERT::BASE );
280 
281  // The alternate symbol may cause a change in the connection status so test the
282  // connections so the connection indicators are drawn correctly.
283  aComponent->UpdatePins();
285  aComponent->ClearFlags();
286  aComponent->SetFlags( savedFlags ); // Restore m_Flags (modified by SetConvert())
287 
288  // If selected make sure all the now-included pins are selected
289  if( aComponent->IsSelected() )
290  m_toolManager->RunAction( EE_ACTIONS::addItemToSel, true, aComponent );
291 
292  RefreshItem( aComponent );
293  OnModify();
294  }
295 }
TOOL_MANAGER * m_toolManager
Definition: draw_frame.h:130
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_player.h:61
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:227
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:50
bool HasConversion() const
Test if part has more than one body conversion type (DeMorgan).
virtual void MoveCursorToCrossHair() override
Function MoveCursorToCrossHair warps the cursor to the current cross hair position.
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:125
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.
a helper to handle the real device context used in KiCad
void SetFlags(STATUS_FLAGS aMask)
Definition: base_struct.h:259
static TOOL_ACTION addItemToSel
Selects an item (specified as the event parameter).
Definition: ee_actions.h:60
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:95
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:263
int ShowQuasiModal()
PROJECT & Prj() const
Function Prj returns a reference to the PROJECT "associated with" this KIWAY.
SCH_DRAW_PANEL * GetCanvas() const override
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:150
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.
bool GetFilterPowerParts() const
std::vector< std::pair< int, wxString > > Fields
void SelectUnit(SCH_COMPONENT *aComponent, int aUnit)
Definition: getpart.cpp:207
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:260
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.
Message panel definition file.
STATUS_FLAGS GetFlags() const
Definition: base_struct.h:261
const LIB_ID & GetLibId() const
void ConvertPart(SCH_COMPONENT *aComponent)
Definition: getpart.cpp:248
void DisplayError(wxWindow *parent, const wxString &text, int displaytime)
Function DisplayError displays an error or warning message box with aMessage.
Definition: confirm.cpp:244
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.