KiCad PCB EDA Suite
Loading...
Searching...
No Matches
gestfich.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2004 Jean-Pierre Charras, [email protected]
5 * Copyright (C) 2008 Wayne Stambaugh <[email protected]>
6 * Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, you may find one here:
20 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21 * or you may search the http://www.gnu.org website for the version 2 license,
22 * or you may write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24 */
25
31#include <wx/mimetype.h>
32#include <wx/dir.h>
33
34#include <pgm_base.h>
35#include <confirm.h>
36#include <core/arraydim.h>
37#include <gestfich.h>
38#include <string_utils.h>
39#include <launch_ext.h>
40#include "wx/tokenzr.h"
41
42#include <filesystem>
43
44void QuoteString( wxString& string )
45{
46 if( !string.StartsWith( wxT( "\"" ) ) )
47 {
48 string.Prepend ( wxT( "\"" ) );
49 string.Append ( wxT( "\"" ) );
50 }
51}
52
53
54wxString FindKicadFile( const wxString& shortname )
55{
56 // Test the presence of the file in the directory shortname of
57 // the KiCad binary path.
58#ifndef __WXMAC__
59 wxString fullFileName = Pgm().GetExecutablePath() + shortname;
60#else
61 wxString fullFileName = Pgm().GetExecutablePath() + wxT( "Contents/MacOS/" ) + shortname;
62#endif
63 if( wxFileExists( fullFileName ) )
64 return fullFileName;
65
66 if( wxGetEnv( wxT( "KICAD_RUN_FROM_BUILD_DIR" ), nullptr ) )
67 {
68 wxFileName buildDir( Pgm().GetExecutablePath(), shortname );
69 buildDir.RemoveLastDir();
70#ifndef __WXMSW__
71 buildDir.AppendDir( shortname );
72#else
73 buildDir.AppendDir( shortname.BeforeLast( '.' ) );
74#endif
75
76 if( buildDir.GetDirs().Last() == "pl_editor" )
77 {
78 buildDir.RemoveLastDir();
79 buildDir.AppendDir( "pagelayout_editor" );
80 }
81
82 if( wxFileExists( buildDir.GetFullPath() ) )
83 return buildDir.GetFullPath();
84 }
85
86 // Test the presence of the file in the directory shortname
87 // defined by the environment variable KiCad.
88 if( Pgm().IsKicadEnvVariableDefined() )
89 {
90 fullFileName = Pgm().GetKicadEnvVariable() + shortname;
91
92 if( wxFileExists( fullFileName ) )
93 return fullFileName;
94 }
95
96#if defined( __WINDOWS__ )
97 // kicad can be installed highly portably on Windows, anywhere and concurrently
98 // either the "kicad file" is immediately adjacent to the exe or it's not a valid install
99 return shortname;
100#else
101
102 // Path list for KiCad binary files
103 const static wxChar* possibilities[] = {
104#if defined( __WXMAC__ )
105 // all internal paths are relative to main bundle kicad.app
106 wxT( "Contents/Applications/pcbnew.app/Contents/MacOS/" ),
107 wxT( "Contents/Applications/eeschema.app/Contents/MacOS/" ),
108 wxT( "Contents/Applications/gerbview.app/Contents/MacOS/" ),
109 wxT( "Contents/Applications/bitmap2component.app/Contents/MacOS/" ),
110 wxT( "Contents/Applications/pcb_calculator.app/Contents/MacOS/" ),
111 wxT( "Contents/Applications/pl_editor.app/Contents/MacOS/" ),
112#else
113 wxT( "/usr/bin/" ),
114 wxT( "/usr/local/bin/" ),
115 wxT( "/usr/local/kicad/bin/" ),
116#endif
117 };
118
119 // find binary file from possibilities list:
120 for( unsigned i=0; i<arrayDim(possibilities); ++i )
121 {
122#ifndef __WXMAC__
123 fullFileName = possibilities[i] + shortname;
124#else
125 // make relative paths absolute
126 fullFileName = Pgm().GetExecutablePath() + possibilities[i] + shortname;
127#endif
128
129 if( wxFileExists( fullFileName ) )
130 return fullFileName;
131 }
132
133 return shortname;
134
135#endif
136}
137
138
139int ExecuteFile( const wxString& aEditorName, const wxString& aFileName, wxProcess* aCallback,
140 bool aFileForKicad )
141{
142 wxString fullEditorName;
143 std::vector<wxString> params;
144
145#ifdef __UNIX__
146 wxString param;
147 bool inSingleQuotes = false;
148 bool inDoubleQuotes = false;
149
150 auto pushParam =
151 [&]()
152 {
153 if( !param.IsEmpty() )
154 {
155 params.push_back( param );
156 param.clear();
157 }
158 };
159
160 for( wxUniChar ch : aEditorName )
161 {
162 if( inSingleQuotes )
163 {
164 if( ch == '\'' )
165 {
166 pushParam();
167 inSingleQuotes = false;
168 continue;
169 }
170 else
171 {
172 param += ch;
173 }
174 }
175 else if( inDoubleQuotes )
176 {
177 if( ch == '"' )
178 {
179 pushParam();
180 inDoubleQuotes = false;
181 }
182 else
183 {
184 param += ch;
185 }
186 }
187 else if( ch == '\'' )
188 {
189 pushParam();
190 inSingleQuotes = true;
191 }
192 else if( ch == '"' )
193 {
194 pushParam();
195 inDoubleQuotes = true;
196 }
197 else if( ch == ' ' )
198 {
199 pushParam();
200 }
201 else
202 {
203 param += ch;
204 }
205 }
206
207 pushParam();
208
209 if( aFileForKicad )
210 fullEditorName = FindKicadFile( params[0] );
211 else
212 fullEditorName = params[0];
213
214 params.erase( params.begin() );
215#else
216
217 if( aFileForKicad )
218 fullEditorName = FindKicadFile( aEditorName );
219 else
220 fullEditorName = aEditorName;
221#endif
222
223 if( wxFileExists( fullEditorName ) )
224 {
225 std::vector<const wchar_t*> args;
226
227 args.emplace_back( fullEditorName.wc_str() );
228
229 if( !params.empty() )
230 {
231 for( const wxString& p : params )
232 args.emplace_back( p.wc_str() );
233 }
234
235 if( !aFileName.IsEmpty() )
236 args.emplace_back( aFileName.wc_str() );
237
238 args.emplace_back( nullptr );
239
240 return wxExecute( const_cast<wchar_t**>( args.data() ), wxEXEC_ASYNC, aCallback );
241 }
242
243 wxString msg;
244 msg.Printf( _( "Command '%s' could not be found." ), fullEditorName );
245 DisplayError( nullptr, msg, 20 );
246 return -1;
247}
248
249
250bool OpenPDF( const wxString& file )
251{
252 wxString msg;
253 wxString filename = file;
254
256
257 if( Pgm().UseSystemPdfBrowser() )
258 {
259 if( !LaunchExternal( filename ) )
260 {
261 msg.Printf( _( "Unable to find a PDF viewer for '%s'." ), filename );
262 DisplayError( nullptr, msg );
263 return false;
264 }
265 }
266 else
267 {
268 const wchar_t* args[3];
269
270 args[0] = Pgm().GetPdfBrowserName().wc_str();
271 args[1] = filename.wc_str();
272 args[2] = nullptr;
273
274 if( wxExecute( const_cast<wchar_t**>( args ) ) == -1 )
275 {
276 msg.Printf( _( "Problem while running the PDF viewer '%s'." ), args[0] );
277 DisplayError( nullptr, msg );
278 return false;
279 }
280 }
281
282 return true;
283}
284
285
286void OpenFile( const wxString& file )
287{
288 wxFileName fileName( file );
289 wxFileType* filetype = wxTheMimeTypesManager->GetFileTypeFromExtension( fileName.GetExt() );
290
291 if( !filetype )
292 return;
293
294 wxString command;
295 wxFileType::MessageParameters params( file );
296
297 filetype->GetOpenCommand( &command, params );
298 delete filetype;
299
300 if( !command.IsEmpty() )
301 wxExecute( command );
302}
303
304
305void KiCopyFile( const wxString& aSrcPath, const wxString& aDestPath, wxString& aErrors )
306{
307 if( !wxCopyFile( aSrcPath, aDestPath ) )
308 {
309 wxString msg;
310
311 if( !aErrors.IsEmpty() )
312 aErrors += "\n";
313
314 msg.Printf( _( "Cannot copy file '%s'." ), aDestPath );
315 aErrors += msg;
316 }
317}
318
319
320wxString QuoteFullPath( wxFileName& fn, wxPathFormat format )
321{
322 return wxT( "\"" ) + fn.GetFullPath( format ) + wxT( "\"" );
323}
324
325
326bool RmDirRecursive( const wxString& aFileName, wxString* aErrors )
327{
328 namespace fs = std::filesystem;
329
330 std::string rmDir = aFileName.ToStdString();
331
332 if( rmDir.length() < 3 )
333 {
334 if( aErrors )
335 *aErrors = _( "Invalid directory name, cannot remove root" );
336
337 return false;
338 }
339
340 if( !fs::exists( rmDir ) )
341 {
342 if( aErrors )
343 *aErrors = wxString::Format( _( "Directory '%s' does not exist" ), aFileName );
344
345 return false;
346 }
347
348 fs::path path( rmDir );
349
350 if( !fs::is_directory( path ) )
351 {
352 if( aErrors )
353 *aErrors = wxString::Format( _( "'%s' is not a directory" ), aFileName );
354
355 return false;
356 }
357
358 try
359 {
360 fs::remove_all( path );
361 }
362 catch( const fs::filesystem_error& e )
363 {
364 if( aErrors )
365 *aErrors = wxString::Format( _( "Error removing directory '%s': %s" ), aFileName, e.what() );
366
367 return false;
368 }
369
370 return true;
371}
constexpr std::size_t arrayDim(T const (&)[N]) noexcept
Returns # of elements in an array.
Definition: arraydim.h:31
virtual const wxString & GetKicadEnvVariable() const
Definition: pgm_base.h:181
virtual void ReadPdfBrowserInfos()
Read the PDF browser choice from the common configuration.
Definition: pgm_base.cpp:1044
virtual const wxString & GetPdfBrowserName() const
Definition: pgm_base.h:187
virtual const wxString & GetExecutablePath() const
Definition: pgm_base.cpp:1038
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:161
This file is part of the common library.
#define _(s)
wxString FindKicadFile(const wxString &shortname)
Search the executable file shortname in KiCad binary path and return full file name if found or short...
Definition: gestfich.cpp:54
wxString QuoteFullPath(wxFileName &fn, wxPathFormat format)
Quote return value of wxFileName::GetFullPath().
Definition: gestfich.cpp:320
bool OpenPDF(const wxString &file)
Run the PDF viewer and display a PDF file.
Definition: gestfich.cpp:250
void KiCopyFile(const wxString &aSrcPath, const wxString &aDestPath, wxString &aErrors)
Definition: gestfich.cpp:305
int ExecuteFile(const wxString &aEditorName, const wxString &aFileName, wxProcess *aCallback, bool aFileForKicad)
Call the executable file aEditorName with the parameter aFileName.
Definition: gestfich.cpp:139
bool RmDirRecursive(const wxString &aFileName, wxString *aErrors)
Removes the directory aDirName and all its contents including subdirectories and their files.
Definition: gestfich.cpp:326
void OpenFile(const wxString &file)
Definition: gestfich.cpp:286
void QuoteString(wxString &string)
Add un " to the start and the end of string (if not already done).
Definition: gestfich.cpp:44
bool LaunchExternal(const wxString &aPath)
Launches the given file or folder in the host OS.
Definition: launch_ext.cpp:25
PGM_BASE & Pgm()
The global Program "get" accessor.
Definition: pgm_base.cpp:1059
see class PGM_BASE