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

int ProcessExecute (const wxString &aCommandLine, int aFlags=wxEXEC_ASYNC, wxProcess *callback=nullptr)
 Run a command in a child process. More...
 
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 307 of file common.cpp.

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

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

Referenced by DIALOG_GEN_FOOTPRINT_POSITION::CreateAsciiFiles(), DIALOG_GEN_FOOTPRINT_POSITION::CreateGerberFiles(), DIALOG_PLOT_SCHEMATIC::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 279 of file common.cpp.

280 {
281  // wxGetenv( wchar_t* ) is not re-entrant on linux.
282  // Put a lock on multithreaded use of wxGetenv( wchar_t* ), called from wxEpandEnvVars(),
283  static std::mutex getenv_mutex;
284 
285  std::lock_guard<std::mutex> lock( getenv_mutex );
286 
287  // We reserve the right to do this another way, by providing our own member function.
288  return KIwxExpandEnvVars( aString, aProject );
289 }
wxString KIwxExpandEnvVars(const wxString &str, const PROJECT *aProject)
Definition: common.cpp:128

References KIwxExpandEnvVars().

Referenced by FILENAME_RESOLVER::addPath(), FILENAME_RESOLVER::checkEnvVarPath(), S3D_PLUGIN_MANAGER::checkPluginName(), S3D_PLUGIN_MANAGER::checkPluginPath(), 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(), DS_DATA_MODEL::MakeFullFileName(), TEXT_BUTTON_FILE_BROWSER::OnButtonClick(), PANEL_SYM_LIB_TABLE::onConvertLegacyLibraries(), DIALOG_GENDRILL::OnGenReportFile(), DIALOG_PLOT::OnOutputDirectoryBrowseClicked(), DIALOG_EXPORT_SVG::OnOutputDirectoryBrowseClicked(), DIALOG_GENDRILL::OnOutputDirectoryBrowseClicked(), DIALOG_GEN_FOOTPRINT_POSITION::OnOutputDirectoryBrowseClicked(), DIALOG_PLOT_SCHEMATIC::OnOutputDirectoryBrowseClicked(), DIALOG_PLOT::Plot(), FILENAME_RESOLVER::ResolvePath(), ResolveUriByEnvVars(), FILENAME_RESOLVER::Set3DConfigDir(), S3D_CACHE::Set3DConfigDir(), FILENAME_RESOLVER::SetProject(), FILENAME_RESOLVER::ShortenPath(), and ERC_TESTER::TestTextVars().

◆ ExpandTextVars() [1/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 70 of file common.cpp.

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

References PROJECT::TextVarResolver().

◆ ExpandTextVars() [2/2]

wxString ExpandTextVars ( const wxString &  aSource,
const PROJECT aProject 
)

Definition at line 64 of file common.cpp.

65 {
66  return ExpandTextVars( aSource, nullptr, nullptr, aProject );
67 }
wxString ExpandTextVars(const wxString &aSource, const PROJECT *aProject)
Definition: common.cpp:64

References ExpandTextVars().

Referenced by AddGerberX2Header(), DS_DRAW_ITEM_LIST::BuildFullText(), ExpandTextVars(), PCB_TEXT::GetShownText(), SCH_FIELD::GetShownText(), SCH_TEXT::GetShownText(), FP_TEXT::GetShownText(), NETLIST_EXPORTER_XML::makeDesignHeader(), ResolveUriByEnvVars(), and TITLE_BLOCK::TextVarResolver().

◆ ProcessExecute()

int ProcessExecute ( const wxString &  aCommandLine,
int  aFlags = wxEXEC_ASYNC,
wxProcess *  callback = nullptr 
)

Run a command in a child process.

Parameters
aCommandLineThe process and any arguments to it all in a single string.
aFlagsThe same args as allowed for wxExecute()
callbackwxProcess implementing OnTerminate to be run when the child process finishes
Returns
pid of process, 0 in case of error (like return values of wxExecute()).

Definition at line 46 of file common.cpp.

47 {
48  return (int) wxExecute( aCommandLine, aFlags, callback );
49 }

Referenced by doPrintFile(), ExecuteFile(), GetAssociatedDocument(), OpenFile(), OpenPDF(), and SCH_EDIT_FRAME::WriteNetListFile().

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

293 {
294  wxString uri = ExpandTextVars( aUri, aProject );
295 
296  // URL-like URI: return as is.
297  wxURL url( uri );
298 
299  if( url.GetError() == wxURL_NOERR )
300  return uri;
301 
302  // Otherwise, the path points to a local file. Resolve environment variables if any.
303  return ExpandEnvVarSubstitutions( aUri, aProject );
304 }
wxString ExpandTextVars(const wxString &aSource, const PROJECT *aProject)
Definition: common.cpp:64
const wxString ExpandEnvVarSubstitutions(const wxString &aString, PROJECT *aProject)
Replace any environment variable & text variable references with their values.
Definition: common.cpp:279

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 }
wxString FindValidPath(const wxString &aFileName) const
Definition: search_stack.h:70
const wxChar *const tracePathsAndFiles
Flag to enable path and file name debug output.
Look for files in a number of paths.
Definition: search_stack.h:41
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:106
static wxString GetDocumentationPath()
Gets the documentation path, which is the base path for help files.
Definition: paths.cpp:253
void SystemDirsAppend(SEARCH_STACK *aSearchStack)
Append system places to aSearchStack in a platform specific way and pertinent to KiCad programs.
void AddPaths(const wxString &aPaths, int aIndex=-1)
Insert or append path(s).

References SEARCH_STACK::AddPaths(), SEARCH_STACK::FindValidPath(), 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.

TimestampDir

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

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

Definition at line 516 of file common.cpp.

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

References matchWild().

Referenced by FP_CACHE::GetTimestamp(), and GPCB_FPL_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 610 of file common.cpp.

611 {
613  return false;
614 
615  wxMessageDialog dialog( NULL, _( "This operating system is not supported "
616  "by KiCad and its dependencies." ),
617  _( "Unsupported Operating System" ),
618  wxOK | wxICON_EXCLAMATION );
619 
620  dialog.SetExtendedMessage( _( "Any issues with KiCad on this system cannot "
621  "be reported to the official bugtracker." ) );
622  dialog.ShowModal();
623 
624  return true;
625 }
bool IsOperatingSystemUnsupported()
Checks if the Operating System is explicitly unsupported and we want to prevent users from sending bu...
Definition: gtk/app.cpp:51
#define NULL
#define _(s)

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

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