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 
186 
187  if( sel.Unit == 0 )
188  sel.Unit = 1;
189 
190  sel.Fields = dlg.GetFields();
191  sel.LibId = id;
192 
193  if( sel.LibId.IsValid() )
194  {
195  aHistoryList.erase(
196  std::remove_if(
197  aHistoryList.begin(),
198  aHistoryList.end(),
199  [ &sel ]( COMPONENT_SELECTION const& i ){ return i.LibId == sel.LibId; } ),
200  aHistoryList.end() );
201 
202  aHistoryList.insert( aHistoryList.begin(), sel );
203  }
204 
205  return sel;
206 }
207 
208 
209 void SCH_EDIT_FRAME::SelectUnit( SCH_COMPONENT* aComponent, int aUnit )
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 }
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:328
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
void SetUseAllUnits(bool aUseAll)
Sets whether to utilize all units of a component when placing.
std::vector< std::pair< int, wxString > > Fields
void SelectUnit(SCH_COMPONENT *aComponent, int aUnit)
Definition: getpart.cpp:209
bool m_autoplaceFields
automatically place component fields
bool GetUseAllUnits() const
To be called after this dialog returns from ShowModal()
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:649
bool GetKeepSymbol() const
To be called after this dialog returns from ShowModal()
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:248
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.