KiCad PCB EDA Suite
common.h File Reference

The common library. More...

#include <functional>
#include <memory>
#include <wx/fileconf.h>
#include <wx/string.h>
#include <wx/process.h>

Go to the source code of this file.

Functions

wxString SearchHelpFileFullPath (const wxString &aBaseName)
 Return the help file's full path. More...
 
bool EnsureFileDirectoryExists (wxFileName *aTargetFullFileName, const wxString &aBaseFilename, REPORTER *aReporter=nullptr)
 Make aTargetFullFileName absolute and create the path of this file if it doesn't yet exist. More...
 
const wxString ExpandEnvVarSubstitutions (const wxString &aString, PROJECT *aProject)
 Replace any environment variable & text variable references with their values. More...
 
wxString ExpandTextVars (const wxString &aSource, const std::function< bool(wxString *)> *aLocalResolver, const std::function< bool(wxString *)> *aFallbackResolver, const PROJECT *aProject)
 Expand '${var-name}' templates in text. More...
 
wxString ExpandTextVars (const wxString &aSource, const PROJECT *aProject)
 
const wxString ResolveUriByEnvVars (const wxString &aUri, PROJECT *aProject)
 Replace any environment and/or text variables in file-path uris (leaving network-path URIs alone). More...
 
long long TimestampDir (const wxString &aDirPath, const wxString &aFilespec)
 A copy of ConvertFileTimeToWx() because wxWidgets left it as a static function private to src/common/filename.cpp. More...
 
bool WarnUserIfOperatingSystemUnsupported ()
 Checks if the operating system is explicitly unsupported and displays a disclaimer message box. More...
 

Detailed Description

The common library.

Definition in file common.h.

Function Documentation

◆ EnsureFileDirectoryExists()

bool EnsureFileDirectoryExists ( wxFileName *  aTargetFullFileName,
const wxString &  aBaseFilename,
REPORTER aReporter = nullptr 
)

Make aTargetFullFileName absolute and create the path of this file if it doesn't yet exist.

Parameters
aTargetFullFileNamethe wxFileName containing the full path and file name to modify. The path may be absolute or relative to aBaseFilename .
aBaseFilenamea full filename. Only its path is used to set the aTargetFullFileName path.
aReportera point to a REPORTER object use to show messages (can be NULL)
Returns
true if aOutputDir already exists or was successfully created.

Definition at line 295 of file common.cpp.

298{
299 wxString msg;
300 wxString baseFilePath = wxFileName( aBaseFilename ).GetPath();
301
302 // make aTargetFullFileName path, which is relative to aBaseFilename path (if it is not
303 // already an absolute path) absolute:
304 if( !aTargetFullFileName->MakeAbsolute( baseFilePath ) )
305 {
306 if( aReporter )
307 {
308 msg.Printf( _( "Cannot make path '%s' absolute with respect to '%s'." ),
309 aTargetFullFileName->GetPath(),
310 baseFilePath );
311 aReporter->Report( msg, RPT_SEVERITY_ERROR );
312 }
313
314 return false;
315 }
316
317 // Ensure the path of aTargetFullFileName exists, and create it if needed:
318 wxString outputPath( aTargetFullFileName->GetPath() );
319
320 if( !wxFileName::DirExists( outputPath ) )
321 {
322 // Make every directory provided when the provided path doesn't exist
323 if( wxFileName::Mkdir( outputPath, wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL ) )
324 {
325 if( aReporter )
326 {
327 msg.Printf( _( "Output directory '%s' created." ), outputPath );
328 aReporter->Report( msg, RPT_SEVERITY_INFO );
329 return true;
330 }
331 }
332 else
333 {
334 if( aReporter )
335 {
336 msg.Printf( _( "Cannot create output directory '%s'." ), outputPath );
337 aReporter->Report( msg, RPT_SEVERITY_ERROR );
338 }
339
340 return false;
341 }
342 }
343
344 return true;
345}
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)=0
Report a string with a given severity.
#define _(s)
@ RPT_SEVERITY_ERROR
@ RPT_SEVERITY_INFO

