1 /*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2021 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 along
17 * with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include <wx/filename.h>
21 #include <wx/stdpaths.h>
22 #include <wx/string.h>
23 #include <wx/utils.h>
24
25 #include <kiplatform/environment.h>
26 #include <paths.h>
27 #include <pgm_base.h>
28 #include <settings/settings_manager.h>
29 #include <config.h>
30
31 // lowercase or pretty case depending on platform
32 #if defined( __WXMAC__ ) || defined( __WXMSW__ )
33 #define KICAD_PATH_STR "KiCad"
34 #else
35 #define KICAD_PATH_STR "kicad"
36 #endif
37
38
getUserDocumentPath(wxFileName & aPath)39 void PATHS::getUserDocumentPath( wxFileName& aPath )
40 {
41 wxString envPath;
42
43 if( wxGetEnv( wxT( "KICAD_DOCUMENTS_HOME" ), &envPath ) )
44 aPath.AssignDir( envPath );
45 else
46 aPath.AssignDir( KIPLATFORM::ENV::GetDocumentsPath() );
47
48 aPath.AppendDir( KICAD_PATH_STR );
49 aPath.AppendDir( SETTINGS_MANAGER::GetSettingsVersion() );
50 }
51
52
GetUserPluginsPath()53 wxString PATHS::GetUserPluginsPath()
54 {
55 wxFileName tmp;
56 getUserDocumentPath( tmp );
57
58 tmp.AppendDir( "plugins" );
59
60 return tmp.GetPath();
61 }
62
63
GetUserPlugins3DPath()64 wxString PATHS::GetUserPlugins3DPath()
65 {
66 wxFileName tmp;
67
68 tmp.AssignDir( PATHS::GetUserPluginsPath() );
69 tmp.AppendDir( "3d" );
70
71 return tmp.GetPath();
72 }
73
74
GetUserScriptingPath()75 wxString PATHS::GetUserScriptingPath()
76 {
77 wxFileName tmp;
78 getUserDocumentPath( tmp );
79
80 tmp.AppendDir( "scripting" );
81
82 return tmp.GetPath();
83 }
84
85
GetUserTemplatesPath()86 wxString PATHS::GetUserTemplatesPath()
87 {
88 wxFileName tmp;
89 getUserDocumentPath( tmp );
90
91 tmp.AppendDir( "template" );
92
93 return tmp.GetPathWithSep();
94 }
95
96
GetDefaultUserSymbolsPath()97 wxString PATHS::GetDefaultUserSymbolsPath()
98 {
99 wxFileName tmp;
100 getUserDocumentPath( tmp );
101
102 tmp.AppendDir( "symbols" );
103
104 return tmp.GetPath();
105 }
106
107
GetDefaultUserFootprintsPath()108 wxString PATHS::GetDefaultUserFootprintsPath()
109 {
110 wxFileName tmp;
111 getUserDocumentPath( tmp );
112
113 tmp.AppendDir( "footprints" );
114
115 return tmp.GetPath();
116 }
117
118
GetDefaultUser3DModelsPath()119 wxString PATHS::GetDefaultUser3DModelsPath()
120 {
121 wxFileName tmp;
122 getUserDocumentPath( tmp );
123
124 tmp.AppendDir( "3dmodels" );
125
126 return tmp.GetPath();
127 }
128
GetDefault3rdPartyPath()129 wxString PATHS::GetDefault3rdPartyPath()
130 {
131 wxFileName tmp;
132 getUserDocumentPath( tmp );
133
134 tmp.AppendDir( "3rdparty" );
135
136 return tmp.GetPath();
137 }
138
GetDefaultUserProjectsPath()139 wxString PATHS::GetDefaultUserProjectsPath()
140 {
141 wxFileName tmp;
142 getUserDocumentPath( tmp );
143
144 tmp.AppendDir( "projects" );
145
146 return tmp.GetPath();
147 }
148
149
GetStockDataPath(bool aRespectRunFromBuildDir)150 wxString PATHS::GetStockDataPath( bool aRespectRunFromBuildDir )
151 {
152 wxString path;
153
154 if( aRespectRunFromBuildDir && wxGetEnv( wxT( "KICAD_RUN_FROM_BUILD_DIR" ), nullptr ) )
155 {
156 // Allow debugging from build dir by placing relevant files/folders in the build root
157 #if defined( __WXMAC__ )
158 wxFileName fn = wxStandardPaths::Get().GetExecutablePath();
159
160 fn.RemoveLastDir();
161 fn.RemoveLastDir();
162 fn.RemoveLastDir();
163 fn.RemoveLastDir();
164 path = fn.GetPath();
165 #elif defined( __WXMSW__ )
166 path = getWindowsKiCadRoot();
167 #else
168 path = Pgm().GetExecutablePath() + wxT( ".." );
169 #endif
170 }
171 else
172 {
173 #if defined( __WXMAC__ )
174 path = GetOSXKicadDataDir();
175 #elif defined( __WXMSW__ )
176 path = getWindowsKiCadRoot() + wxT( "share/kicad" );
177 #else
178 path = wxString::FromUTF8Unchecked( KICAD_DATA );
179 #endif
180 }
181
182 return path;
183 }
184
185
GetStockEDALibraryPath()186 wxString PATHS::GetStockEDALibraryPath()
187 {
188 wxString path;
189
190 #if defined( __WXMAC__ )
191 path = GetOSXKicadMachineDataDir();
192 #elif defined( __WXMSW__ )
193 path = GetStockDataPath( false );
194 #else
195 path = wxString::FromUTF8Unchecked( KICAD_LIBRARY_DATA );
196 #endif
197
198 return path;
199 }
200
201
GetStockSymbolsPath()202 wxString PATHS::GetStockSymbolsPath()
203 {
204 wxString path;
205
206 path = GetStockDataPath() + wxT( "/symbols" );
207
208 return path;
209 }
210
211
GetStockFootprintsPath()212 wxString PATHS::GetStockFootprintsPath()
213 {
214 wxString path;
215
216 path = GetStockDataPath() + wxT( "/footprints" );
217
218 return path;
219 }
220
221
GetStock3dmodelsPath()222 wxString PATHS::GetStock3dmodelsPath()
223 {
224 wxString path;
225
226 path = GetStockDataPath() + wxT( "/3dmodels" );
227
228 return path;
229 }
230
231
GetStockScriptingPath()232 wxString PATHS::GetStockScriptingPath()
233 {
234 wxString path;
235
236 path = GetStockDataPath() + wxT( "/scripting" );
237
238 return path;
239 }
240
241
GetStockPluginsPath()242 wxString PATHS::GetStockPluginsPath()
243 {
244 wxFileName fn;
245
246 #if defined( __WXMSW__ )
247 fn.AssignDir( Pgm().GetExecutablePath() );
248 fn.AppendDir( wxT( "scripting" ) );
249 #else
250 fn.AssignDir( PATHS::GetStockDataPath( false ) );
251 #endif
252 fn.AppendDir( wxT( "plugins" ) );
253
254 return fn.GetPathWithSep();
255 }
256
257
GetStockPlugins3DPath()258 wxString PATHS::GetStockPlugins3DPath()
259 {
260 wxFileName fn;
261
262 #ifdef __WXGTK__
263 // KICAD_PLUGINDIR = CMAKE_INSTALL_FULL_LIBDIR path is the absolute path
264 // corresponding to the install path used for constructing KICAD_USER_PLUGIN
265 wxString tfname = wxString::FromUTF8Unchecked( KICAD_PLUGINDIR );
266 fn.Assign( tfname, "" );
267 fn.AppendDir( wxT( "kicad" ) );
268 fn.AppendDir( wxT( "plugins" ) );
269 #elif defined( __WXMAC__ )
270 fn.Assign( wxStandardPaths::Get().GetPluginsDir(), wxEmptyString );
271 #else
272 fn.AssignDir( Pgm().GetExecutablePath() );
273 fn.AppendDir( wxT( "plugins" ) );
274 #endif
275
276 fn.AppendDir( "3d" );
277
278 return fn.GetPathWithSep();
279 }
280
281
GetStockDemosPath()282 wxString PATHS::GetStockDemosPath()
283 {
284 wxFileName fn;
285
286 fn.AssignDir( PATHS::GetStockDataPath( false ) );
287 fn.AppendDir( wxT( "demos" ) );
288
289 return fn.GetPathWithSep();
290 }
291
292
GetUserCachePath()293 wxString PATHS::GetUserCachePath()
294 {
295 wxFileName tmp;
296
297 tmp.AssignDir( KIPLATFORM::ENV::GetUserCachePath() );
298 tmp.AppendDir( KICAD_PATH_STR );
299 tmp.AppendDir( SETTINGS_MANAGER::GetSettingsVersion() );
300
301 return tmp.GetPathWithSep();
302 }
303
304
GetDocumentationPath()305 wxString PATHS::GetDocumentationPath()
306 {
307 wxString path;
308
309 #if defined( __WXMAC__ )
310 path = GetOSXKicadDataDir();
311 #elif defined( __WXMSW__ )
312 path = getWindowsKiCadRoot() + "share/doc/kicad";
313 #else
314 path = wxString::FromUTF8Unchecked( KICAD_DOCS );
315 #endif
316
317 return path;
318 }
319
320
EnsurePathExists(const wxString & aPath)321 bool PATHS::EnsurePathExists( const wxString& aPath )
322 {
323 wxFileName path( aPath );
324 if( !path.Normalize() )
325 {
326 return false;
327 }
328
329 if( !wxFileName::DirExists( aPath ) )
330 {
331 if( !wxFileName::Mkdir( aPath, wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL ) )
332 {
333 return false;
334 }
335 }
336
337 return true;
338 }
339
340
EnsureUserPathsExist()341 void PATHS::EnsureUserPathsExist()
342 {
343 EnsurePathExists( GetUserPluginsPath() );
344 EnsurePathExists( GetUserPlugins3DPath() );
345 EnsurePathExists( GetUserScriptingPath() );
346 EnsurePathExists( GetUserTemplatesPath() );
347 EnsurePathExists( GetDefaultUserProjectsPath() );
348 EnsurePathExists( GetDefaultUserSymbolsPath() );
349 EnsurePathExists( GetDefaultUserFootprintsPath() );
350 EnsurePathExists( GetDefaultUser3DModelsPath() );
351 EnsurePathExists( GetDefault3rdPartyPath() );
352 }
353
354
355 #ifdef __WXMAC__
GetOSXKicadUserDataDir()356 wxString PATHS::GetOSXKicadUserDataDir()
357 {
358 // According to wxWidgets documentation for GetUserDataDir:
359 // Mac: ~/Library/Application Support/appname
360 wxFileName udir( wxStandardPaths::Get().GetUserDataDir(), wxEmptyString );
361
362 // Since appname is different if started via launcher or standalone binary
363 // map all to "kicad" here
364 udir.RemoveLastDir();
365 udir.AppendDir( "kicad" );
366
367 return udir.GetPath();
368 }
369
370
GetOSXKicadMachineDataDir()371 wxString PATHS::GetOSXKicadMachineDataDir()
372 {
373 // 6.0 forward: Same as the main data dir
374 return GetOSXKicadDataDir();
375 }
376
377
GetOSXKicadDataDir()378 wxString PATHS::GetOSXKicadDataDir()
379 {
380 // According to wxWidgets documentation for GetDataDir:
381 // Mac: appname.app/Contents/SharedSupport bundle subdirectory
382 wxFileName ddir( wxStandardPaths::Get().GetDataDir(), wxEmptyString );
383
384 // This must be mapped to main bundle for everything but kicad.app
385 const wxArrayString dirs = ddir.GetDirs();
386
387 // Check if we are the main kicad binary. in this case, the path will be
388 // /path/to/bundlename.app/Contents/SharedSupport
389 // If we are an aux binary, the path will be something like
390 // /path/to/bundlename.app/Contents/Applications/<standalone>.app/Contents/SharedSupport
391 if( dirs.GetCount() >= 6 &&
392 dirs[dirs.GetCount() - 4] == wxT( "Applications" ) &&
393 dirs[dirs.GetCount() - 6].Lower().EndsWith( wxT( "app" ) ) )
394 {
395 ddir.RemoveLastDir();
396 ddir.RemoveLastDir();
397 ddir.RemoveLastDir();
398 ddir.RemoveLastDir();
399 ddir.AppendDir( wxT( "SharedSupport" ) );
400 }
401
402 return ddir.GetPath();
403 }
404 #endif
405
406
407 #ifdef __WXWINDOWS__
getWindowsKiCadRoot()408 wxString PATHS::getWindowsKiCadRoot()
409 {
410 wxFileName root( Pgm().GetExecutablePath() + "/../" );
411 root.Normalize();
412
413 return root.GetPathWithSep();
414 }
415 #endif
416