KiCad PCB EDA Suite
Loading...
Searching...
No Matches
design_block_tree_model_adapter.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 The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or (at your
9 * option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
20#include <pgm_base.h>
21#include <kiface_base.h>
22#include <eda_base_frame.h>
23#include <core/kicad_algo.h>
26#include <wx/log.h>
27#include <wx/tokenzr.h>
29#include <string_utils.h>
30#include <eda_pattern_match.h>
31#include <design_block.h>
34#include <kiplatform/ui.h>
35
36wxObjectDataPtr<LIB_TREE_MODEL_ADAPTER>
38 APP_SETTINGS_BASE::LIB_TREE& aSettings, TOOL_INTERACTIVE* aContextMenuTool )
39{
40 auto* adapter = new DESIGN_BLOCK_TREE_MODEL_ADAPTER( aParent, aLibs, aSettings, aContextMenuTool );
41 return wxObjectDataPtr<LIB_TREE_MODEL_ADAPTER>( adapter );
42}
43
44
48 TOOL_INTERACTIVE* aContextMenuTool ) :
49 LIB_TREE_MODEL_ADAPTER( aParent, wxT( "pinned_design_block_libs" ), aSettings ),
50 m_libs( aLibs ),
51 m_frame( aParent ),
52 m_contextMenuTool( aContextMenuTool )
53{
54 auto width = m_cfg.column_widths.find( wxT( "Item" ) );
55
56 // Leave part of Description visible in the default 300-pixel docked pane.
57 if( width == m_cfg.column_widths.end() || !IsValidColumnWidth( width->second ) )
58 m_colWidths[wxT( "Item" )] = 225;
59}
60
61
63{
65 PROJECT_FILE& project = aParent->Prj().GetProjectFile();
67
68 for( const LIBRARY_TABLE_ROW* row : manager.Rows( LIBRARY_TABLE_TYPE::DESIGN_BLOCK ) )
69 {
70 if( row->Hidden() )
71 continue;
72
73 wxString libName = row->Nickname();
74
75 bool pinned = alg::contains( cfg->m_Session.pinned_design_block_libs, libName )
76 || alg::contains( project.m_PinnedDesignBlockLibs, libName );
77
78 std::vector<LIB_TREE_ITEM*> designBlocks = getDesignBlocks( aParent, libName );
79
80 // Design blocks come back in filesystem enumeration order, so they are not presorted;
81 // let AssignIntrinsicRanks() sort them by name.
82 DoAddLibrary( libName, row->Description(), designBlocks, pinned, false );
83
84 for( LIB_TREE_ITEM* designBlock : designBlocks )
85 delete designBlock;
86 }
87
88 m_tree.AssignIntrinsicRanks( m_shownColumns );
89}
90
91
93{
94 // A queued GtkTreeView scroll target holds a row reference into the nodes we are about to
95 // free. Unlike UpdateSearchString's reset, this teardown happens out-of-band, so the later
96 // CancelPendingScroll would flush the reference against freed memory. Drop it here while the
97 // rows it points at are still valid (#24757).
99
100 m_tree.Clear();
101}
102
103
105 const wxString& aLibName )
106{
107 std::vector<LIB_TREE_ITEM*> libList;
108
109 DESIGN_BLOCK_LIBRARY_ADAPTER* libs = m_frame->Prj().DesignBlockLibs();
110
111 std::vector<DESIGN_BLOCK*> blocks = libs->GetDesignBlocks( aLibName );
112
113 for( DESIGN_BLOCK* block : blocks )
114 {
115 LIB_ID id = block->GetLIB_ID();
116 id.SetLibNickname( aLibName );
117 block->SetLibId( id );
118 libList.emplace_back( block );
119 }
120
121 return libList;
122}
123
124
125wxString DESIGN_BLOCK_TREE_MODEL_ADAPTER::GenerateInfo( LIB_ID const& aLibId, int aUnit )
126{
127 static const wxString DescriptionFormat = wxT(
128 "<b>__NAME__</b>"
129 "__DESC__"
130 "__KEY__"
131 "<hr><table border=0>"
132 "__FIELDS__"
133 "</table>" );
134
135 static const wxString DescFormat = wxS( "<br>%s" );
136 static const wxString KeywordsFormat = wxS( "<br>" ) + _( "Keywords" ) + wxS( ": %s" );
137
138 static const wxString FieldFormat = wxT(
139 "<tr>"
140 " <td><b>__FIELD_NAME__</b></td>"
141 " <td>__FIELD_VALUE__</td>"
142 "</tr>" );
143
144
145 if( !aLibId.IsValid() )
146 return wxEmptyString;
147
148 const DESIGN_BLOCK* db = nullptr;
149
150 try
151 {
152 db = m_libs->GetEnumeratedDesignBlock( aLibId.GetLibNickname(), aLibId.GetLibItemName() );
153 }
154 catch( const IO_ERROR& ioe )
155 {
156 wxLogError( _( "Error loading design block %s from library '%s'." ) + wxS( "\n%s" ),
157 aLibId.GetLibItemName().wx_str(), aLibId.GetLibNickname().wx_str(), ioe.What() );
158
159 return wxEmptyString;
160 }
161
162 wxString html = DescriptionFormat;
163
164 if( db )
165 {
166 wxString name = aLibId.GetLibItemName();
167 wxString desc = db->GetLibDescription();
168 wxString keywords = db->GetKeywords();
169
170 html.Replace( "__NAME__", EscapeHTML( name ) );
171
172 wxString esc_desc = EscapeHTML( UnescapeString( desc ) );
173
174 // Add line breaks
175 esc_desc.Replace( wxS( "\n" ), wxS( "<br>" ) );
176
177 // Add links
178 esc_desc = LinkifyHTML( esc_desc );
179
180 if( esc_desc.IsEmpty() )
181 html.Replace( "__DESC__", wxEmptyString );
182 else
183 html.Replace( "__DESC__", wxString::Format( DescFormat, esc_desc ) );
184
185 if( keywords.IsEmpty() )
186 html.Replace( "__KEY__", wxEmptyString );
187 else
188 html.Replace( "__KEY__", wxString::Format( KeywordsFormat, EscapeHTML( keywords ) ) );
189
190 wxString fieldTable;
191
192 for( const auto& [key, value] : db->GetFields() )
193 {
194 wxString fieldRow = FieldFormat;
195 fieldRow.Replace( wxS( "__FIELD_NAME__" ), EscapeHTML( key ) );
196 fieldRow.Replace( wxS( "__FIELD_VALUE__" ), EscapeHTML( value ) );
197 fieldTable += fieldRow;
198 }
199
200 html.Replace( "__FIELDS__", fieldTable );
201
202 // Design blocks (unlike symbols and footprints) are not cached. We own the pointer.
203 delete db;
204 }
205 else
206 {
207 html.Printf( _( "Error loading design block %s from library '%s'." ) + wxS( "\n" ),
208 aLibId.GetLibItemName().wx_str(), aLibId.GetLibNickname().wx_str() );
209 }
210
211 return html;
212}
213
214
const char * name
std::vector< DESIGN_BLOCK * > GetDesignBlocks(const wxString &aNickname)
std::vector< LIB_TREE_ITEM * > getDesignBlocks(EDA_BASE_FRAME *aParent, const wxString &aLibName)
wxString GenerateInfo(LIB_ID const &aLibId, int aUnit) override
static wxObjectDataPtr< LIB_TREE_MODEL_ADAPTER > Create(EDA_BASE_FRAME *aParent, DESIGN_BLOCK_LIBRARY_ADAPTER *aLibs, APP_SETTINGS_BASE::LIB_TREE &aSettings, TOOL_INTERACTIVE *aContextMenuTool)
Factory function: create a model adapter in a reference-counting container.
DESIGN_BLOCK_TREE_MODEL_ADAPTER(EDA_BASE_FRAME *aParent, DESIGN_BLOCK_LIBRARY_ADAPTER *aLibs, APP_SETTINGS_BASE::LIB_TREE &aSettings, TOOL_INTERACTIVE *aContextMenuTool)
Constructor; takes a set of libraries to be included in the search.
const wxString & GetKeywords() const
const wxString & GetLibDescription() const
const nlohmann::ordered_map< wxString, wxString > & GetFields() const
The base frame for deriving all KiCad main window classes.
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
virtual const wxString What() const
A composite of Problem() and Where()
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
std::vector< LIBRARY_TABLE_ROW * > Rows(LIBRARY_TABLE_TYPE aType, LIBRARY_TABLE_SCOPE aScope=LIBRARY_TABLE_SCOPE::BOTH, bool aIncludeInvalid=false) const
Returns a flattened list of libraries of the given type.
A logical library item identifier and consists of various portions much like a URI.
Definition lib_id.h:45
bool IsValid() const
Check if this LID_ID is valid.
Definition lib_id.h:168
int SetLibNickname(const UTF8 &aLibNickname)
Override the logical library name portion of the LIB_ID to aLibNickname.
Definition lib_id.cpp:113
const UTF8 & GetLibItemName() const
Definition lib_id.h:98
const UTF8 & GetLibNickname() const
Return the logical library name portion of a LIB_ID.
Definition lib_id.h:83
A mix-in to provide polymorphism between items stored in libraries (symbols, aliases and footprints).
LIB_TREE_MODEL_ADAPTER(EDA_BASE_FRAME *aParent, const wxString &aPinnedKey, APP_SETTINGS_BASE::LIB_TREE &aSettingsStruct)
Create the adapter.
static bool IsValidColumnWidth(int aWidth)
APP_SETTINGS_BASE::LIB_TREE & m_cfg
std::map< wxString, int > m_colWidths
LIB_TREE_NODE_LIBRARY & DoAddLibrary(const wxString &aNodeName, const wxString &aDesc, const std::vector< LIB_TREE_ITEM * > &aItemList, bool aPinned, bool aPresorted)
Add the given list of symbols by alias.
std::vector< wxString > m_shownColumns
virtual COMMON_SETTINGS * GetCommonSettings() const
Definition pgm_base.cpp:546
virtual LIBRARY_MANAGER & GetLibraryManager() const
Definition pgm_base.h:125
The backing store for a PROJECT, in JSON format.
virtual PROJECT_FILE & GetProjectFile() const
Definition project.h:201
wxString wx_str() const
Definition utf8.cpp:41
#define _(s)
Base window classes and related definitions.
Abstract pattern-matching tool and implementations.
static const wxString KeywordsFormat
static const wxString DescriptionFormat
static const wxString DescFormat
static const wxString FieldFormat
void CancelPendingScroll(wxDataViewCtrl *aCtrl)
Cancel any pending scroll-to-item request on aCtrl.
Definition wxgtk/ui.cpp:542
bool contains(const _Container &__container, _Value __value)
Returns true if the container contains the given value.
Definition kicad_algo.h:96
PGM_BASE & Pgm()
The global program "get" accessor.
see class PGM_BASE
wxString EscapeHTML(const wxString &aString)
Return a new wxString escaped for embedding in HTML.
wxString UnescapeString(const wxString &aSource)
wxString LinkifyHTML(wxString aStr)
Wraps links in HTML tags.
std::vector< wxString > pinned_design_block_libs