References _, REPORTER::Report(), RPT_SEVERITY_ERROR, and RPT_SEVERITY_INFO.

Referenced by DIALOG_GEN_FOOTPRINT_POSITION::CreateAsciiFiles(), DIALOG_GEN_FOOTPRINT_POSITION::CreateGerberFiles(), SCH_PLOTTER::createPlotFileName(), DIALOG_EXPORT_SVG::ExportSVGFile(), DIALOG_GENDRILL::GenDrillAndMapFiles(), PLOT_CONTROLLER::OpenPlotfile(), and DIALOG_PLOT::Plot().

◆ ExpandEnvVarSubstitutions()

const wxString ExpandEnvVarSubstitutions ( const wxString &  aString,
PROJECT aProject 
)

Replace any environment variable & text variable references with their values.

Parameters
aStringa string containing (perhaps) references to env var
Returns
the expanded environment variable.

Definition at line 267 of file common.cpp.

268{
269 // wxGetenv( wchar_t* ) is not re-entrant on linux.
270 // Put a lock on multithreaded use of wxGetenv( wchar_t* ), called from wxEpandEnvVars(),
271 static std::mutex getenv_mutex;
272
273 std::lock_guard<std::mutex> lock( getenv_mutex );
274
275 // We reserve the right to do this another way, by providing our own member function.
276 return KIwxExpandEnvVars( aString, aProject );
277}
wxString KIwxExpandEnvVars(const wxString &str, const PROJECT *aProject)
Definition: common.cpp:121

References KIwxExpandEnvVars().

Referenced by FILENAME_RESOLVER::addPath(), FILENAME_RESOLVER::checkEnvVarPath(), S3D_PLUGIN_MANAGER::checkPluginName(), DIALOG_GEN_FOOTPRINT_POSITION::CreateAsciiFiles(), DIALOG_GEN_FOOTPRINT_POSITION::CreateGerberFiles(), FILENAME_RESOLVER::createPathList(), DIALOG_EXPORT_SVG::ExportSVGFile(), DIALOG_GENDRILL::GenDrillAndMapFiles(), LIB_TABLE_ROW::GetFullURI(), DIALOG_PLOT_SCHEMATIC::getOutputPath(), TEXT_BUTTON_FILE_BROWSER::OnButtonClick(), PANEL_SYM_LIB_TABLE::onConvertLegacyLibraries(), DIALOG_GENDRILL::OnGenReportFile(), DIALOG_PLOT_SCHEMATIC::OnOutputDirectoryBrowseClicked(), DIALOG_EXPORT_SVG::OnOutputDirectoryBrowseClicked(), DIALOG_GEN_FOOTPRINT_POSITION::OnOutputDirectoryBrowseClicked(), DIALOG_GENDRILL::OnOutputDirectoryBrowseClicked(), DIALOG_PLOT::OnOutputDirectoryBrowseClicked(), DIALOG_PAGES_SETTINGS::OnWksFileSelection(), PLOT_CONTROLLER::OpenPlotfile(), DIALOG_PLOT::Plot(), FILENAME_RESOLVER::ResolvePath(), DS_DATA_MODEL::ResolvePath(), ResolveUriByEnvVars(), S3D_CACHE::Set3DConfigDir(), FILENAME_RESOLVER::Set3DConfigDir(), FILENAME_RESOLVER::SetProject(), FILENAME_RESOLVER::ShortenPath(), ERC_TESTER::TestTextVars(), and NETLIST_EXPORTER_SPICE::writeInclude().

◆ ExpandTextVars() [1/2]

◆ ExpandTextVars() [2/2]

wxString ExpandTextVars ( const wxString &  aSource,
const std::function< bool(wxString *)> *  aLocalResolver,
const std::function< bool(wxString *)> *  aFallbackResolver,
const PROJECT aProject 
)

Expand '${var-name}' templates in text.

The LocalResolver is given first crack at it, after which the PROJECT's resolver is called.

Definition at line 63 of file common.cpp.

