void PGM_BASE::SetLanguagePath() { SEARCH_STACK guesses; SystemDirsAppend( &guesses ); // Add our internat dir to the wxLocale catalog of paths for( unsigned i = 0; i < guesses.GetCount(); i++ ) { wxFileName fn( guesses[i], wxEmptyString ); // Append path for Windows and unix KiCad package install fn.AppendDir( wxT( "share" ) ); fn.AppendDir( wxT( "internat" ) ); if( fn.IsDirReadable() ) { wxLogDebug( wxT( "Adding locale lookup path: " ) + fn.GetPath() ); wxLocale::AddCatalogLookupPathPrefix( fn.GetPath() ); } // Append path for unix standard install fn.RemoveLastDir(); fn.AppendDir( wxT( "kicad" ) ); fn.AppendDir( wxT( "internat" ) ); if( fn.IsDirReadable() ) { wxLogDebug( wxT( "Adding locale lookup path: " ) + fn.GetPath() ); wxLocale::AddCatalogLookupPathPrefix( fn.GetPath() ); } } }
DIALOG_EESCHEMA_CONFIG::DIALOG_EESCHEMA_CONFIG( wxWindow* aParent, wxString* aCallersProjectSpecificLibPaths, wxArrayString* aCallersLibNames ) : DIALOG_EESCHEMA_CONFIG_FBP( aParent ), m_callers_project_specific_lib_paths( aCallersProjectSpecificLibPaths ), m_callers_lib_names( aCallersLibNames ), m_lib_list_changed( false ), m_lib_path_changed( false ) { m_ListLibr->InsertItems( *aCallersLibNames, 0 ); // Load user libs paths: wxArrayString paths; SEARCH_STACK::Split( &paths, *aCallersProjectSpecificLibPaths ); for( unsigned i=0; i<paths.GetCount(); ++i ) { wxString path = paths[i]; if( wxFileName::DirExists( Prj().AbsolutePath( path ) ) ) m_listUserPaths->Append( path ); } // Display actual library paths which come in part from KIFACE::KifaceSearch() // along with aCallersProjectSpecificLibPaths at the front. SEARCH_STACK* libpaths = Prj().SchSearchS(); DBG( libpaths->Show( __func__ ); ) for( unsigned ii = 0; ii < libpaths->GetCount(); ii++ )
SEARCH_STACK* PROJECT::SchSearchS() { SEARCH_STACK* ss = (SEARCH_STACK*) GetElem( PROJECT::ELEM_SCH_SEARCH_STACK ); wxASSERT( !ss || dynamic_cast<SEARCH_STACK*>( GetElem( PROJECT::ELEM_SCH_SEARCH_STACK ) ) ); if( !ss ) { ss = new SEARCH_STACK(); // Make PROJECT the new SEARCH_STACK owner. SetElem( PROJECT::ELEM_SCH_SEARCH_STACK, ss ); // to the empty SEARCH_STACK for SchSearchS(), add project dir as first ss->AddPaths( m_project_name.GetPath() ); // next add the paths found in *.pro, variable "LibDir" wxString libDir; try { PART_LIBS::LibNamesAndPaths( this, false, &libDir ); } catch( const IO_ERROR& DBG( ioe ) ) { DBG(printf( "%s: %s\n", __func__, TO_UTF8( ioe.What() ) );) } if( !!libDir ) { wxArrayString paths; SEARCH_STACK::Split( &paths, libDir ); for( unsigned i =0; i<paths.GetCount(); ++i ) { wxString path = AbsolutePath( paths[i] ); ss->AddPaths( path ); // at the end } } // append all paths from aSList add_search_paths( ss, Kiface().KifaceSearch(), -1 ); // addLibrarySearchPaths( SEARCH_STACK* aSP, wxConfigBase* aCfg ) // This is undocumented, but somebody wanted to store !schematic! // library search paths in the .kicad_common file? add_search_paths( ss, Pgm().CommonSettings(), -1 ); }
/** * Function FindFileInSearchPaths * looks in "this" for \a aFilename, but first modifies every search * path by appending a list of path fragments from aSubdirs. That modification * is not relative. */ wxString FindFileInSearchPaths( const SEARCH_STACK& aStack, const wxString& aFilename, const wxArrayString* aSubdirs ) { wxPathList paths; for( unsigned i = 0; i < aStack.GetCount(); ++i ) { wxFileName fn( aStack[i], wxEmptyString ); if( aSubdirs ) { for( unsigned j = 0; j < aSubdirs->GetCount(); j++ ) fn.AppendDir( (*aSubdirs)[j] ); } wxLogDebug( wxT( " %s" ), GetChars( fn.GetFullPath() ) ); if( fn.DirExists() ) { paths.Add( fn.GetPath() ); } } return paths.FindValidPath( aFilename ); }
/** * Function missingLegacyLibs * tests the list of \a aLibNames by URI to determine if any of them are missing from * the #FP_LIB_TABLE. * * @note The missing legacy footprint library test is performed by using old library * file path lookup method. If the library is found, it is compared against all * of the URIs in the table rather than the nickname. This was done because the * user could change the nicknames from the default table. Using the full path * is more reliable. * * @param aLibNames is the list of legacy library names. * @param aErrorMsg is a pointer to a wxString object to store the URIs of any missing * legacy library paths. Can be NULL. * @return true if there are missing legacy libraries. Otherwise false. */ static bool missingLegacyLibs( FP_LIB_TABLE* aTbl, SEARCH_STACK& aSStack, const wxArrayString& aLibNames, wxString* aErrorMsg ) { bool missing = false; for( unsigned i = 0; i < aLibNames.GetCount(); i++ ) { wxFileName fn( wxEmptyString, aLibNames[i], LegacyFootprintLibPathExtension ); wxString legacyLibPath = aSStack.FindValidPath( fn.GetFullPath() ); /* if( legacyLibPath.IsEmpty() ) continue; */ if( !aTbl->FindRowByURI( legacyLibPath ) ) { missing = true; if( aErrorMsg ) { *aErrorMsg += wxChar( '"' ); if( !legacyLibPath ) *aErrorMsg += !legacyLibPath ? aLibNames[i] : legacyLibPath; *aErrorMsg += wxT( "\"\n" ); } } } return missing; }
void DIALOG_EDIT_COMPONENT_IN_LIBRARY::BrowseAndSelectDocFile( wxCommandEvent& event ) { PROJECT& prj = Prj(); SEARCH_STACK* search = prj.SchSearchS(); wxString mask = wxT( "*" ); wxString docpath = prj.GetRString( PROJECT::DOC_PATH ); if( !docpath ) docpath = search->LastVisitedPath( wxT( "doc" ) ); wxString fullFileName = EDA_FILE_SELECTOR( _( "Doc Files" ), docpath, wxEmptyString, wxEmptyString, mask, this, wxFD_OPEN, true ); if( fullFileName.IsEmpty() ) return; /* If the path is already in the library search paths * list, just add the library name to the list. Otherwise, add * the library name with the full or relative path. * the relative path, when possible is preferable, * because it preserve use of default libraries paths, when the path is a sub path of * these default paths */ wxFileName fn = fullFileName; prj.SetRString( PROJECT::DOC_PATH, fn.GetPath() ); wxString filename = search->FilenameWithRelativePathInSearchList( fullFileName, wxPathOnly( Prj().GetProjectFullName() ) ); // Filenames are always stored in unix like mode, ie separator "\" is stored as "/" // to ensure files are identical under unices and windows #ifdef __WINDOWS__ filename.Replace( wxT( "\\" ), wxT( "/" ) ); #endif m_DocfileCtrl->SetValue( filename ); }
static bool copy_pro_file_template( const SEARCH_STACK& aSearchS, const wxString& aDestination ) { if( aDestination.IsEmpty() ) { wxLogTrace( tracePathsAndFiles, "%s: destination is empty.", __func__ ); return false; } wxString templateFile = wxT( "kicad." ) + ProjectFileExtension; wxString kicad_pro_template = aSearchS.FindValidPath( templateFile ); if( !kicad_pro_template ) { wxLogTrace( tracePathsAndFiles, "%s: template file '%s' not found using search paths.", __func__, TO_UTF8( templateFile ) ); wxFileName templ( wxStandardPaths::Get().GetDocumentsDir(), wxT( "kicad" ), ProjectFileExtension ); if( !templ.IsFileReadable() ) { wxString msg = wxString::Format( _( "Unable to find \"%s\" template config file." ), GetChars( templateFile ) ); DisplayErrorMessage( nullptr, _( "Error copying project file template" ), msg ); return false; } kicad_pro_template = templ.GetFullPath(); } wxLogTrace( tracePathsAndFiles, "%s: using template file '%s' as project file.", __func__, TO_UTF8( kicad_pro_template ) ); // Verify aDestination can be created. if this is not the case, wxCopyFile // will generate a crappy log error message, and we *do not want* this kind // of stupid message wxFileName fn( aDestination ); bool success = true; if( fn.IsOk() && fn.IsDirWritable() ) success = wxCopyFile( kicad_pro_template, aDestination ); else { wxLogMessage( _( "Cannot create prj file \"%s\" (Directory not writable)" ), GetChars( aDestination) ); success = false; } return success; }
wxString RETAINED_PATH::LastVisitedPath( const SEARCH_STACK& aSStack, const wxString& aSubPathToSearch ) { if( !!m_retained_path ) return m_retained_path; wxString path; // Initialize default path to the main default lib path // this is the second path in list (the first is the project path) unsigned pcount = aSStack.GetCount(); if( pcount ) { unsigned ipath = 0; if( aSStack[0] == wxGetCwd() ) ipath = 1; // First choice of path: if( ipath < pcount ) path = aSStack[ipath]; // Search a sub path matching aSubPathToSearch if( !aSubPathToSearch.IsEmpty() ) { for( ; ipath < pcount; ipath++ ) { if( aSStack[ipath].Contains( aSubPathToSearch ) ) { path = aSStack[ipath]; break; } } } } if( path.IsEmpty() ) path = wxGetCwd(); return path; }
bool PGM_KICAD::OnPgmInit( wxApp* aWxApp ) { m_wx_app = aWxApp; // first thing. wxString absoluteArgv0 = wxStandardPaths::Get().GetExecutablePath(); if( !wxIsAbsolutePath( absoluteArgv0 ) ) { wxLogError( wxT( "No meaningful argv[0]" ) ); return false; } // Set LIB_ENV_VAR *before* loading the KIFACE DSOs, in case they have hard // dependencies on subsidiary DSOs below it. set_lib_env_var( absoluteArgv0 ); if( !initPgm() ) return false; m_bm.Init(); // Add search paths to feed the PGM_KICAD::SysSearch() function, // currenly limited in support to only look for project templates { SEARCH_STACK bases; SystemDirsAppend( &bases ); // DBG( bases.Show( (std::string(__func__) + " bases").c_str() );) for( unsigned i = 0; i < bases.GetCount(); ++i ) { wxFileName fn( bases[i], wxEmptyString ); // Add KiCad template file path to search path list. fn.AppendDir( wxT( "template" ) ); m_bm.m_search.AddPaths( fn.GetPath() ); } //DBG( m_bm.m_search.Show( (std::string( __func__ ) + " SysSearch()").c_str() );) } // Must be called before creating the main frame in order to // display the real hotkeys in menus or tool tips extern struct EDA_HOTKEY_CONFIG kicad_Manager_Hokeys_Descr[]; ReadHotkeyConfig( KICAD_MANAGER_FRAME_NAME, kicad_Manager_Hokeys_Descr ); KICAD_MANAGER_FRAME* frame = new KICAD_MANAGER_FRAME( NULL, wxT( "KiCad" ), wxDefaultPosition, wxDefaultSize ); App().SetTopWindow( frame ); Kiway.SetTop( frame ); bool prjloaded = false; // true when the project is loaded if( App().argc > 1 ) frame->SetProjectFileName( App().argv[1] ); else if( GetFileHistory().GetCount() ) { wxString last_pro = GetFileHistory().GetHistoryFile( 0 ); if( !wxFileExists( last_pro ) ) { GetFileHistory().RemoveFileFromHistory( 0 ); wxFileName namelessProject( wxStandardPaths::Get().GetDocumentsDir(), NAMELESS_PROJECT, ProjectFileExtension ); frame->SetProjectFileName( namelessProject.GetFullPath() ); } else { // Try to open the last opened project, // if a project name is not given when starting Kicad frame->SetProjectFileName( last_pro ); wxCommandEvent cmd( 0, wxID_FILE1 ); frame->OnFileHistory( cmd ); prjloaded = true; // OnFileHistory() loads the project } } else // there is no history { wxFileName namelessProject( wxStandardPaths::Get().GetDocumentsDir(), NAMELESS_PROJECT, ProjectFileExtension ); frame->SetProjectFileName( namelessProject.GetFullPath() ); } if( !prjloaded ) { wxCommandEvent cmd( 0, wxID_ANY ); frame->OnLoadProject( cmd ); } frame->Show( true ); frame->Raise(); return true; }
// non-member so it can be moved easily, and kept REALLY private. // Do NOT Clear() in here. static void add_search_paths( SEARCH_STACK* aDst, const SEARCH_STACK& aSrc, int aIndex ) { for( unsigned i=0; i<aSrc.GetCount(); ++i ) aDst->AddPaths( aSrc[i], aIndex ); }
bool LIB_EDIT_FRAME::SaveActiveLibrary( bool newFile ) { wxFileName fn; wxString msg; m_canvas->EndMouseCapture( ID_NO_TOOL_SELECTED, m_canvas->GetDefaultCursor() ); PART_LIB* lib = GetCurLib(); // Just in case the library hasn't been cached yet. lib->GetCount(); if( !lib ) { DisplayError( this, _( "No library specified." ) ); return false; } wxString oldFileName = lib->GetFullFileName(); if( GetScreen()->IsModify() ) { if( IsOK( this, _( "Include last component changes?" ) ) ) { lib->EnableBuffering(); try { SaveOnePart( lib, false ); } catch( ... ) { lib->EnableBuffering( false ); msg.Printf( _( "Unexpected error occured saving part to '%s' symbol library." ), lib->GetName() ); DisplayError( this, msg ); return false; } lib->EnableBuffering( false ); } } if( newFile ) { PROJECT& prj = Prj(); SEARCH_STACK* search = prj.SchSearchS(); // Get a new name for the library wxString default_path = prj.GetRString( PROJECT::SCH_LIB_PATH ); if( !default_path ) default_path = search->LastVisitedPath(); wxFileDialog dlg( this, _( "Part Library Name:" ), default_path, wxEmptyString, SchematicLibraryFileWildcard, wxFD_SAVE | wxFD_OVERWRITE_PROMPT ); if( dlg.ShowModal() == wxID_CANCEL ) return false; fn = dlg.GetPath(); // The GTK file chooser doesn't return the file extension added to // file name so add it here. if( fn.GetExt().IsEmpty() ) fn.SetExt( SchematicLibraryFileExtension ); prj.SetRString( PROJECT::SCH_LIB_PATH, fn.GetPath() ); } else { fn = wxFileName( lib->GetFullFileName() ); msg.Printf( _( "Modify library file '%s' ?" ), GetChars( fn.GetFullPath() ) ); if( !IsOK( this, msg ) ) return false; } // Verify the user has write privileges before attempting to save the library file. if( !IsWritable( fn ) ) return false; ClearMsgPanel(); wxFileName libFileName = fn; wxFileName backupFileName = fn; // Rename the old .lib file to .bak. if( libFileName.FileExists() ) { backupFileName.SetExt( "bak" ); if( backupFileName.FileExists() ) wxRemoveFile( backupFileName.GetFullPath() ); if( !wxRenameFile( libFileName.GetFullPath(), backupFileName.GetFullPath() ) ) { libFileName.MakeAbsolute(); msg = _( "Failed to rename old component library file " ) + backupFileName.GetFullPath(); DisplayError( this, msg ); } } wxFileName docFileName = libFileName; docFileName.SetExt( DOC_EXT ); // Rename .doc file to .bck. if( docFileName.FileExists() ) { backupFileName.SetExt( "bck" ); if( backupFileName.FileExists() ) wxRemoveFile( backupFileName.GetFullPath() ); if( !wxRenameFile( docFileName.GetFullPath(), backupFileName.GetFullPath() ) ) { msg = _( "Failed to save old library document file " ) + backupFileName.GetFullPath(); DisplayError( this, msg ); } } try { lib->SetFileName( fn.GetFullPath() ); lib->Save(); } catch( ... /* IO_ERROR ioe */ ) { lib->SetFileName( oldFileName ); msg.Printf( _( "Failed to create symbol library file '%s'" ), GetChars( docFileName.GetFullPath() ) ); DisplayError( this, msg ); return false; } lib->SetFileName( oldFileName ); msg.Printf( _( "Library file '%s' saved" ), GetChars( fn.GetFullPath() ) ); fn.SetExt( DOC_EXT ); wxString msg1; msg1.Printf( _( "Documentation file '%s' saved" ), GetChars( fn.GetFullPath() ) ); AppendMsgPanel( msg, msg1, BLUE ); UpdateAliasSelectList(); UpdatePartSelectList(); refreshSchematic(); return true; }
void LIB_EDIT_FRAME::LoadOneSymbol() { LIB_PART* part = GetCurPart(); // Exit if no library entry is selected or a command is in progress. if( !part || ( m_drawItem && m_drawItem->GetFlags() ) ) return; PROJECT& prj = Prj(); SEARCH_STACK* search = prj.SchSearchS(); m_canvas->SetIgnoreMouseEvents( true ); wxString default_path = prj.GetRString( PROJECT::SCH_LIB_PATH ); if( !default_path ) default_path = search->LastVisitedPath(); wxFileDialog dlg( this, _( "Import Symbol Drawings" ), default_path, wxEmptyString, SchematicSymbolFileWildcard, wxFD_OPEN | wxFD_FILE_MUST_EXIST ); if( dlg.ShowModal() == wxID_CANCEL ) return; SetCrossHairPosition( wxPoint( 0, 0 ) ); m_canvas->MoveCursorToCrossHair(); m_canvas->SetIgnoreMouseEvents( false ); wxString filename = dlg.GetPath(); prj.SetRString( PROJECT::SCH_LIB_PATH, filename ); std::unique_ptr<PART_LIB> lib( new PART_LIB( LIBRARY_TYPE_SYMBOL, filename ) ); wxString err; if( !lib->Load( err ) ) { wxString msg = wxString::Format( _( "Error '%s' occurred loading part file '%s'." ), GetChars( err ), GetChars( filename ) ); DisplayError( this, msg ); return; } if( lib->IsEmpty() ) { wxString msg = wxString::Format( _( "No parts found in part file '%s'." ), GetChars( filename ) ); DisplayError( this, msg ); return; } if( lib->GetCount() > 1 ) { wxString msg = wxString::Format( _( "More than one part in part file '%s'." ), GetChars( filename ) ); wxMessageBox( msg, _( "Warning" ), wxOK | wxICON_EXCLAMATION, this ); } LIB_PART* first = lib->GetFirstEntry()->GetPart(); LIB_ITEMS& drawList = first->GetDrawItemList(); for( LIB_ITEM& item : drawList ) { if( item.Type() == LIB_FIELD_T ) continue; if( item.GetUnit() ) item.SetUnit( m_unit ); if( item.GetConvert() ) item.SetConvert( m_convert ); item.SetFlags( IS_NEW | SELECTED ); LIB_ITEM* newItem = (LIB_ITEM*) item.Clone(); newItem->SetParent( part ); part->AddDrawItem( newItem ); } part->RemoveDuplicateDrawItems(); part->ClearSelectedItems(); OnModify(); m_canvas->Refresh(); }
void LIB_EDIT_FRAME::SaveOneSymbol() { wxString msg; PROJECT& prj = Prj(); SEARCH_STACK* search = prj.SchSearchS(); LIB_PART* part = GetCurPart(); if( !part || part->GetDrawItemList().empty() ) return; wxString default_path = prj.GetRString( PROJECT::SCH_LIB_PATH ); if( !default_path ) default_path = search->LastVisitedPath(); wxFileDialog dlg( this, _( "Export Symbol Drawings" ), default_path, part->GetName(), SchematicSymbolFileWildcard, wxFD_SAVE | wxFD_OVERWRITE_PROMPT ); if( dlg.ShowModal() == wxID_CANCEL ) return; wxFileName fn = dlg.GetPath(); /* The GTK file chooser doesn't return the file extension added to * file name so add it here. */ if( fn.GetExt().IsEmpty() ) fn.SetExt( SchematicSymbolFileExtension ); prj.SetRString( PROJECT::SCH_LIB_PATH, fn.GetPath() ); msg.Printf( _( "Saving symbol in '%s'" ), GetChars( fn.GetPath() ) ); SetStatusText( msg ); wxString line; // File header line << wxT( LIBFILE_IDENT ) << wxT( " " ) << LIB_VERSION_MAJOR << wxT( "." ) << LIB_VERSION_MINOR << wxT( " SYMBOL " ) << wxT( "Date: " ) << DateAndTime() << wxT( "\n" ); // Component name comment and definition. line << wxT( "# SYMBOL " ) << part->GetName() << wxT( "\n#\nDEF " ) << part->GetName() << wxT( " " ); if( !part->GetReferenceField().GetText().IsEmpty() ) line << part->GetReferenceField().GetText() << wxT( " " ); else line << wxT( "~ " ); line << 0 << wxT( " " ) << part->GetPinNameOffset() << wxT( " " ); if( part->ShowPinNumbers() ) line << wxT( "Y " ); else line << wxT( "N " ); if( part->ShowPinNames() ) line << wxT( "Y " ); else line << wxT( "N " ); line << wxT( "1 0 N\n" ); try { FILE_OUTPUTFORMATTER formatter( fn.GetFullPath() ); try { formatter.Print( 0, "%s", TO_UTF8( line ) ); part->GetReferenceField().Save( formatter ); part->GetValueField().Save( formatter ); formatter.Print( 0, "DRAW\n" ); LIB_ITEMS& drawList = part->GetDrawItemList(); for( LIB_ITEM& item : drawList ) { if( item.Type() == LIB_FIELD_T ) continue; // Don't save unused parts or alternate body styles. if( m_unit && item.GetUnit() && ( item.GetUnit() != m_unit ) ) continue; if( m_convert && item.GetConvert() && ( item.GetConvert() != m_convert ) ) continue; item.Save( formatter ); } formatter.Print( 0, "ENDDRAW\n" ); formatter.Print( 0, "ENDDEF\n" ); } catch( const IO_ERROR& ioe ) { msg.Printf( _( "An error occurred attempting to save symbol file '%s'" ), GetChars( fn.GetFullPath() ) ); DisplayError( this, msg ); } } catch( const IO_ERROR& ioe ) { DisplayError( this, ioe.errorText ); return; } }
// See also FindKicadHelpPath.cpp.notused. wxString SearchHelpFileFullPath( const SEARCH_STACK& aSStack, const wxString& aBaseName ) { wxArrayString subdirs; wxArrayString altsubdirs; SEARCH_STACK ss = aSStack; // It might already be in aSStack, but why depend on other code // far away when it's so easy to add it again (to our copy) as the first place to look. // This is CMAKE_INSTALL_PREFIX unless DEFAULT_INSTALL_PATH was defined during // build configuration: ss.AddPaths( wxT( DEFAULT_INSTALL_PATH ), 0 ); #if defined(__WXMAC__) ss.AddPaths( GetOSXKicadMachineDataDir() ); ss.AddPaths( Pgm().GetExecutablePath(), 0 ); // OS X packages can have the help files in // /Library/Application\ Support/kicad/help, // and in Contents/SharedSupport/help inside the // bundle. // Below we account for an international subdirectory. subdirs.Add( wxT( "help" ) ); altsubdirs.Add( wxT( "Contents" ) ); altsubdirs.Add( wxT( "SharedSupport" ) ); altsubdirs.Add( wxT( "help" ) ); #endif #if ! defined(__WXMAC__) // && defined(__linux__) // This is the executable path minus the trailing bin directory used on Windows and Linux. wxFileName tmp( Pgm().GetExecutablePath(), wxEmptyString ); wxArrayString binDirs = tmp.GetDirs(); if( !binDirs.IsEmpty() && binDirs[ binDirs.GetCount() - 1 ].CmpNoCase( wxT( "bin" ) ) == 0 ) tmp.RemoveLastDir(); ss.AddPaths( tmp.GetPath(), 0 ); // Based on kicad-doc.bzr/CMakeLists.txt, line 20, the help files are // installed into "<CMAKE_INSTALL_PREFIX>/share/doc/kicad/help" for linux. // This is ${KICAD_HELP} var in that CMakeLists.txt file. // Below we account for an international subdirectory. subdirs.Add( wxT( "share" ) ); subdirs.Add( wxT( "doc" ) ); subdirs.Add( wxT( "kicad" ) ); subdirs.Add( wxT( "help" ) ); // Based on kicad-doc.bzr/CMakeLists.txt, line 35, the help files are // installed into "<CMAKE_INSTALL_PREFIX>/doc/help" for Windows. // This is ${KICAD_HELP} var in that CMakeLists.txt file. // Below we account for an international subdirectory. altsubdirs.Add( wxT( "doc" ) ); altsubdirs.Add( wxT( "help" ) ); #endif // If there's a KICAD environment variable set, always use that guy's path first. if( !Pgm().GetKicadEnvVariable().IsEmpty() ) ss.AddPaths( Pgm().GetKicadEnvVariable(), 0 ); /* Search for a help file. * we *must* find a help file. * so help is searched in directories in this order: * help/<canonical name> like help/en_GB * help/<short name> like help/en * help/en */ wxLocale* i18n = Pgm().GetLocale(); // We try to find help file in help/<canonical name> // If fails, try to find help file in help/<short canonical name> // If fails, try to find help file in help/en wxArrayString locale_name_dirs; locale_name_dirs.Add( i18n->GetCanonicalName() ); // canonical name like fr_FR // wxLocale::GetName() does not return always the short name locale_name_dirs.Add( i18n->GetName().BeforeLast( '_' ) ); // short canonical name like fr locale_name_dirs.Add( wxT( "en" ) ); // default (en) #if defined(DEBUG) && 1 ss.Show( wxString( __func__ ) ); wxLogDebug( wxT( "%s: m_help_file:'%s'" ), __func__, GetChars( aBaseName ) ); #endif wxLogDebug( wxT( "Checking SEARCH_STACK for file %s" ), GetChars( aBaseName ) ); // Help files can be html (.html ext) or pdf (.pdf ext) files. // Therefore, <BaseName>.html file is searched and if not found, // <BaseName>.pdf file is searched in the same paths wxString fn; for( unsigned ii = 0; ii < locale_name_dirs.GetCount(); ii++ ) { subdirs.Add( locale_name_dirs[ii] ); altsubdirs.Add( locale_name_dirs[ii] ); fn = FindFileInSearchPaths( ss, aBaseName + wxT( ".html" ), &altsubdirs ); if( !fn.IsEmpty() ) break; fn = FindFileInSearchPaths( ss, aBaseName + wxT( ".pdf" ), &altsubdirs ); if( !fn.IsEmpty() ) break; fn = FindFileInSearchPaths( ss, aBaseName + wxT( ".html" ), &subdirs ); if( !fn.IsEmpty() ) break; fn = FindFileInSearchPaths( ss, aBaseName + wxT( ".pdf" ), &subdirs ); if( !fn.IsEmpty() ) break; subdirs.RemoveAt( subdirs.GetCount() - 1 ); altsubdirs.RemoveAt( altsubdirs.GetCount() - 1 ); } return fn; }
void SystemDirsAppend( SEARCH_STACK* aSearchStack ) { // No clearing is done here, the most general approach is NOT to assume that // our appends will be the only thing in the stack. This function has no // knowledge of caller's intentions. // wxPathList::AddEnvList() is broken, use SEARCH_STACK::AddPaths(). // SEARCH_STACK::AddPaths() will verify readability and existence of // each directory before adding. SEARCH_STACK maybe; // User environment variable path is the first search path. Chances are // if the user is savvy enough to set an environment variable they know // what they are doing. It should take precedence over anything else. // Otherwise don't set it. maybe.AddPaths( wxGetenv( wxT( "KICAD" ) ) ); #ifdef __WXMAC__ // Add the directory for the user-dependent, program specific data files. maybe.AddPaths( GetOSXKicadUserDataDir() ); // Global machine specific application data maybe.AddPaths( GetOSXKicadMachineDataDir() ); // Global application specific data files inside bundle maybe.AddPaths( GetOSXKicadDataDir() ); #else // This is from CMAKE_INSTALL_PREFIX. // Useful when KiCad is installed by `make install`. // Use as second ranked place. maybe.AddPaths( wxT( DEFAULT_INSTALL_PATH ) ); // Add the directory for the user-dependent, program specific data files. // According to wxWidgets documentation: // Unix: ~/.appname // Windows: C:\Documents and Settings\username\Application Data\appname maybe.AddPaths( wxStandardPaths::Get().GetUserDataDir() ); { // Should be full path to this program executable. wxString bin_dir = Pgm().GetExecutablePath(); #if defined(__MINGW32__) // bin_dir uses unix path separator. So to parse with wxFileName // use windows separator, especially important for server inclusion: // like: \\myserver\local_path . bin_dir.Replace( wxFileName::GetPathSeparator( wxPATH_UNIX ), wxFileName::GetPathSeparator( wxPATH_WIN ) ); #endif wxFileName bin_fn( bin_dir, wxEmptyString ); // Dir of the global (not user-specific), application specific, data files. // From wx docs: // Unix: prefix/share/appname // Windows: the directory where the executable file is located // Mac: appname.app/Contents/SharedSupport bundle subdirectory wxString data_dir = wxStandardPaths::Get().GetDataDir(); if( bin_fn.GetPath() != data_dir ) { // add data_dir if it is different from the bin_dir maybe.AddPaths( data_dir ); } // Up one level relative to binary path with "share" appended below. bin_fn.RemoveLastDir(); maybe.AddPaths( bin_fn.GetPath() ); } /* The normal OS program file install paths allow for a binary to be * installed in a different path from the library files. This is * useful for development purposes so the library and documentation * files do not need to be installed separately. If someone can * figure out a way to implement this without #ifdef, please do. */ #if defined(__MINGW32__) maybe.AddPaths( wxGetenv( wxT( "PROGRAMFILES" ) ) ); #else maybe.AddPaths( wxGetenv( wxT( "PATH" ) ) ); #endif #endif #if defined(DEBUG) && 0 maybe.Show( "maybe wish list" ); #endif // Append 1) kicad, 2) kicad/share, 3) share, and 4) share/kicad to each // possible base path in 'maybe'. Since SEARCH_STACK::AddPaths() will verify // readability and existence of each directory, not all of these will be // actually appended. for( unsigned i = 0; i < maybe.GetCount(); ++i ) { wxFileName fn( maybe[i], wxEmptyString ); #ifndef __WXMAC__ if( fn.GetPath().AfterLast( fn.GetPathSeparator() ) == wxT( "bin" ) ) { fn.RemoveLastDir(); if( !fn.GetDirCount() ) continue; // at least on linux } #endif aSearchStack->AddPaths( fn.GetPath() ); #ifndef __WXMAC__ fn.AppendDir( wxT( "kicad" ) ); aSearchStack->AddPaths( fn.GetPath() ); // add maybe[i]/kicad fn.AppendDir( wxT( "share" ) ); aSearchStack->AddPaths( fn.GetPath() ); // add maybe[i]/kicad/share fn.RemoveLastDir(); // ../ clear share fn.RemoveLastDir(); // ../ clear kicad fn.AppendDir( wxT( "share" ) ); aSearchStack->AddPaths( fn.GetPath() ); // add maybe[i]/share fn.AppendDir( wxT( "kicad" ) ); aSearchStack->AddPaths( fn.GetPath() ); // add maybe[i]/share/kicad #endif } #if defined(DEBUG) && 0 // final results: aSearchStack->Show( __func__ ); #endif }
/** * Function convertFromLegacy * converts the footprint names in \a aNetList from the legacy format to the #FPID format. * * @param aNetList is the #NETLIST object to convert. * @param aLibNames is the list of legacy footprint library names from the currently loaded * project. * @param aReporter is the #REPORTER object to dump messages into. * @return true if all footprint names were successfully converted to a valid FPID. */ static bool convertFromLegacy( FP_LIB_TABLE* aTbl, SEARCH_STACK& aSStack, NETLIST& aNetList, const wxArrayString& aLibNames, REPORTER* aReporter = NULL ) throw( IO_ERROR ) { wxString msg; FPID lastFPID; COMPONENT* component; MODULE* module = 0; bool retv = true; if( aNetList.IsEmpty() ) return true; aNetList.SortByFPID(); wxString libPath; PLUGIN::RELEASER pi( IO_MGR::PluginFind( IO_MGR::LEGACY ) ); for( unsigned ii = 0; ii < aNetList.GetCount(); ii++ ) { component = aNetList.GetComponent( ii ); // The footprint hasn't been assigned yet so ignore it. if( component->GetFPID().empty() ) continue; if( component->GetFPID() != lastFPID ) { module = NULL; for( unsigned ii = 0; ii < aLibNames.GetCount(); ii++ ) { wxFileName fn( wxEmptyString, aLibNames[ii], LegacyFootprintLibPathExtension ); libPath = aSStack.FindValidPath( fn.GetFullPath() ); if( !libPath ) { if( aReporter ) { msg.Printf( _( "Cannot find footprint library file '%s' in any of the " "KiCad legacy library search paths.\n" ), GetChars( fn.GetFullPath() ) ); aReporter->Report( msg ); } retv = false; continue; } module = pi->FootprintLoad( libPath, component->GetFPID().GetFootprintName() ); if( module ) { lastFPID = component->GetFPID(); break; } } } if( !module ) { if( aReporter ) { msg.Printf( _( "Component '%s' footprint '%s' was not found in any legacy " "library.\n" ), GetChars( component->GetReference() ), GetChars( component->GetFPID().Format() ) ); aReporter->Report( msg ); } // Clear the footprint assignment since the old library lookup method is no // longer valid. FPID emptyFPID; component->SetFPID( emptyFPID ); retv = false; continue; } else { wxString libNickname; const FP_LIB_TABLE::ROW* row; if( ( row = aTbl->FindRowByURI( libPath ) ) != NULL ) libNickname = row->GetNickName(); if( libNickname.IsEmpty() ) { if( aReporter ) { msg.Printf( _( "Component '%s' with footprint '%s' and legacy library path '%s' " "was not found in the footprint library table.\n" ), GetChars( component->GetReference() ), GetChars( component->GetFPID().Format() ), GetChars( libPath ) ); aReporter->Report( msg ); } retv = false; } else { FPID newFPID = lastFPID; newFPID.SetLibNickname( libNickname ); if( !newFPID.IsValid() ) { if( aReporter ) { msg.Printf( _( "Component '%s' FPID '%s' is not valid.\n" ), GetChars( component->GetReference() ), GetChars( newFPID.Format() ) ); aReporter->Report( msg ); } retv = false; } else { // The footprint name should already be set. component->SetFPID( newFPID ); } } } } return retv; }