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_PART* symbol = GetLibPart( i.LibId );
140 
141  // This can be null, for example when a symbol has been deleted from a library
142  if( symbol )
143  history_list.push_back( symbol );
144  }
145 
146  adapter->DoAddLibrary( "-- " + _( "Recently Used" ) + " --", wxEmptyString, history_list,
147  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 
187 
188  if( sel.Unit == 0 )
189  sel.Unit = 1;
190 
191  sel.Fields = dlg.GetFields();
192  sel.LibId = id;
193 
194  if( sel.LibId.IsValid() )
195  {
196  aHistoryList.erase(
197  std::remove_if(
198  aHistoryList.begin(),
199  aHistoryList.end(),
200  [ &sel ]( COMPONENT_SELECTION const& i ){ return i.LibId == sel.LibId; } ),
201  aHistoryList.end() );
202 
203  aHistoryList.insert( aHistoryList.begin(), sel );
204  }
205 
206  return sel;
207 }
208 
209 
210 void SCH_EDIT_FRAME::SelectUnit( SCH_COMPONENT* aComponent, int aUnit )
211 {
212  LIB_PART* part = GetLibPart( aComponent->GetLibId() );
213 
214  if( !part )
215  return;
216 
217  int unitCount = part->GetUnitCount();
218 
219  if( unitCount <= 1 || aComponent->GetUnit() == aUnit )
220  return;
221 
222  if( aUnit > unitCount )
223  aUnit = unitCount;
224 
225  STATUS_FLAGS savedFlags = aComponent->GetFlags();
226 
227  if( !aComponent->GetEditFlags() ) // No command in progress: save in undo list
228  SaveCopyInUndoList( aComponent, UR_CHANGED );
229 
230  /* Update the unit number. */
231  aComponent->SetUnitSelection( g_CurrentSheet, aUnit );
232  aComponent->SetUnit( aUnit );
233  aComponent->ClearFlags();
234  aComponent->SetFlags( savedFlags ); // Restore m_Flag modified by SetUnit()
235 
236  if( !aComponent->GetEditFlags() ) // No command in progress: update schematic
237  {
238  if( m_autoplaceFields )
239  aComponent->AutoAutoplaceFields( GetScreen() );
240 
242 
243  RefreshItem( aComponent );
244  OnModify();
245  }
246 }
247 
248 
250 {
251  if( !aComponent )
252  return;
253 
254  LIB_ID id = aComponent->GetLibId();
255  LIB_PART* part = GetLibPart( id );
256 
257  if( part )
258  {
259  wxString msg;
260 
261  if( !part->HasConversion() )
262  {
263  msg.Printf( _( "No alternate body style found for symbol \"%s\" in library \"%s\"." ),
264  id.GetLibItemName().wx_str(), id.GetLibNickname().wx_str() );
265  DisplayError( this, msg );
266  return;
267  }
268 
269  STATUS_FLAGS savedFlags = aComponent->GetFlags();
270 
271  aComponent->SetConvert( aComponent->GetConvert() + 1 );
272 
273  // ensure m_Convert = 1 or 2
274  // 1 = shape 1 = not converted
275  // 2 = shape 2 = first converted shape
276  // > 2 is not used but could be used for more shapes
277  // like multiple shapes for a programmable component
278  // When m_Convert = val max, return to the first shape
279  if( aComponent->GetConvert() > LIB_ITEM::LIB_CONVERT::DEMORGAN )
280  aComponent->SetConvert( LIB_ITEM::LIB_CONVERT::BASE );
281 
282  // The alternate symbol may cause a change in the connection status so test the
283  // connections so the connection indicators are drawn correctly.
284  aComponent->UpdatePins();
286  aComponent->ClearFlags();
287  aComponent->SetFlags( savedFlags ); // Restore m_Flags (modified by SetConvert())
288 
289  // If selected make sure all the now-included pins are selected
290  if( aComponent->IsSelected() )
291  m_toolManager->RunAction( EE_ACTIONS::addItemToSel, true, aComponent );
292 
293  RefreshItem( aComponent );
294  OnModify();
295  }
296 }
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.
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.
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)
Load symbol from symbol library table.
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:42
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...
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
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
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:210
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:249
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.