67{
68 wxString newbuf;
69 size_t sourceLen = aSource.length();
70
71 newbuf.Alloc( sourceLen ); // best guess (improves performance)
72
73 for( size_t i = 0; i < sourceLen; ++i )
74 {
75 if( aSource[i] == '$' && i + 1 < sourceLen && aSource[i+1] == '{' )
76 {
77 wxString token;
78
79 for( i = i + 2; i < sourceLen; ++i )
80 {
81 if( aSource[i] == '}' )
82 break;
83 else
84 token.append( aSource[i] );
85 }
86
87 if( token.IsEmpty() )
88 continue;
89
90 if( aLocalResolver && (*aLocalResolver)( &token ) )
91 {
92 newbuf.append( token );
93 }
94 else if( aProject && aProject->TextVarResolver( &token ) )
95 {
96 newbuf.append( token );
97 }
98 else if( aFallbackResolver && (*aFallbackResolver)( &token ) )
99 {
100 newbuf.append( token );
101 }
102 else
103 {
104 // Token not resolved: leave the reference unchanged
105 newbuf.append( "${" + token + "}" );
106 }
107 }
108 else
109 {
110 newbuf.append( aSource[i] );
111 }
112 }
113
114 return newbuf;
115}
virtual bool TextVarResolver(wxString *aToken) const
Definition: project.cpp:70

References PROJECT::TextVarResolver().

◆ ResolveUriByEnvVars()

const wxString ResolveUriByEnvVars ( const wxString &  aUri,
PROJECT aProject 
)

Replace any environment and/or text variables in file-path uris (leaving network-path URIs alone).

Definition at line 280 of file common.cpp.

281{
282 wxString uri = ExpandTextVars( aUri, aProject );
283
284 // URL-like URI: return as is.
285 wxURL url( uri );
286
287 if( url.GetError() == wxURL_NOERR )
288 return uri;
289
290 // Otherwise, the path points to a local file. Resolve environment variables if any.
291 return ExpandEnvVarSubstitutions( aUri, aProject );
292}
const wxString ExpandEnvVarSubstitutions(const wxString &aString, PROJECT *aProject)
Replace any environment variable & text variable references with their values.
Definition: common.cpp:267

References ExpandEnvVarSubstitutions(), and ExpandTextVars().

Referenced by GetAssociatedDocument().

◆ SearchHelpFileFullPath()

wxString SearchHelpFileFullPath ( const wxString &  aBaseName)

Return the help file's full path.

Return the full path and name (including extension) of the given KiCad help file. It is expected to be found in a subfolder help/<LANG>/ in one of the system paths. Supported file types are *.html and *.pdf. If no such file is available for the current locale, an attempt to find the English version is made. The search order for <LANG> is: 1) canonical form (e.g., "fr_FR"), 2) short form (e.g., "fr"), and 3) "en".

Parameters
aBaseNameis the name of the help file to search for (without extension).
Returns
the full path and filename if aBaseName is found, else wxEmptyString.

Definition at line 32 of file searchhelpfilefullpath.cpp.

