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, const PROJECT *aProject)
 Replace any environment variable & text variable references with their values. More...
 
wxString ExpandTextVars (const wxString &aSource, const std::function< bool(wxString *)> *aResolver)
 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 327 of file common.cpp.

330{
331 wxString msg;
332 wxString baseFilePath = wxFileName( aBaseFilename ).GetPath();
333
334 // make aTargetFullFileName path, which is relative to aBaseFilename path (if it is not
335 // already an absolute path) absolute:
336 if( !aTargetFullFileName->MakeAbsolute( baseFilePath ) )
337 {
338 if( aReporter )
339 {
340 msg.Printf( _( "Cannot make path '%s' absolute with respect to '%s'." ),
341 aTargetFullFileName->GetPath(),
342 baseFilePath );
343 aReporter->Report( msg, RPT_SEVERITY_ERROR );
344 }
345
346 return false;
347 }
348
349 // Ensure the path of aTargetFullFileName exists, and create it if needed:
350 wxString outputPath( aTargetFullFileName->GetPath() );
351
352 if( !wxFileName::DirExists( outputPath ) )
353 {
354 // Make every directory provided when the provided path doesn't exist
355 if( wxFileName::Mkdir( outputPath, wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL ) )
356 {
357 if( aReporter )
358 {
359 msg.Printf( _( "Output directory '%s' created." ), outputPath );
360 aReporter->Report( msg, RPT_SEVERITY_INFO );
361 return true;
362 }
363 }
364 else
365 {
366 if( aReporter )
367 {
368 msg.Printf( _( "Cannot create output directory '%s'." ), outputPath );
369 aReporter->Report( msg, RPT_SEVERITY_ERROR );
370 }
371
372 return false;
373 }
374 }
375
376 return true;
377}
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,
const 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 299 of file common.cpp.

300{
301 // wxGetenv( wchar_t* ) is not re-entrant on linux.
302 // Put a lock on multithreaded use of wxGetenv( wchar_t* ), called from wxEpandEnvVars(),
303 static std::mutex getenv_mutex;
304
305 std::lock_guard<std::mutex> lock( getenv_mutex );
306
307 // We reserve the right to do this another way, by providing our own member function.
308 return KIwxExpandEnvVars( aString, aProject );
309}
wxString KIwxExpandEnvVars(const wxString &str, const PROJECT *aProject, std::set< wxString > *aSet=nullptr)
Definition: common.cpp:118

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(), SIM_LIB_MGR::ResolveLibraryPath(), 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 *)> *  aResolver 
)

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

Definition at line 70 of file common.cpp.

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

◆ 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 312 of file common.cpp.

313{
314 wxString uri = ExpandTextVars( aUri, aProject );
315
316 // URL-like URI: return as is.
317 wxURL url( uri );
318
319 if( url.GetError() == wxURL_NOERR )
320 return uri;
321
322 // Otherwise, the path points to a local file. Resolve environment variables if any.
323 return ExpandEnvVarSubstitutions( aUri, aProject );
324}
const wxString ExpandEnvVarSubstitutions(const wxString &aString, const PROJECT *aProject)
Replace any environment variable & text variable references with their values.
Definition: common.cpp:299

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#ifndef __WIN32__
41 // just in case, add all known system directories to the search stack
42 SystemDirsAppend( &basePaths );
43#endif
44
45#if defined( DEBUG )
46 basePaths.Show( wxString( __func__ ) + wxS( ": basePaths" ) );
47#endif
48
49 // By default, the documentation from kicad-doc is installed to a folder called "help" with
50 // subdirectories for all supported languages. Although this can be changed at build-time by
51 // overwriting ${KICAD_DOC_PATH}, the best guess KiCad can make is that help files are always
52 // located in a folder named "help". If no translation matching the current locale settings is
53 // available, the English version will be returned instead.
54
55 wxLocale* currentLocale = Pgm().GetLocale();
56 wxArrayString localeNameDirs;
57
58 // canonical form of the current locale (e.g., "fr_FR")
59 localeNameDirs.Add( currentLocale->GetCanonicalName() );
60
61 // short form of the current locale (e.g., "fr")
62 // wxLocale::GetName() does not always return the short form
63 localeNameDirs.Add( currentLocale->GetName().BeforeLast( wxS( '_' ) ) );
64
65 // plain English (in case a localised version of the help file cannot be found)
66 localeNameDirs.Add( wxS( "en" ) );
67
68 for( wxString& locale : localeNameDirs )
69 {
70 SEARCH_STACK docPaths;
71
72 for( wxString& base : basePaths )
73 {
74 wxFileName path( base, wxEmptyString );
75
76 // add <base>/help/<locale>/
77 path.AppendDir( wxS( "help" ) );
78 path.AppendDir( locale );
79 docPaths.AddPaths( path.GetPath() );
80
81 // add <base>/doc/help/<locale>/
82 path.InsertDir( path.GetDirCount() - 2, wxS( "doc" ) );
83 docPaths.AddPaths( path.GetPath() );
84
85 // add <base>/doc/kicad/help/<locale>/
86 path.InsertDir( path.GetDirCount() - 2, wxS( "kicad" ) );
87 docPaths.AddPaths( path.GetPath() );
88 }
89
90#if defined( DEBUG )
91 docPaths.Show( wxString( __func__ ) + wxS( ": docPaths (" ) + locale + wxS( ")" ) );
92#endif
93
94 // search HTML first, as it is the preferred format for help files
95 wxLogTrace( tracePathsAndFiles, wxS( "Checking SEARCH_STACK for file %s.html" ),
96 aBaseName );
97 helpFile = docPaths.FindValidPath( aBaseName + wxS( ".html" ) );
98
99 if( !helpFile.IsEmpty() )
100 {
101 // prepend URI protocol to open the file in a browser
102 helpFile = wxS( "file://" ) + helpFile;
103 break;
104 }
105
106 // search PDF only when no corresponding HTML file was found
107 wxLogTrace( tracePathsAndFiles, wxS( "Checking SEARCH_STACK for file %s.pdf" ), aBaseName );
108 helpFile = docPaths.FindValidPath( aBaseName + wxS( ".pdf" ) );
109
110 if( !helpFile.IsEmpty() )
111 break;
112 }
113
114 return helpFile;
115}
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 536 of file common.cpp.

