31#include <wx/mimetype.h> 
   40#include "wx/tokenzr.h" 
   42#include <wx/wfstream.h> 
   44#include <wx/zipstrm.h> 
   50    if( !
string.StartsWith( wxT( 
"\"" ) ) )
 
   52        string.Prepend ( wxT( 
"\"" ) );
 
   53        string.Append ( wxT( 
"\"" ) );
 
 
   67    if( wxFileExists( fullFileName ) )
 
   70    if( wxGetEnv( wxT( 
"KICAD_RUN_FROM_BUILD_DIR" ), 
nullptr ) )
 
   72        wxFileName buildDir( 
Pgm().GetExecutablePath(), shortname );
 
   73        buildDir.RemoveLastDir();
 
   75        buildDir.AppendDir( shortname );
 
   77        buildDir.AppendDir( shortname.BeforeLast( 
'.' ) );
 
   80        if( buildDir.GetDirs().Last() == 
"pl_editor" )
 
   82            buildDir.RemoveLastDir();
 
   83            buildDir.AppendDir( 
"pagelayout_editor" );
 
   86        if( wxFileExists( buildDir.GetFullPath() ) )
 
   87            return buildDir.GetFullPath();
 
   92    if( 
Pgm().IsKicadEnvVariableDefined() )
 
   96        if( wxFileExists( fullFileName ) )
 
  100#if defined( __WINDOWS__ ) 
  107    const static wxChar* possibilities[] = {
 
  108#if defined( __WXMAC__ ) 
  110        wxT( 
"Contents/Applications/pcbnew.app/Contents/MacOS/" ),
 
  111        wxT( 
"Contents/Applications/eeschema.app/Contents/MacOS/" ),
 
  112        wxT( 
"Contents/Applications/gerbview.app/Contents/MacOS/" ),
 
  113        wxT( 
"Contents/Applications/bitmap2component.app/Contents/MacOS/" ),
 
  114        wxT( 
"Contents/Applications/pcb_calculator.app/Contents/MacOS/" ),
 
  115        wxT( 
"Contents/Applications/pl_editor.app/Contents/MacOS/" ),
 
  118        wxT( 
"/usr/local/bin/" ),
 
  119        wxT( 
"/usr/local/kicad/bin/" ),
 
  124    for( 
unsigned i=0;  i<
arrayDim(possibilities);  ++i )
 
  127        fullFileName = possibilities[i] + shortname;
 
  133        if( wxFileExists( fullFileName ) )
 
 
  143int ExecuteFile( 
const wxString& aEditorName, 
const wxString& aFileName, wxProcess* aCallback,
 
  146    wxString              fullEditorName;
 
  147    std::vector<wxString> params;
 
  151    bool     inSingleQuotes = 
false;
 
  152    bool     inDoubleQuotes = 
false;
 
  157                if( !param.IsEmpty() )
 
  159                    params.push_back( param );
 
  164    for( wxUniChar ch : aEditorName )
 
  171                inSingleQuotes = 
false;
 
  179        else if( inDoubleQuotes )
 
  184                inDoubleQuotes = 
false;
 
  191        else if( ch == 
'\'' )
 
  194            inSingleQuotes = 
true;
 
  199            inDoubleQuotes = 
true;
 
  216        fullEditorName = params[0];
 
  218    params.erase( params.begin() );
 
  224        fullEditorName = aEditorName;
 
  227    if( wxFileExists( fullEditorName ) )
 
  229        std::vector<const wchar_t*> args;
 
  231        args.emplace_back( fullEditorName.wc_str() );
 
  233        if( !params.empty() )
 
  235            for( 
const wxString& p : params )
 
  236                args.emplace_back( p.wc_str() );
 
  239        if( !aFileName.IsEmpty() )
 
  240            args.emplace_back( aFileName.wc_str() );
 
  242        args.emplace_back( 
nullptr );
 
  244        return wxExecute( 
const_cast<wchar_t**
>( args.data() ), wxEXEC_ASYNC, aCallback );
 
  248    msg.Printf( 
_( 
"Command '%s' could not be found." ), fullEditorName );
 
 
  257    wxString filename = file;
 
  261    if( 
Pgm().UseSystemPdfBrowser() )
 
  265            msg.Printf( 
_( 
"Unable to find a PDF viewer for '%s'." ), filename );
 
  272        const wchar_t* args[3];
 
  275        args[1] = filename.wc_str();
 
  278        if( wxExecute( 
const_cast<wchar_t**
>( args ) ) == -1 )
 
  280            msg.Printf( 
_( 
"Problem while running the PDF viewer '%s'." ), args[0] );
 
 
  290void KiCopyFile( 
const wxString& aSrcPath, 
const wxString& aDestPath, wxString& aErrors )
 
  292    if( !wxCopyFile( aSrcPath, aDestPath ) )
 
  296        if( !aErrors.IsEmpty() )
 
  299        msg.Printf( 
_( 
"Cannot copy file '%s'." ), aDestPath );
 
 
  307    return wxT( 
"\"" ) + fn.GetFullPath( format ) + wxT( 
"\"" );
 
 
  313    namespace fs = std::filesystem;
 
  315    std::string rmDir = aFileName.ToStdString();
 
  317    if( rmDir.length() < 3 )
 
  320            *aErrors = 
_( 
"Invalid directory name, cannot remove root" );
 
  325    if( !fs::exists( rmDir ) )
 
  328            *aErrors = wxString::Format( 
_( 
"Directory '%s' does not exist" ), aFileName );
 
  333    fs::path 
path( rmDir );
 
  335    if( !fs::is_directory( 
path ) )
 
  338            *aErrors = wxString::Format( 
_( 
"'%s' is not a directory" ), aFileName );
 
  345        fs::remove_all( 
path );
 
  347    catch( 
const fs::filesystem_error& e )
 
  350            *aErrors = wxString::Format( 
_( 
"Error removing directory '%s': %s" ),
 
  351                                         aFileName, e.what() );
 
 
  360bool CopyDirectory( 
const wxString& aSourceDir, 
const wxString& aDestDir, wxString& aErrors )
 
  362    wxDir dir( aSourceDir );
 
  364    if( !dir.IsOpened() )
 
  366        aErrors += wxString::Format( 
_( 
"Could not open source directory: %s" ), aSourceDir );
 
  367        aErrors += wxT( 
"\n" );
 
  371    if( !wxFileName::Mkdir( aDestDir, wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL ) )
 
  373        aErrors += wxString::Format( 
_( 
"Could not create destination directory: %s" ), aDestDir );
 
  374        aErrors += wxT( 
"\n" );
 
  379    bool     cont = dir.GetFirst( &filename );
 
  383        wxString sourcePath = aSourceDir + wxFileName::GetPathSeparator() + filename;
 
  384        wxString destPath = aDestDir + wxFileName::GetPathSeparator() + filename;
 
  386        if( wxFileName::DirExists( sourcePath ) )
 
  395            if( !wxCopyFile( sourcePath, destPath ) )
 
  397                aErrors += wxString::Format( 
_( 
"Could not copy file: %s to %s" ),
 
  404        cont = dir.GetNext( &filename );
 
 
  412                           int& aFileCopiedCount, 
const std::vector<wxString>& aExclusions )
 
  415    wxFileName sourceFn( aSourcePath );
 
  416    wxString   sourcePath = sourceFn.GetFullPath();
 
  417    bool       isSourceDirectory = wxFileName::DirExists( sourcePath );
 
  418    wxString   baseDestDir = aDestDir;
 
  420    auto performCopy = [&]( 
const wxString& src, 
const wxString& dest ) -> 
bool 
  422        if( wxCopyFile( src, dest ) )
 
  428        aErrors += wxString::Format( 
_( 
"Could not copy file: %s to %s" ), src, dest );
 
  429        aErrors += wxT( 
"\n" );
 
  433    auto processEntries = [&]( 
const wxString& srcDir, 
const wxString& pattern,
 
  434                               const wxString& destDir ) -> 
bool 
  438        if( !dir.IsOpened() )
 
  440            aErrors += wxString::Format( 
_( 
"Could not open source directory: %s" ), srcDir );
 
  441            aErrors += wxT( 
"\n" );
 
  449        bool cont = dir.GetFirst( &filename, pattern, wxDIR_FILES | wxDIR_DIRS | wxDIR_HIDDEN );
 
  453            const wxString entrySrc = srcDir + wxFileName::GetPathSeparator() + filename;
 
  454            const wxString entryDest = destDir + wxFileName::GetPathSeparator() + filename;
 
  458                    filename.Matches( wxT( 
"~*.lck" ) ) || filename.Matches( wxT( 
"*.lck" ) );
 
  460            for( 
const auto& exclusion : aExclusions )
 
  462                if( entrySrc.Matches( exclusion ) )
 
  471                if( wxFileName::DirExists( entrySrc ) )
 
  477                        aErrors += wxString::Format( 
_( 
"Could not copy directory: %s to %s" ),
 
  478                                                     entrySrc, entryDest );
 
  479                        aErrors += wxT( 
"\n" );
 
  487                    if( !performCopy( entrySrc, entryDest ) )
 
  494            cont = dir.GetNext( &filename );
 
  501    if( isSourceDirectory )
 
  503        wxString sourceDirName = sourceFn.GetFullName();
 
  504        baseDestDir = wxFileName( aDestDir, sourceDirName ).GetFullPath();
 
  508    if( !wxFileName::Mkdir( baseDestDir, wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL ) )
 
  511                wxString::Format( 
_( 
"Could not create destination directory: %s" ), baseDestDir );
 
  512        aErrors += wxT( 
"\n" );
 
  518    if( !isSourceDirectory )
 
  520        const wxString fileName = sourceFn.GetFullName();
 
  523        if( fileName.Contains( 
'*' ) || fileName.Contains( 
'?' ) )
 
  525            const wxString dirPath = sourceFn.GetPath();
 
  527            if( !wxFileName::DirExists( dirPath ) )
 
  529                aErrors += wxString::Format( 
_( 
"Source directory does not exist: %s" ), dirPath );
 
  530                aErrors += wxT( 
"\n" );
 
  535            return processEntries( dirPath, fileName, baseDestDir );
 
  539        return performCopy( sourcePath, wxFileName( baseDestDir, fileName ).GetFullPath() );
 
  543    return processEntries( sourcePath, wxEmptyString, baseDestDir );
 
 
  548                        const wxString& aParentDir )
 
  550    wxDir dir( aSourceDir );
 
  552    if( !dir.IsOpened() )
 
  554        aErrors += wxString::Format( 
_( 
"Could not open source directory: %s" ), aSourceDir );
 
  560    bool     cont = dir.GetFirst( &filename );
 
  564        wxString sourcePath = aSourceDir + wxFileName::GetPathSeparator() + filename;
 
  565        wxString zipPath = aParentDir + filename;
 
  567        if( wxFileName::DirExists( sourcePath ) )
 
  570            aZip.PutNextDirEntry( zipPath + 
"/" );
 
  579            aZip.PutNextEntry( zipPath );
 
  580            wxFFileInputStream fileStream( sourcePath );
 
  582            if( !fileStream.IsOk() )
 
  584                aErrors += wxString::Format( 
_( 
"Could not read file: %s" ), sourcePath );
 
  588            aZip.Write( fileStream );
 
  591        cont = dir.GetNext( &filename );
 
 
constexpr std::size_t arrayDim(T const (&)[N]) noexcept
Returns # of elements in an array.
 
virtual const wxString & GetKicadEnvVariable() const
 
virtual void ReadPdfBrowserInfos()
Read the PDF browser choice from the common configuration.
 
virtual const wxString & GetPdfBrowserName() const
 
virtual const wxString & GetExecutablePath() const
 
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
 
This file is part of the common library.
 
wxString FindKicadFile(const wxString &shortname)
Search the executable file shortname in KiCad binary path and return full file name if found or short...
 
wxString QuoteFullPath(wxFileName &fn, wxPathFormat format)
Quote return value of wxFileName::GetFullPath().
 
bool OpenPDF(const wxString &file)
Run the PDF viewer and display a PDF file.
 
void KiCopyFile(const wxString &aSrcPath, const wxString &aDestPath, wxString &aErrors)
 
int ExecuteFile(const wxString &aEditorName, const wxString &aFileName, wxProcess *aCallback, bool aFileForKicad)
Call the executable file aEditorName with the parameter aFileName.
 
bool CopyFilesOrDirectory(const wxString &aSourcePath, const wxString &aDestDir, wxString &aErrors, int &aFileCopiedCount, const std::vector< wxString > &aExclusions)
 
bool RmDirRecursive(const wxString &aFileName, wxString *aErrors)
Remove the directory aDirName and all its contents including subdirectories and their files.
 
void QuoteString(wxString &string)
Add un " to the start and the end of string (if not already done).
 
bool CopyDirectory(const wxString &aSourceDir, const wxString &aDestDir, wxString &aErrors)
Copy a directory and its contents to another directory.
 
bool AddDirectoryToZip(wxZipOutputStream &aZip, const wxString &aSourceDir, wxString &aErrors, const wxString &aParentDir)
Add a directory and its contents to a zip file.
 
bool LaunchExternal(const wxString &aPath)
Launches the given file or folder in the host OS.
 
PGM_BASE & Pgm()
The global program "get" accessor.