33{
34 SEARCH_STACK basePaths;
35 wxString helpFile;
36
37 // help files are most likely located in the documentation install path
38 basePaths.Add( PATHS::GetDocumentationPath() );
39
40 // just in case, add all known system directories to the search stack
41 SystemDirsAppend( &basePaths );
42
43#if defined( DEBUG )
44 basePaths.Show( wxString( __func__ ) + ": basePaths" );
45#endif
46
47 // By default, the documentation from kicad-doc is installed to a folder called "help" with
48 // subdirectories for all supported languages. Although this can be changed at build-time by
49 // overwriting ${KICAD_DOC_PATH}, the best guess KiCad can make is that help files are always
50 // located in a folder named "help". If no translation matching the current locale settings is
51 // available, the English version will be returned instead.
52
53 wxLocale* currentLocale = Pgm().GetLocale();
54 wxArrayString localeNameDirs;
55
56 // canonical form of the current locale (e.g., "fr_FR")
57 localeNameDirs.Add( currentLocale->GetCanonicalName() );
58
59 // short form of the current locale (e.g., "fr")
60 // wxLocale::GetName() does not always return the short form
61 localeNameDirs.Add( currentLocale->GetName().BeforeLast( '_' ) );
62
63 // plain English (in case a localised version of the help file cannot be found)
64 localeNameDirs.Add( "en" );
65
66 for( wxString& locale : localeNameDirs )
67 {
68 SEARCH_STACK docPaths;
69
70 for( wxString& base : basePaths )
71 {
72 wxFileName path( base, wxEmptyString );
73
74 // add <base>/help/<locale>/
75 path.AppendDir( "help" );
76 path.AppendDir( locale );
77 docPaths.AddPaths( path.GetPath() );
78
79 // add <base>/doc/help/<locale>/
80 path.InsertDir( path.GetDirCount() - 2, "doc" );
81 docPaths.AddPaths( path.GetPath() );
82
83 // add <base>/doc/kicad/help/<locale>/
84 path.InsertDir( path.GetDirCount() - 2, "kicad" );
85 docPaths.AddPaths( path.GetPath() );
86 }
87
88#if defined( DEBUG )
89 docPaths.Show( wxString( __func__ ) + ": docPaths (" + locale + ")" );
90#endif
91
92 // search HTML first, as it is the preferred format for help files
93 wxLogTrace( tracePathsAndFiles, "Checking SEARCH_STACK for file %s.html", aBaseName );
94 helpFile = docPaths.FindValidPath( aBaseName + ".html" );
95
96 if( !helpFile.IsEmpty() )
97 {
98 // prepend URI protocol to open the file in a browser
99 helpFile = "file://" + helpFile;
100 break;
101 }
102
103 // search PDF only when no corresponding HTML file was found
104 wxLogTrace( tracePathsAndFiles, "Checking SEARCH_STACK for file %s.pdf", aBaseName );
105 helpFile = docPaths.FindValidPath( aBaseName + ".pdf" );
106
107 if( !helpFile.IsEmpty() )
108 break;
109 }
110
111 return helpFile;
112}
static wxString GetDocumentationPath()
Gets the documentation path, which is the base path for help files.
Definition: paths.cpp:333
Look for files in a number of paths.
Definition: search_stack.h:42
void AddPaths(const wxString &aPaths, int aIndex=-1)
Insert or append path(s).
const wxChar *const tracePathsAndFiles
Flag to enable path and file name debug output.
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:111
void SystemDirsAppend(SEARCH_STACK *aSearchStack)
Append system places to aSearchStack in a platform specific way and pertinent to KiCad programs.

References SEARCH_STACK::AddPaths(), PATHS::GetDocumentationPath(), path, Pgm(), SystemDirsAppend(), and tracePathsAndFiles.

Referenced by COMMON_CONTROL::ShowHelp().

◆ TimestampDir()

long long TimestampDir ( const wxString &  aDirPath,
const wxString &  aFilespec 
)

A copy of ConvertFileTimeToWx() because wxWidgets left it as a static function private to src/common/filename.cpp.

This routine offers SIGNIFICANT performance benefits over using wxWidgets to gather timestamps from matching files in a directory.

Parameters
aDirPathis the directory to search.
aFilespecis a (wildcarded) file spec to match against.
Returns
a hash of the last-mod-dates of all matching files in the directory.

Definition at line 504 of file common.cpp.