537{
538 long long timestamp = 0;
539
540#if defined( __WIN32__ )
541 // Win32 version.
542 // Save time by not searching for each path twice: once in wxDir.GetNext() and once in
543 // wxFileName.GetModificationTime(). Also cuts out wxWidgets' string-matching and case
544 // conversion by staying on the MSW side of things.
545 std::wstring filespec( aDirPath.t_str() );
546 filespec += '\\';
547 filespec += aFilespec.t_str();
548
549 WIN32_FIND_DATA findData;
550 wxDateTime lastModDate;
551
552 HANDLE fileHandle = ::FindFirstFile( filespec.data(), &findData );
553
554 if( fileHandle != INVALID_HANDLE_VALUE )
555 {
556 do
557 {
558 ConvertFileTimeToWx( &lastModDate, findData.ftLastWriteTime );
559 timestamp += lastModDate.GetValue().GetValue();
560
561 // Get the file size (partial) as well to check for sneaky changes.
562 timestamp += findData.nFileSizeLow;
563 }
564 while ( FindNextFile( fileHandle, &findData ) != 0 );
565 }
566
567 FindClose( fileHandle );
568#else
569 // POSIX version.
570 // Save time by not converting between encodings -- do everything on the file-system side.
571 std::string filespec( aFilespec.fn_str() );
572 std::string dir_path( aDirPath.fn_str() );
573
574 DIR* dir = opendir( dir_path.c_str() );
575
576 if( dir )
577 {
578 for( dirent* dir_entry = readdir( dir ); dir_entry; dir_entry = readdir( dir ) )
579 {
580 if( !matchWild( filespec.c_str(), dir_entry->d_name, true ) )
581 continue;
582
583 std::string entry_path = dir_path + '/' + dir_entry->d_name;
584 struct stat entry_stat;
585
586 if( wxCRT_Lstat( entry_path.c_str(), &entry_stat ) == 0 )
587 {
588 // Timestamp the source file, not the symlink
589 if( S_ISLNK( entry_stat.st_mode ) ) // wxFILE_EXISTS_SYMLINK
590 {
591 char buffer[ PATH_MAX + 1 ];
592 ssize_t pathLen = readlink( entry_path.c_str(), buffer, PATH_MAX );
593
594 if( pathLen > 0 )
595 {
596 struct stat linked_stat;
597 buffer[ pathLen ] = '\0';
598 entry_path = dir_path + buffer;
599
600 if( wxCRT_Lstat( entry_path.c_str(), &linked_stat ) == 0 )
601 {
602 entry_stat = linked_stat;
603 }
604 else
605 {
606 // if we couldn't lstat the linked file we'll have to just use
607 // the symbolic link info
608 }
609 }
610 }
611
612 if( S_ISREG( entry_stat.st_mode ) ) // wxFileExists()
613 {
614 timestamp += entry_stat.st_mtime * 1000;
615
616 // Get the file size as well to check for sneaky changes.
617 timestamp += entry_stat.st_size;
618 }
619 }
620 else
621 {
622 // if we couldn't lstat the file itself all we can do is use the name
623 timestamp += (signed) std::hash<std::string>{}( std::string( dir_entry->d_name ) );
624 }
625 }
626
627 closedir( dir );
628 }
629#endif
630
631 return timestamp;
632}
bool matchWild(const char *pat, const char *text, bool dot_special)
Performance enhancements to file and directory operations.
Definition: common.cpp:394

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 635 of file common.cpp.

636{
638 return false;
639
640 wxMessageDialog dialog( nullptr, _( "This operating system is not supported "
641 "by KiCad and its dependencies." ),
642 _( "Unsupported Operating System" ),
643 wxOK | wxICON_EXCLAMATION );
644
645 dialog.SetExtendedMessage( _( "Any issues with KiCad on this system cannot "
646 "be reported to the official bugtracker." ) );
647 dialog.ShowModal();
648
649 return true;
650}
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().