1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2010-2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
5  * Copyright (C) 2012 Wayne Stambaugh <stambaughw@verizon.net>
6  * Copyright (C) 2012-2021 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 #ifndef FP_LIB_TABLE_H_
27 #define FP_LIB_TABLE_H_
28 
29 #include <lib_table_base.h>
30 #include <io_mgr.h>
31 
32 class FOOTPRINT;
33 class FP_LIB_TABLE_GRID;
34 
35 
36 /**
37  * Hold a record identifying a library accessed by the appropriate footprint library #PLUGIN
38  * object in the #FP_LIB_TABLE.
39  */
40 class FP_LIB_TABLE_ROW : public LIB_TABLE_ROW
41 {
42 public:
43     typedef IO_MGR::PCB_FILE_T LIB_T;
44 
45     FP_LIB_TABLE_ROW( const wxString& aNick, const wxString& aURI, const wxString& aType,
46                       const wxString& aOptions, const wxString& aDescr = wxEmptyString ) :
LIB_TABLE_ROW(aNick,aURI,aOptions,aDescr)47         LIB_TABLE_ROW( aNick, aURI, aOptions, aDescr )
48     {
49         SetType( aType );
50     }
51 
FP_LIB_TABLE_ROW()52     FP_LIB_TABLE_ROW() :
53         type( IO_MGR::KICAD_SEXP )
54     {
55     }
56 
57     bool operator==( const FP_LIB_TABLE_ROW& aRow ) const;
58 
59     bool operator!=( const FP_LIB_TABLE_ROW& aRow ) const   { return !( *this == aRow ); }
60 
61     /**
62      * return the type of footprint library table represented by this row.
63      */
GetType()64     const wxString GetType() const override         { return IO_MGR::ShowType( type ); }
65 
66     /**
67      * Change the type represented by this row.
68      */
69     void SetType( const wxString& aType ) override;
70 
71 protected:
FP_LIB_TABLE_ROW(const FP_LIB_TABLE_ROW & aRow)72     FP_LIB_TABLE_ROW( const FP_LIB_TABLE_ROW& aRow ) :
73         LIB_TABLE_ROW( aRow ),
74         type( aRow.type )
75     {
76     }
77 
78 private:
do_clone()79     virtual LIB_TABLE_ROW* do_clone() const override
80     {
81         return new FP_LIB_TABLE_ROW( *this );
82     }
83 
setPlugin(PLUGIN * aPlugin)84     void setPlugin( PLUGIN* aPlugin )
85     {
86         plugin.set( aPlugin );
87     }
88 
89     friend class FP_LIB_TABLE;
90 
91     PLUGIN::RELEASER  plugin;
92     LIB_T             type;
93 };
94 
95 
96 class FP_LIB_TABLE : public LIB_TABLE
97 {
98 public:
Type()99     KICAD_T Type() override { return FP_LIB_TABLE_T; }
100 
101     virtual void Parse( LIB_TABLE_LEXER* aLexer ) override;
102 
103     virtual void Format( OUTPUTFORMATTER* aOutput, int aIndentLevel ) const override;
104 
105     /**
106      * Build a footprint library table by pre-pending this table fragment in front of
107      * @a aFallBackTable.  Loading of this table fragment is done by using Parse().
108      *
109      * @param aFallBackTable is another FP_LIB_TABLE which is searched only when a row
110      *                       is not found in this table.  No ownership is taken of
111      *                       \a aFallBackTable.
112      */
113     FP_LIB_TABLE( FP_LIB_TABLE* aFallBackTable = nullptr );
114 
115     bool operator==( const FP_LIB_TABLE& aFpTable ) const;
116 
117     bool operator!=( const FP_LIB_TABLE& r ) const  { return !( *this == r ); }
118 
119     /**
120      * Return an #FP_LIB_TABLE_ROW if \a aNickName is found in this table or in any chained
121      * fall back table fragment.
122      *
123      * If \a aCheckIfEnabled is true, the library will be ignored even if it is disabled.
124      * Otherwise, the row found will be returned even if entry is disabled.
125      *
126      * The #PLUGIN is loaded and attached to the "plugin" field of the #FP_LIB_TABLE_ROW if
127      * not already loaded.
128      *
129      * @param aNickName is the name of library nickname to find.
130      * @param aCheckIfEnabled is the flag to check if the library found is enabled.
131      * @return the library \a NickName if found.
132      * @throw IO_ERROR if \a aNickName cannot be found.
133      */
134     const FP_LIB_TABLE_ROW* FindRow( const wxString& aNickName, bool aCheckIfEnabled = false );
135 
136     /**
137      * Return a list of footprint names contained within the library given by @a aNickname.
138      *
139      * @param aFootprintNames is the list to fill with the footprint names found in \a aNickname
140      * @param aNickname is a locator for the "library", it is a "name" in LIB_TABLE_ROW.
141      * @param aBestEfforts if true, don't throw on errors.
142      *
143      * @throw IO_ERROR if the library cannot be found, or footprint cannot be loaded.
144      */
145     void FootprintEnumerate( wxArrayString& aFootprintNames, const wxString& aNickname,
146                              bool aBestEfforts );
147 
148     /**
149      * Generate a hashed timestamp representing the last-mod-times of the library indicated
150      * by \a aNickname, or all libraries if \a aNickname is NULL.
151      */
152     long long GenerateTimestamp( const wxString* aNickname );
153 
154     /**
155      * If possible, prefetches the specified library (e.g. performing downloads). Does not parse.
156      * Threadsafe.
157      *
158      * This is a no-op for libraries that cannot be prefetched.
159      *
160      * @param aNickname is a locator for the library; it is a name in LIB_TABLE_ROW.
161      *
162      * @throw IO_ERROR if there is an error prefetching the library.
163      */
164     void PrefetchLib( const wxString& aNickname );
165 
166     /**
167      * Load a footprint having @a aFootprintName from the library given by @a aNickname.
168      *
169      * @param aNickname is a locator for the "library", it is a "name" in #LIB_TABLE_ROW.
170      * @param aFootprintName is the name of the footprint to load.
171      * @param aKeepUUID = true to keep initial items UUID, false to set new UUID
172      *                   normally true if loaded in the footprint editor, false
173      *                   if loaded in the board editor. Used only in kicad_plugin
174      * @return  the footprint if found caller owns it, else NULL if not found.
175      *
176      * @throw   IO_ERROR if the library cannot be found or read.  No exception
177      *          is thrown in the case where aFootprintName cannot be found.
178      */
179     FOOTPRINT* FootprintLoad( const wxString& aNickname, const wxString& aFootprintName,
180                               bool aKeepUUID = false );
181 
182     /**
183      * Indicates whether or not the given footprint already exists in the given library.
184      */
185     bool FootprintExists( const wxString& aNickname, const wxString& aFootprintName );
186 
187     /**
188      * A version of #FootprintLoad() for use after #FootprintEnumerate() for more efficient
189      * cache management.
190      *
191      * The return value is const to allow it to return a reference to a cached item.
192      */
193     const FOOTPRINT* GetEnumeratedFootprint( const wxString& aNickname,
194                                              const wxString& aFootprintName );
195     /**
196      * The set of return values from FootprintSave() below.
197      */
198     enum SAVE_T
199     {
200         SAVE_OK,
201         SAVE_SKIPPED,
202     };
203 
204     /**
205      * Write @a aFootprint to an existing library given by @a aNickname.
206      *
207      * If a footprint by the same name already exists, it is replaced.
208      *
209      * @param aNickname is a locator for the "library", it is a "name" in #LIB_TABLE_ROW.
210      * @param aFootprint is what to store in the library. The caller continues to own the
211      *                   footprint after this call.
212      * @param aOverwrite when true means overwrite any existing footprint by the same name,
213      *                   else if false means skip the write and return SAVE_SKIPPED.
214      * @return #SAVE_OK or #SAVE_SKIPPED.  If error saving, then #IO_ERROR is thrown.
215      *
216      * @throw IO_ERROR if there is a problem saving.
217      */
218     SAVE_T FootprintSave( const wxString& aNickname, const FOOTPRINT* aFootprint,
219                           bool aOverwrite = true );
220 
221     /**
222      * Delete the @a aFootprintName from the library given by @a aNickname.
223      *
224      * @param aNickname is a locator for the "library", it is a "name" in #LIB_TABLE_ROW.
225      * @param aFootprintName is the name of a footprint to delete from the specified library.
226      *
227      * @throw IO_ERROR if there is a problem finding the footprint or the library, or deleting it.
228      */
229     void FootprintDelete( const wxString& aNickname, const wxString& aFootprintName );
230 
231     /**
232      * Return true if the library given by @a aNickname is writable.
233      *
234      * Often system libraries are read only because of where they are installed.
235      *
236      * @throw IO_ERROR if no library at aLibraryPath exists.
237      */
238     bool IsFootprintLibWritable( const wxString& aNickname );
239 
240     void FootprintLibDelete( const wxString& aNickname );
241 
242     void FootprintLibCreate( const wxString& aNickname );
243 
244     /**
245      * Load a footprint having @a aFootprintId with possibly an empty nickname.
246      *
247      * @param aFootprintId the [nickname] and footprint name of the footprint to load.
248      * @param aKeepUUID = true to keep initial items UUID, false to set new UUID
249      *                   normally true if loaded in the footprint editor, false
250      *                   if loaded in the board editor
251      *                   used only in kicad_plugin
252      * @return  the #FOOTPRINT if found caller owns it, else NULL if not found.
253      *
254      * @throw   IO_ERROR if the library cannot be found or read.  No exception is
255      *                   thrown in the case where \a aFootprintName cannot be found.
256      * @throw   PARSE_ERROR if @a aFootprintId is not parsed OK.
257      */
258     FOOTPRINT* FootprintLoadWithOptionalNickname( const LIB_ID& aFootprintId,
259                                                   bool aKeepUUID = false );
260 
261     /**
262      * Load the global footprint library table into \a aTable.
263      *
264      * This probably should be move into the application object when KiCad is changed
265      * to a single process application.  This is the least painful solution for the
266      * time being.
267      *
268      * @param aTable the #FP_LIB_TABLE object to load.
269      * @return true if the global library table exists and is loaded properly.
270      * @throw IO_ERROR if an error occurs attempting to load the footprint library
271      *                 table.
272      */
273     static bool LoadGlobalTable( FP_LIB_TABLE& aTable );
274 
275     /**
276      * @return the platform specific global footprint library path and file name.
277      */
278     static wxString GetGlobalTableFileName();
279 
280     /**
281      * Return the name of the environment variable used to hold the directory of
282      * locally installed "KiCad sponsored" system footprint libraries.
283      *
284      *These can be either legacy or pretty format.  The only thing special about this
285      * particular environment variable is that it is set automatically by KiCad on
286      * program start up, <b>if</b> it is not set already in the environment.
287      */
288     static const wxString GlobalPathEnvVariableName();
289 
290 private:
291     friend class FP_LIB_TABLE_GRID;
292 };
293 
294 
295 extern FP_LIB_TABLE GFootprintTable;        // KIFACE scope.
296 
297 #endif  // FP_LIB_TABLE_H_
298