1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2014-2021 KiCad Developers, see AUTHORS.txt for contributors.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU 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, you may find one here:
18  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19  * or you may search the http://www.gnu.org website for the version 2 license,
20  * or you may write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
22  */
23 #ifndef PROJECT_H_
24 #define PROJECT_H_
25 
26 /**
27  * @file project.h
28  */
29 #include <map>
30 #include <vector>
31 #include <kiid.h>
32 #include <wx/string.h>
33 #include <wx/filename.h>
34 #include <core/typeinfo.h>
35 
36 /// A variable name whose value holds the current project directory.
37 /// Currently an environment variable, eventually a project variable.
38 #define PROJECT_VAR_NAME            wxT( "KIPRJMOD" )
39 
40 /// default name for nameless projects
41 #define NAMELESS_PROJECT _( "untitled" )
42 
43 class wxConfigBase;
44 class PARAM_CFG;
45 class FP_LIB_TABLE;
46 class SYMBOL_LIBS;
47 class SEARCH_STACK;
48 class S3D_CACHE;
49 class KIWAY;
50 class SYMBOL_LIB_TABLE;
51 class FILENAME_RESOLVER;
52 class PROJECT_FILE;
53 class PROJECT_LOCAL_SETTINGS;
54 
55 
56 /**
57  * Container for project specific data.
58  *
59  * Because it is in the neutral program top, which is not linked to by subsidiary DSOs,
60  * any functions in this interface must be virtual.
61  */
62 class PROJECT
63 {
64 public:
65     /**
66      * A #PROJECT can hold stuff it knows nothing about, in the form of _ELEM derivatives.
67      *
68      * Derive #PROJECT elements from this, it has a virtual destructor, and Elem*() functions
69      * can work with it.  Implementation is opaque in class #PROJECT.  If find you have to
70      * include derived class headers in this file, you are doing incompatible with the goal
71      * of this class.  Keep knowledge of derived classes opaque to class PROJECT please.
72     */
73     class _ELEM
74     {
75     public:
~_ELEM()76         virtual ~_ELEM() {}
77 
78         virtual KICAD_T Type() = 0;     // Sanity-checking for returned values.
79     };
80 
81     PROJECT();
82     virtual ~PROJECT();
83 
84     //-----<Cross Module API>----------------------------------------------------
85 
86     virtual bool TextVarResolver( wxString* aToken ) const;
87 
88     virtual std::map<wxString, wxString>& GetTextVars() const;
89 
90     /**
91      * Return the full path and name of the project.
92      *
93      * This is the same as the name of the project file (.pro prior to version 6 and .kicad_prj
94      * from version 6 onwards) and will always be an absolute path.
95      */
96     virtual const wxString GetProjectFullName() const;
97 
98     /**
99      * Return the full path of the project.
100      *
101      * This is the path of the project file and will always be an absolute path, ending with
102      * a path separator.
103      */
104     virtual const wxString GetProjectPath() const;
105 
106     /**
107      * Return the short name of the project.
108      *
109      * This is the file name without extension or path.
110      */
111     virtual const wxString GetProjectName() const;
112 
113     /**
114      * Check if this project is a null project (i.e. the default project object created when
115      * no real project is open).
116      *
117      * The null project still presents all the same project interface, but is not backed by
118      * any files, so saving it makes no sense.
119      *
120      * @return true if this is an empty project.
121      */
122     virtual bool IsNullProject() const;
123 
IsReadOnly()124     virtual bool IsReadOnly() const { return m_readOnly || IsNullProject(); }
125 
126     virtual void SetReadOnly( bool aReadOnly = true ) { m_readOnly = aReadOnly; }
127 
128     /**
129      * Return the name of the sheet identified by the given UUID.
130      */
131     virtual const wxString GetSheetName( const KIID& aSheetID );
132 
133     /**
134      * Returns the path and filename of this project's footprint library table.
135      *
136      * This project specific footprint library table not the global one.
137      */
138     virtual const wxString FootprintLibTblName() const;
139 
140     /**
141      * Return the path and file name of this projects symbol library table.
142      */
143     virtual const wxString SymbolLibTableName() const;
144 
GetProjectFile()145     virtual PROJECT_FILE& GetProjectFile() const
146     {
147         wxASSERT( m_projectFile );
148         return *m_projectFile;
149     }
150 
GetLocalSettings()151     virtual PROJECT_LOCAL_SETTINGS& GetLocalSettings() const
152     {
153         wxASSERT( m_localSettings );
154         return *m_localSettings;
155     }
156 
157     /// Retain a number of project specific wxStrings, enumerated here:
158     enum RSTRING_T
159     {
160         DOC_PATH,
161         SCH_LIB_PATH,
162         SCH_LIB_SELECT,               // eeschema/selpart.cpp
163         SCH_LIBEDIT_CUR_LIB,
164         SCH_LIBEDIT_CUR_SYMBOL,       // eeschema/libeditframe.cpp
165 
166         VIEWER_3D_PATH,
167         VIEWER_3D_FILTER_INDEX,
168 
169         PCB_LIB_NICKNAME,
170         PCB_FOOTPRINT,
171         PCB_FOOTPRINT_EDITOR_FP_NAME,
172         PCB_FOOTPRINT_EDITOR_LIB_NICKNAME,
173         PCB_FOOTPRINT_VIEWER_FP_NAME,
174         PCB_FOOTPRINT_VIEWER_LIB_NICKNAME,
175 
176         RSTRING_COUNT
177     };
178 
179     /**
180      * Return a "retained string", which is any session and project specific string
181      * identified in enum #RSTRING_T.
182      *
183      * Retained strings are not written to disk, and are therefore good only for the current
184      * session.
185      */
186     virtual const wxString& GetRString( RSTRING_T aStringId );
187 
188     /**
189      * Store a "retained string", which is any session and project specific string
190      * identified in enum #RSTRING_T.
191      *
192      * Retained strings are not written to disk, and are therefore good only for the current
193      * session.
194      */
195     virtual void SetRString( RSTRING_T aStringId, const wxString& aString );
196 
197     /**
198      * The set of #_ELEMs that a #PROJECT can hold.
199      */
200     enum ELEM_T
201     {
202         ELEM_FPTBL,
203 
204         ELEM_SCH_SYMBOL_LIBS,
205         ELEM_SCH_SEARCH_STACK,
206         ELEM_3DCACHE,
207         ELEM_SYMBOL_LIB_TABLE,
208 
209         ELEM_COUNT
210     };
211 
212     /**
213      * Get and set the elements for this project.
214      *
215      * This is a cross module API, therefore the #_ELEM destructor is virtual and
216      * can point to a destructor function in another link image.  Be careful that
217      * that program module is resident at time of destruction.
218      *
219      * Summary:
220      *  -#) cross module API.
221      *  -#) #PROJECT knows nothing about #_ELEM objects except how to delete them and
222      *      set and get pointers to them.
223      */
224     virtual  _ELEM*  GetElem( ELEM_T aIndex );
225     virtual  void    SetElem( ELEM_T aIndex, _ELEM* aElem );
226 
227     /**
228      * Delete all the _ELEMs and set their pointers to NULL.
229      */
230     virtual void ElemsClear();
231 
232     /**
233      * Clear the _ELEMs and RSTRINGs.
234      */
Clear()235     void Clear()        // inline not virtual
236     {
237         ElemsClear();
238 
239         for( unsigned i = 0; i<RSTRING_COUNT;  ++i )
240             SetRString( RSTRING_T( i ), wxEmptyString );
241     }
242 
243     /**
244      * Fix up @a aFileName if it is relative to the project's directory to be an absolute
245      * path and filename.
246      *
247      * This intends to overcome the now missing chdir() into the project directory.
248      */
249     virtual const wxString AbsolutePath( const wxString& aFileName ) const;
250 
251     /**
252      * Return the table of footprint libraries. Requires an active Kiway as this is fetched
253      * from Pcbnew.
254      */
255     virtual FP_LIB_TABLE* PcbFootprintLibs( KIWAY& aKiway );
256 
257     // These are the non-virtual DATA LOAD ON DEMAND members. They load project related
258     // data on demand, and do so typically into m_elems[] at a particular index using
259     // SetElem() & GetElem().  That is, they wrap SetElem() and GetElem().
260     // To get the data to reload on demand, first SetProjectFullName(),
261     // then call SetElem( ELEM_T, NULL ) from client code.
262 
263     // non-virtuals resident in PCBNEW link image(s).  By being non-virtual, these
264     // functions can get linked into the KIFACE that needs them, and only there.
265     // In fact, the other KIFACEs don't even know they exist.
266 #if defined( PCBNEW ) || defined( CVPCB )
267     /**
268      * Return the table of footprint libraries without Kiway, only from within Pcbnew.
269      */
270     FP_LIB_TABLE* PcbFootprintLibs();
271 
272     /**
273      * Return a pointer to an instance of the 3D cache manager.
274      *
275      * An instance is created and initialized if appropriate.
276      *
277      * @return a pointer to an instance of the 3D cache manager or NULL on failure.
278      */
279     S3D_CACHE* Get3DCacheManager( bool updateProjDir = false );
280 
281     /// Accessor for 3D path resolver
282     FILENAME_RESOLVER* Get3DFilenameResolver();
283 #endif
284 
285 
286 #if defined( EESCHEMA )
287     // These are all prefaced with "Sch"
288     SYMBOL_LIBS*  SchLibs();
289 
290     /// Accessor for Eeschema search stack.
291     SEARCH_STACK*  SchSearchS();
292 
293     /// Accessor for project symbol library table.
294     SYMBOL_LIB_TABLE* SchSymbolLibTable();
295 
296     /// Accessor for 3D path resolver
Get3DFilenameResolver()297     FILENAME_RESOLVER* Get3DFilenameResolver() { return nullptr; }
298 #endif
299 
300 private:
301     friend class SETTINGS_MANAGER; // so that SM can set project path
302     friend class TEST_NETLISTS_FIXTURE; // TODO(JE) make this not required
303 
304     /**
305      * Set the full directory, basename, and extension of the project.
306      *
307      * This is the name of the project file with full absolute path and it also defines
308      * the name of the project.  The project name and the project file names are exactly
309      * the same, providing the project filename is absolute.
310      */
311     virtual void setProjectFullName( const wxString& aFullPathAndName );
312 
313     /**
314      * Set the backing store file for this project.
315      *
316      * This should only be called by #SETTINGS_MANGER on load.
317      *
318      * @param aFile is a loaded PROJECT_FILE.
319      */
setProjectFile(PROJECT_FILE * aFile)320     virtual void setProjectFile( PROJECT_FILE* aFile )
321     {
322         m_projectFile = aFile;
323     }
324 
325     /**
326      * Set the local settings backing store.
327      *
328      * This should only be called by #SETTINGS_MANAGER on load.
329      *
330      * @param aSettings is the local settings object (may or may not exist on disk at this point)
331      */
setLocalSettings(PROJECT_LOCAL_SETTINGS * aSettings)332     virtual void setLocalSettings( PROJECT_LOCAL_SETTINGS* aSettings )
333     {
334         m_localSettings = aSettings;
335     }
336 
337     /**
338      * Return the full path and file name of the project specific library table \a aLibTableName..
339      */
340     const wxString libTableName( const wxString& aLibTableName ) const;
341 
342     wxFileName      m_project_name;         ///< \<fullpath\>/\<basename\>.pro
343     wxString        m_pro_date_and_time;
344 
345     ///< True if the project is read-only: no project files will be written
346     bool m_readOnly;
347 
348     /// Backing store for project data -- owned by SETTINGS_MANAGER
349     PROJECT_FILE*   m_projectFile;
350 
351     /// Backing store for project local settings -- owned by SETTINGS_MANAGER
352     PROJECT_LOCAL_SETTINGS* m_localSettings;
353 
354     std::map<KIID, wxString>     m_sheetNames;
355 
356     /// @see this::SetRString(), GetRString(), and enum RSTRING_T.
357     wxString        m_rstrings[RSTRING_COUNT];
358 
359     /// @see this::Elem() and enum ELEM_T.
360     _ELEM*          m_elems[ELEM_COUNT];
361 };
362 
363 
364 #endif  // PROJECT_H_
365