505{
506 long long timestamp = 0;
507
508#if defined( __WIN32__ )
509 // Win32 version.
510 // Save time by not searching for each path twice: once in wxDir.GetNext() and once in
511 // wxFileName.GetModificationTime(). Also cuts out wxWidgets' string-matching and case
512 // conversion by staying on the MSW side of things.
513 std::wstring filespec( aDirPath.t_str() );
514 filespec += '\\';
515 filespec += aFilespec.t_str();
516
517 WIN32_FIND_DATA findData;
518 wxDateTime lastModDate;
519
520 HANDLE fileHandle = ::FindFirstFile( filespec.data(), &findData );
521
522 if( fileHandle != INVALID_HANDLE_VALUE )
523 {
524 do
525 {
526 ConvertFileTimeToWx( &lastModDate, findData.ftLastWriteTime );
527 timestamp += lastModDate.GetValue().GetValue();
528
529 // Get the file size (partial) as well to check for sneaky changes.
530 timestamp += findData.nFileSizeLow;
531 }
532 while ( FindNextFile( fileHandle, &findData ) != 0 );
533 }
534
535 FindClose( fileHandle );
536#else
537 // POSIX version.
538 // Save time by not converting between encodings -- do everything on the file-system side.
539 std::string filespec( aFilespec.fn_str() );
540 std::string dir_path( aDirPath.fn_str() );
541
542 DIR* dir = opendir( dir_path.c_str() );
543
544 if( dir )
545 {
546 for( dirent* dir_entry = readdir( dir ); dir_entry; dir_entry = readdir( dir ) )
547 {
548 if( !matchWild( filespec.c_str(), dir_entry->d_name, true ) )
549 continue;
550
551 std::string entry_path = dir_path + '/' + dir_entry->d_name;
552 struct stat entry_stat;
553
554 if( wxCRT_Lstat( entry_path.c_str(), &entry_stat ) == 0 )
555 {
556 // Timestamp the source file, not the symlink
557 if( S_ISLNK( entry_stat.st_mode ) ) // wxFILE_EXISTS_SYMLINK
558 {
559 char buffer[ PATH_MAX + 1 ];
560 ssize_t pathLen = readlink( entry_path.c_str(), buffer, PATH_MAX );
561
562 if( pathLen > 0 )
563 {
564 struct stat linked_stat;
565 buffer[ pathLen ] = '\0';
566 entry_path = dir_path + buffer;
567
568 if( wxCRT_Lstat( entry_path.c_str(), &linked_stat ) == 0 )
569 {
570 entry_stat = linked_stat;
571 }
572 else
573 {
574 // if we couldn't lstat the linked file we'll have to just use
575 // the symbolic link info
576 }
577 }
578 }
579
580 if( S_ISREG( entry_stat.st_mode ) ) // wxFileExists()
581 {
582 timestamp += entry_stat.st_mtime * 1000;
583
584 // Get the file size as well to check for sneaky changes.
585 timestamp += entry_stat.st_size;
586 }
587 }
588 else
589 {
590 // if we couldn't lstat the file itself all we can do is use the name
591 timestamp += (signed) std::hash<std::string>{}( std::string( dir_entry->d_name ) );
592 }
593 }
594
595 closedir( dir );
596 }
597#endif
598
599 return timestamp;
600}
bool matchWild(const char *pat, const char *text, bool dot_special)
Performance enhancements to file and directory operations.
Definition: common.cpp:362

References matchWild().

Referenced by GPCB_FPL_CACHE::GetTimestamp(), and FP_CACHE::GetTimestamp().

◆ WarnUserIfOperatingSystemUnsupported()

bool WarnUserIfOperatingSystemUnsupported ( )

Checks if the operating system is explicitly unsupported and displays a disclaimer message box.

Returns
true if the operating system is unsupported

Definition at line 603 of file common.cpp.

604{
606 return false;
607
608 wxMessageDialog dialog( nullptr, _( "This operating system is not supported "
609 "by KiCad and its dependencies." ),
610 _( "Unsupported Operating System" ),
611 wxOK | wxICON_EXCLAMATION );
612
613 dialog.SetExtendedMessage( _( "Any issues with KiCad on this system cannot "
614 "be reported to the official bugtracker." ) );
615 dialog.ShowModal();
616
617 return true;
618}
bool IsOperatingSystemUnsupported()
Checks if the Operating System is explicitly unsupported and we want to prevent users from sending bu...
Definition: gtk/app.cpp:51

References _, and KIPLATFORM::APP::IsOperatingSystemUnsupported().

Referenced by PGM_BASE::InitPgm(), and COMMON_CONTROL::ReportBug().