kicad/pcbnew/dialogs/wizard_add_fplib.cpp

962 lines
31 KiB
C++

/**
* @file wizard_add_fplib.cpp
*/
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/** @brief this code creates a wizard to add entries in the footprint library table.
* The wizard contains 3 pages:
* The first is the selection of the type of libraries (plugin type):
* * Kicad .pretty library (actually a folder containing .kicad_mod footprint files)
* * Gihtub .pretty on line library, accessible via a internet connection
* * Legacy library (old .mod format file containing footprints desc)
* * Eagle xml V6 library (.lbr files)
* * Geda-PCB library (actually a folder containing .fp footprint files
* The second is the selection of path management:
* use environment variable or absolute path.
* When using an environment variable, selec it
* The third is the library list selection
* It allows entering entries by running a tool to select a set of libraries
* The tool depend on the type of lib (files/folder/urls):
* * multi files selector
* * multi folder selector
* * multi URL selector (via a web viewer)
* The path and the plugin type comes from the selection, and a library nickname
* is built from the path.
*/
#include <wx/wx.h>
#include <wx/url.h>
#include <wx/progdlg.h>
#include <pgm_base.h>
#include <kiface_i.h>
#include <dialog_helpers.h>
#include <project.h> // For PROJECT_VAR_NAME definition
#include <fp_lib_table.h> // For KISYSMOD definition
#include <io_mgr.h>
#include <wizard_add_fplib.h>
#include <dialog_select_dirlist_base.h>
// a key to store the default Kicad Github libs URL
#define KICAD_FPLIBS_URL_KEY wxT( "kicad_fplib_url" )
// key to store last options of th wizard
#define WIZARD_LAST_PLUGIN_KEY wxT( "wizard_plugin" )
#define WIZARD_LAST_PATHOPTION_KEY wxT( "wizard_path_option" )
// static members to store last choices during a session
int WIZARD_FPLIB_TABLE::m_last_plugin_choice = 0;
int WIZARD_FPLIB_TABLE::m_last_defaultpath_choice = 2;
WIZARD_FPLIB_TABLE::WIZARD_FPLIB_TABLE( wxWindow* aParent, wxArrayString& aEnvVariableList )
: WIZARD_FPLIB_TABLE_BASE( aParent )
{
initDlg( aEnvVariableList );
// Allows github plugin selection only when the plugin is compiled:
#ifndef BUILD_GITHUB_PLUGIN
m_rbFpLibFormat->Enable( GITHUB_PLUGIN, false );
if( m_rbFpLibFormat->GetSelection() == GITHUB_PLUGIN )
m_rbFpLibFormat->SetSelection( KICAD_PLUGIN );
#endif
// Currently, I (JPC) do not know the best way to add/store
// what is currently called env variables
// So do not show tools to change them,
// but do not remove the code, just in case
m_buttonAddEV->Show( false );
m_buttonRemoveEV->Show( false );
#ifndef BUILD_GITHUB_PLUGIN
m_buttonGithubLibList->Show( false );
#endif
// Gives a minimal size to the dialog, which allows displaying any page
wxSize minsize;
for( unsigned ii = 0; ii < m_pages.size(); ii++ )
{
wxSize size = m_pages[ii]->GetSizer()->CalcMin();
minsize.x = std::max( minsize.x, size.x );
minsize.y = std::max( minsize.y, size.y );
}
SetMinSize( minsize );
SetPageSize( minsize );
GetSizer()->SetSizeHints( this );
Center();
}
WIZARD_FPLIB_TABLE::~WIZARD_FPLIB_TABLE()
{
// Use this if you want to store kicad lib URL in pcbnew/cvpcb section config:
// wxConfigBase* cfg = Kiface().KifaceSettings();
// Use this if you want to store kicad lib URL in common section config:
wxConfigBase* cfg = Pgm().CommonSettings();
cfg->Write( KICAD_FPLIBS_URL_KEY, m_textCtrlGithubURL->GetValue() );
m_last_plugin_choice = m_rbFpLibFormat->GetSelection();
m_last_defaultpath_choice = m_rbPathManagement->GetSelection();
cfg->Write( WIZARD_LAST_PLUGIN_KEY, m_last_plugin_choice );
cfg->Write( WIZARD_LAST_PATHOPTION_KEY, m_last_defaultpath_choice );
}
void WIZARD_FPLIB_TABLE::initDlg( wxArrayString& aEnvVariableList )
{
m_currLibDescr = NULL;
SetBitmap( KiBitmap( wizard_add_fplib_icon_xpm ) );
wxString msg;
wxConfigBase* cfg = Pgm().CommonSettings();
cfg->Read( WIZARD_LAST_PLUGIN_KEY, &m_last_plugin_choice );
cfg->Read( WIZARD_LAST_PATHOPTION_KEY, &m_last_defaultpath_choice );
cfg->Read( KICAD_FPLIBS_URL_KEY, &msg );
if( msg.IsEmpty() ) // Give our current KiCad github URL
msg = wxT( "http://github.com/KiCad" );
// Be sure there is no trailing '/' at the end of the repo name
if( msg.EndsWith( wxT("/" ) ) )
msg.RemoveLast();
m_textCtrlGithubURL->SetValue( msg );
// KIGITHUB is frequently used (examples in docs, and other place)
// So add it if it not yet in list, but if it is defined as env var
// (note this env var is not hardcoded or existing in kicad sources)
if( aEnvVariableList.Index( wxT("KIGITHUB"), false ) == wxNOT_FOUND )
{
// Not yet in use in lib table, see in env. vars
wxString evValue;
wxGetEnv( wxT("KIGITHUB"), &evValue );
// Not yet in use in lib table, but it is defined in environment,
// so add it, just in case
if( ! evValue.IsEmpty() )
aEnvVariableList.Add( wxT("KIGITHUB") );
}
m_rowPrjEnvVarPosition = 0;
m_predefinedEnvVarCnt = aEnvVariableList.GetCount();
for( int row = 0; row < m_predefinedEnvVarCnt; row++ )
{
if( GetEnvVarCount() <= row )
m_gridEnvironmentVariablesList->AppendRows(1);
m_gridEnvironmentVariablesList->SetCellValue( row, 0, aEnvVariableList[row] );
if( aEnvVariableList[row] == PROJECT_VAR_NAME )
m_rowPrjEnvVarPosition = row;
wxString evValue;
if( wxGetEnv( aEnvVariableList[row], &evValue ) )
m_gridEnvironmentVariablesList->SetCellValue( row, 1, evValue );
// All these env var are defined outside the wizard,
// and cannot be modified in this dialog
m_gridEnvironmentVariablesList->SetReadOnly( row, 0, true );
m_gridEnvironmentVariablesList->SetReadOnly( row, 1, true );
}
m_gridEnvironmentVariablesList->Fit();
m_buttonRemoveEV->Enable( GetEnvVarCount() > m_predefinedEnvVarCnt );
m_gridEnvironmentVariablesList->AutoSizeColumns();
m_rbFpLibFormat->SetSelection( m_last_plugin_choice );
m_rbPathManagement->SetSelection( m_last_defaultpath_choice );
wxCommandEvent event;
updateFromPlugingChoice();
OnPathManagementSelection( event );
}
int WIZARD_FPLIB_TABLE::HasGithubEnvVarCompatible()
{
// Return true if at least one env var defines a url relative to github
for( int row = 0; row < GetEnvVarCount(); row++ )
{
if( m_gridEnvironmentVariablesList->GetCellValue(
wxGridCellCoords( row, 1 ) ).Lower().StartsWith( "http" ) )
return row;
}
return -1;
}
bool WIZARD_FPLIB_TABLE::ValidateOptions()
{
// Some choices can be conficting or do not work.
// Warn the user when this is the case
wxString msg;
if( getSelectedEnvVarValue().IsEmpty() )
{
// PROJECT_PATH option cannot be used with empty local path
if( m_rbPathManagement->GetSelection() == PROJECT_PATH )
{
msg = _("The project path is empty and this option is not valid.\n"
"Looks like you are running the wizard outside a project.");
wxMessageBox( msg );
return false;
}
else if( m_rbPathManagement->GetSelection() != ABSOLUTE_PATH )
{
wxMessageBox( wxString::Format(
_("The default path defined by env var \"%s\" is empty.\nCannot use it"),
GetChars( getSelectedEnvVar() ) ) );
return false;
}
}
else
{
if( IsGithubPlugin() )
{
// Github plugin cannot be used with local path; Need absolute path or valid URL
if( !getSelectedEnvVarValue().Lower().StartsWith( "http" ) )
{
msg = _("Github Plugin uses a valid Internet URL starting by http.\n"
"Cannot be used as URL");
wxMessageBox( msg );
return false;
}
}
else
{
if( getSelectedEnvVarValue().Lower().StartsWith( "http" ) )
{
msg = _("This default path looks strange.\n"
"Cannot be used for a file path");
wxMessageBox( msg );
return false;
}
}
}
// Other conficts: TODO
return true;
}
void WIZARD_FPLIB_TABLE::OnPluginSelection( wxCommandEvent& event )
{
updateFromPlugingChoice();
}
void WIZARD_FPLIB_TABLE::updateFromPlugingChoice()
{
#ifdef BUILD_GITHUB_PLUGIN
m_buttonGithubLibList->Show( IsGithubPlugin() || IsKicadPlugin() );
#endif
// update dialog options and widgets depending on a plugin choice
// Project path has no sense for GITHUB_PLUGIN
bool enablePrjPathOpt = not IsGithubPlugin();
// Project path cannot be used if unknown
if( m_gridEnvironmentVariablesList->GetCellValue(
wxGridCellCoords( m_rowPrjEnvVarPosition, 1 ) ).IsEmpty() )
enablePrjPathOpt = false;
m_rbPathManagement->Enable( PROJECT_PATH, enablePrjPathOpt );
// Sometimes only the choice "absolute path" is allowed;
// Force this choice, at least make it the default choice
bool force_absolute_path = false;
// For github plugin, the project path is not allowed
if( ( m_rbPathManagement->GetSelection() == PROJECT_PATH ) && !enablePrjPathOpt )
force_absolute_path = true;
// For github plugin, at least one github compatible path must exist
// If no github path, force absolute path
int first_github_envvar = HasGithubEnvVarCompatible();
if( IsGithubPlugin() )
{
if( first_github_envvar < 0 )
force_absolute_path = true;
else if( !getSelectedEnvVarValue().StartsWith( "http" ) )
m_gridEnvironmentVariablesList->SelectRow( first_github_envvar );
}
if( force_absolute_path )
m_rbPathManagement->SetSelection( ABSOLUTE_PATH );
}
void WIZARD_FPLIB_TABLE::OnPathManagementSelection( wxCommandEvent& event )
{
// Disable irrevant options, and enable others.
int row_count = GetEnvVarCount();
switch( m_rbPathManagement->GetSelection() )
{
case PROJECT_PATH: // Choice = path relative to the project
m_gridEnvironmentVariablesList->Enable( true );
m_buttonAddEV->Enable( false );
m_gridEnvironmentVariablesList->ShowRow( PROJECT_PATH );
for( int row = 0; row < row_count; row++ )
{
if( row == PROJECT_PATH )
continue;
m_gridEnvironmentVariablesList->HideRow( row );
}
break;
case ENV_VAR_PATH: // Choice = path relative to env var
m_gridEnvironmentVariablesList->Enable( true );
m_buttonAddEV->Enable( true );
for( int row = 0; row < row_count; row++ )
m_gridEnvironmentVariablesList->ShowRow( row );
break;
case ABSOLUTE_PATH: // Choice = path relative to the project
m_gridEnvironmentVariablesList->Enable( false );
m_buttonAddEV->Enable( false );
break;
}
}
void WIZARD_FPLIB_TABLE::OnAddEVariable( wxCommandEvent& event )
{
m_gridEnvironmentVariablesList->AppendRows( 1 );
m_gridEnvironmentVariablesList->AutoSizeColumns();
m_buttonRemoveEV->Enable( GetEnvVarCount() > m_predefinedEnvVarCnt );
m_gridEnvironmentVariablesList->SetGridCursor( GetEnvVarCount()-1, 0 );
}
void WIZARD_FPLIB_TABLE::OnRemoveEVariable( wxCommandEvent& event )
{
wxArrayInt selectedRows = m_gridEnvironmentVariablesList->GetSelectedRows();
int row_cursor = m_gridEnvironmentVariablesList->GetGridCursorRow();
if( selectedRows.size() == 0 && row_cursor >= 0 )
selectedRows.Add( row_cursor );
std::sort( selectedRows.begin(), selectedRows.end() );
for( int ii = selectedRows.GetCount()-1; ii >= 0; ii-- )
{
int row = selectedRows[ii];
// don't remove them env var. which are already existing in lib table
if( row > m_predefinedEnvVarCnt-1 )
m_gridEnvironmentVariablesList->DeleteRows( row, 1 );
}
m_gridEnvironmentVariablesList->SelectRow( m_gridEnvironmentVariablesList->GetGridCursorRow() );
m_buttonRemoveEV->Enable( GetEnvVarCount() > m_predefinedEnvVarCnt );
}
void WIZARD_FPLIB_TABLE::OnSelectEnvVarCell( wxGridEvent& event )
{
// Ensure the selected row is also the row which have the focus.
// useful when the user want to delete a row, and select it by the mouse
m_gridEnvironmentVariablesList->SelectRow( event.GetRow() );
}
wxString WIZARD_FPLIB_TABLE::getSelectedEnvVar()
{
wxString envVar;
wxArrayInt selectedRows = m_gridEnvironmentVariablesList->GetSelectedRows();
int row = selectedRows.GetCount() ? selectedRows[0] :
m_gridEnvironmentVariablesList->GetGridCursorRow();
switch( m_rbPathManagement->GetSelection() )
{
case ENV_VAR_PATH: // Choice = path relative to env var
envVar = m_gridEnvironmentVariablesList->GetCellValue(
wxGridCellCoords( row, 0 ) );
break;
case PROJECT_PATH: // Choice = path relative to the project
envVar = PROJECT_VAR_NAME;
break;
case ABSOLUTE_PATH: // Choice = absolute path
default:
break;
}
return envVar;
}
wxString WIZARD_FPLIB_TABLE::getSelectedEnvVarValue()
{
wxString envVarValue;
wxArrayInt selectedRows = m_gridEnvironmentVariablesList->GetSelectedRows();
int row = selectedRows.GetCount() ? selectedRows[0] :
m_gridEnvironmentVariablesList->GetGridCursorRow();
switch( m_rbPathManagement->GetSelection() )
{
case ENV_VAR_PATH: // Choice = path relative tp env var
envVarValue = m_gridEnvironmentVariablesList->GetCellValue(
wxGridCellCoords( row, 1 ) );
break;
case PROJECT_PATH: // Choice = path relative to the project
envVarValue = m_gridEnvironmentVariablesList->GetCellValue(
wxGridCellCoords( m_rowPrjEnvVarPosition, 1 ) );
break;
case ABSOLUTE_PATH: // Choice = absolute path
default:
break;
}
return envVarValue;
}
void WIZARD_FPLIB_TABLE::OnPageChanged( wxWizardEvent& event )
{
if( GetCurrentPage() == m_pages[2] )
setLastPage();
else if( GetCurrentPage() == m_pages[1] )
setSecondPage();
}
void WIZARD_FPLIB_TABLE::OnPageChanging( wxWizardEvent& event )
{
if( !( GetCurrentPage() == m_pages[1] && event.GetDirection() ) )
return;
if( ! ValidateOptions() )
{
event.Veto();
return;
}
if( ( m_rbPathManagement->GetSelection() != ABSOLUTE_PATH ) &&
( IsGithubPlugin() ) )
{
wxURI uri( getSelectedEnvVarValue() );
// We cannot use wxURL to test the validity of the url, because
// wxURL does not know https protocol we are using, and aways returns
// error for url starting by https
bool badurl = !uri.HasPath();
if( badurl )
{
wxMessageBox( wxString::Format(
_("The URL defined by env var \"%s\" is an incorrect URL.\nCannot use it"),
GetChars( getSelectedEnvVar() ) ) );
event.Veto();
}
}
}
bool WIZARD_FPLIB_TABLE::setSecondPage()
{
// Init parameters for the second wizard page: this is only
// the current library description.
updateFromPlugingChoice();
delete m_currLibDescr;
m_currLibDescr = NULL;
switch( m_rbFpLibFormat->GetSelection() )
{
case 0: // Kicad lib type
m_currLibDescr = new LIB_DESCR_KICAD;
m_buttonGithubLibList->SetLabel( _("Download Github Libs") );
break;
case 1: // Github lib type
m_currLibDescr = new LIB_DESCR_GITHUB;
m_buttonGithubLibList->SetLabel( _("Github Libs List") );
break;
case 2: // Legacy lib type
m_currLibDescr = new LIB_DESCR_LEGACY;
break;
case 3: // Eagle V6 lib type
m_currLibDescr = new LIB_DESCR_EAGLE;
break;
case 4: // Geda lib type
m_currLibDescr = new LIB_DESCR_GEDA;
break;
}
if( IsGithubPlugin() )
{
#ifdef KICAD_USE_WEBKIT
m_buttonAddLib->SetLabel( _("Add Libs with WebViewer") );
#else
m_buttonAddLib->SetLabel( _("Add FP Library entry") );
#endif
}
else
m_buttonAddLib->SetLabel( _("Add FP Libraries") );
return m_currLibDescr!= NULL;
}
bool WIZARD_FPLIB_TABLE::setLastPage() // Init prms for the last wizard page
{
// Update texts in last wizard page
m_textPluginType->SetLabel( m_rbFpLibFormat->GetStringSelection() );
switch( m_rbPathManagement->GetSelection() )
{
case ENV_VAR_PATH: // Choice = path relative env var
case PROJECT_PATH: // Choice = path relative to the project
m_currLibDescr->m_EnvVarName = getSelectedEnvVar();
m_currLibDescr->m_DefaultPath = getSelectedEnvVarValue();
m_currLibDescr->m_IsAbsolutePath = false;
m_textOption->SetLabel( wxString::Format( wxT("%s (%s)"),
m_rbPathManagement->GetStringSelection().GetData(),
getSelectedEnvVar().GetData() ) );
m_textPath->SetLabel( getSelectedEnvVarValue() );
break;
case ABSOLUTE_PATH: // Choice = absolute path
m_currLibDescr->m_IsAbsolutePath = true;
m_textOption->SetLabel( m_rbPathManagement->GetStringSelection() );
if( IsGithubPlugin() )
m_textPath->SetLabel( _("Full URL") );
else
m_textPath->SetLabel( _("Full filename") );
break;
}
return true;
}
void WIZARD_FPLIB_TABLE::OnAddFpLibs( wxCommandEvent& event )
{
if( m_currLibDescr->m_IsFile )
selectLibsFiles();
else if( m_currLibDescr->m_IsGitHub )
selectLibsGithubWithWebViewer();
else
selectLibsFolders();
m_gridFpListLibs->SetGridCursor( GetLibsCount()-1, 0 );
m_gridFpListLibs->SelectRow( GetLibsCount()-1 );
}
void WIZARD_FPLIB_TABLE::selectLibsFiles() // select a set of library files
{
wxString msk = wxT("*.") + m_currLibDescr->m_Ext;
wxFileDialog dlg( this, _("Select Library Files"), m_currLibDescr->m_DefaultPath,
wxEmptyString, msk,
wxFD_DEFAULT_STYLE|wxFD_FILE_MUST_EXIST|wxFD_MULTIPLE );
dlg.ShowModal();
wxArrayString filepaths;
dlg.GetPaths( filepaths );
// Create the nickname: currently make it from the filename
wxArrayString nicknames;
wxFileName fn;
for( unsigned ii = 0; ii < filepaths.GetCount(); ii++ )
{
fn = filepaths[ii];
nicknames.Add( fn.GetName() );
if( m_currLibDescr->m_IsAbsolutePath || m_currLibDescr->m_DefaultPath.IsEmpty() )
{
filepaths[ii] = fn.GetPathWithSep();
}
else
{
if( ! fn.MakeRelativeTo( m_currLibDescr->m_DefaultPath ) )
filepaths[ii] = fn.GetFullPath();
else
filepaths[ii].Printf( wxT("${%s}%c%s"),
GetChars( m_currLibDescr->m_EnvVarName ),
fn.GetPathSeparator(),
GetChars( fn.GetFullPath() ) );
}
#ifdef __WINDOWS__
// We store paths using Unix notation, which also works fine on Windows
filepaths[ii].Replace( wxT("\\"), wxT("/") );
#endif
}
populateLibList( nicknames, filepaths, m_currLibDescr->m_PluginName );
m_gridFpListLibs->AutoSizeColumns();
}
void WIZARD_FPLIB_TABLE::populateLibList( const wxArrayString& aNickNames,
const wxArrayString& aPaths,
const wxString& aPluginName )
{
if( aPaths.GetCount() <= 0 )
return;
// Ensure there is room for selected libs
int first_row = m_gridFpListLibs->GetTable()->GetRowsCount();
m_gridFpListLibs->AppendRows( aPaths.GetCount() );
// Populates the library list
for( unsigned ii = 0; ii < aPaths.GetCount(); ii++ )
{
int jj = first_row + ii;
// Add the nickname: currently make it from filename
m_gridFpListLibs->SetCellValue( jj, 0, aNickNames[ii] );
// Add the full path:
m_gridFpListLibs->SetCellValue( jj, 1, aPaths[ii] );
// Add the plugin name:
m_gridFpListLibs->SetCellValue( jj, 2, aPluginName );
m_gridFpListLibs->SetReadOnly( jj, 2, true );
}
m_gridFpListLibs->Fit();
}
// A helper dialog to show and select a set of directories
class DIALOG_SELECT_DIRLIST : public DIALOG_SELECT_DIRLIST_BASE
{
public:
DIALOG_SELECT_DIRLIST( wxWindow* parent,
const wxString& aDefaultPath ):
DIALOG_SELECT_DIRLIST_BASE( parent, wxID_ANY )
{
if( !aDefaultPath.IsEmpty() )
m_dirCtrl->SetPath( aDefaultPath );
Layout();
GetSizer()->Fit( this );
GetSizer()->SetSizeHints(this);
Centre();
}
~DIALOG_SELECT_DIRLIST() {};
void GetPaths( wxArrayString& aPaths ) { m_dirCtrl->GetPaths( aPaths ); }
};
void WIZARD_FPLIB_TABLE::selectLibsFolders() // select a set of library folders
{
DIALOG_SELECT_DIRLIST dlg( this, m_currLibDescr->m_DefaultPath );
if( dlg.ShowModal() != wxID_OK )
return;
wxArrayString filepaths;
dlg.GetPaths( filepaths );
// Create the nickname: currently make it from the filename
wxArrayString nicknames;
wxFileName fn;
for( unsigned ii = 0; ii < filepaths.GetCount(); ii++ )
{
fn = filepaths[ii];
nicknames.Add( fn.GetName() );
fn.AssignDir( filepaths[ii] );
if( m_currLibDescr->m_IsAbsolutePath || m_currLibDescr->m_DefaultPath.IsEmpty() )
{
filepaths[ii] = fn.GetFullPath();
}
else
{
if( ! fn.MakeRelativeTo( m_currLibDescr->m_DefaultPath ) )
filepaths[ii] = fn.GetFullPath();
else
filepaths[ii].Printf( wxT("${%s}%c%s"),
GetChars( m_currLibDescr->m_EnvVarName ),
fn.GetPathSeparator(),
GetChars( fn.GetFullPath() ) );
}
#ifdef __WINDOWS__
// We store paths using Unix notation, which also works fine on Windows
filepaths[ii].Replace( wxT("\\"), wxT("/") );
#endif
// Remove trailing path separator, if any.
if( filepaths[ii].EndsWith( wxT("/") ) )
filepaths[ii].RemoveLast();
}
populateLibList( nicknames, filepaths, m_currLibDescr->m_PluginName );
}
#ifdef KICAD_USE_WEBKIT
// A helper function to run the wen viewer (see webviewer.cpp)
extern int RunWebViewer( wxWindow * aParent, const wxString& aUrlOnStart,
wxArrayString* aUrlListSelection = NULL );
#endif
void WIZARD_FPLIB_TABLE::selectLibsGithubWithWebViewer() // select a set of library on Github
{
// A string array to store the URLs selected from the web viewer:
wxArrayString urls;
// Run the web viewer and open the default URL: the default path
// or our github library repos
wxString defaultURL = m_currLibDescr->m_DefaultPath;
if( defaultURL.IsEmpty() )
defaultURL = wxT( "https://github.com/KiCad" );
#ifdef KICAD_USE_WEBKIT
RunWebViewer( this, defaultURL, &urls );
#else
// If the Web Viewer is not available, just add a template
// to the fp lib table.
// The user have to edit it
urls.Add( defaultURL + wxT("/newlibname.pretty") );
#endif
installGithubLibsFromList( urls );
}
void WIZARD_FPLIB_TABLE::installGithubLibsFromList( wxArrayString& aUrlList )
{
// add the libs found in aUrlList, after calculating a nickname and
// replacing the path by an env variable, if needed
// Create the nickname: currently make it from the url
wxArrayString filepaths;
wxArrayString nicknames;
for( unsigned ii = 0; ii < aUrlList.GetCount(); ii++ )
{
wxString urlstring( aUrlList[ii] );
wxURI uri( urlstring );
// We cannot use wxURL to test the validity of the url, because
// wxURL does not know https protocol we are using, and aways returns
// error for URLs starting by https. Hope this test is enough
if( uri.HasPath() )
nicknames.Add( uri.GetPath().AfterLast( '/').BeforeLast( '.' ) );
else
continue; // Should not happen: bad URL
if( m_currLibDescr->m_IsAbsolutePath ||
m_currLibDescr->m_DefaultPath.IsEmpty() )
{
filepaths.Add( aUrlList[ii] ); // use the full URL
}
else
{
wxString shortURI;
if( aUrlList[ii].Lower().StartsWith(
m_currLibDescr->m_DefaultPath.Lower(), &shortURI ) )
{
shortURI.Prepend( wxT("${") + m_currLibDescr->m_EnvVarName + wxT("}") );
filepaths.Add( shortURI );
}
else // keep the full URL
filepaths.Add( aUrlList[ii] ); // use the full URL
}
}
populateLibList( nicknames, filepaths, m_currLibDescr->m_PluginName );
}
void WIZARD_FPLIB_TABLE::OnRemoveFpLibs( wxCommandEvent& event )
{
wxArrayInt selectedRows = m_gridFpListLibs->GetSelectedRows();
int row_cursor = m_gridFpListLibs->GetGridCursorRow();
if( selectedRows.size() == 0 && row_cursor >= 0 )
selectedRows.Add( row_cursor );
std::sort( selectedRows.begin(), selectedRows.end() );
for( int ii = selectedRows.GetCount()-1; ii >= 0; ii-- )
{
int row = selectedRows[ii];
m_gridFpListLibs->DeleteRows( row, 1 );
}
m_gridFpListLibs->SelectRow( m_gridFpListLibs->GetGridCursorRow() );
}
#ifdef BUILD_GITHUB_PLUGIN
#include <../github/github_getliblist.h>
void WIZARD_FPLIB_TABLE::OnGithubLibsList( wxCommandEvent& event )
{
wxArrayString liblist;
getLibsListGithub( liblist );
if( liblist.GetCount() == 0 ) // No lib selected
return;
if( IsKicadPlugin() )
{
wxString msg;
if( !downloadGithubLibsFromList( liblist, &msg ) )
{
wxMessageBox( msg );
return;
}
}
else
installGithubLibsFromList( liblist );
}
void WIZARD_FPLIB_TABLE::getLibsListGithub( wxArrayString& aList )
{
wxBeginBusyCursor();
// Be sure there is no trailing '/' at the end of the repo name
wxString git_url = m_textCtrlGithubURL->GetValue();
if( git_url.EndsWith( wxT("/" ) ) )
{
git_url.RemoveLast();
m_textCtrlGithubURL->SetValue( git_url );
}
GITHUB_GETLIBLIST getter( git_url );
wxArrayString fullList;
getter.GetLibraryList( fullList );
wxEndBusyCursor();
wxArrayInt choices;
wxString msg( _( "Urls detected as footprint .pretty libraries.\n"
"Selected urls will be added to the current footprint library list" ) );
if( wxGetSelectedChoices( choices, msg,
_( "Footprint libraries" ), fullList, this ) <= 0 )
return;
// Add selected url in list
for( unsigned ii = 0; ii < choices.GetCount(); ii++ )
{
wxString& url = fullList[choices[ii]];
aList.Add( url );
}
}
// Download the .pretty libraries found in aUrlLis and store them on disk
// in a master folder
bool WIZARD_FPLIB_TABLE::downloadGithubLibsFromList( wxArrayString& aUrlList,
wxString * aErrorMessage )
{
wxString masterFolder;
wxString default_path;
wxGetEnv( FP_LIB_TABLE::GlobalPathEnvVariableName(), &default_path );
masterFolder = wxDirSelector( _("Output Folder" ),
default_path, 0, wxDefaultPosition, this );
if( masterFolder.IsEmpty() ) // Aborted by user
{
if( aErrorMessage )
*aErrorMessage = _( "Aborted" );
return false;
}
if( !wxDirExists( masterFolder ) )
{
if( aErrorMessage )
aErrorMessage->Printf( _( "Folder '%s' does not exists" ),
GetChars( masterFolder ) );
return false;
}
// Display a progress bar to show the downlaod state
wxProgressDialog pdlg( _("Download libraries"), wxEmptyString, aUrlList.GetCount() );
// Download libs:
for( unsigned ii = 0; ii < aUrlList.GetCount(); ii++ )
{
wxString& libsrc_name = aUrlList[ii];
wxString libdst_name;
// Extract the lib name from the full URL:
wxURI url( libsrc_name );
wxFileName fn( url.GetPath() );
// Set our local path
fn.SetPath( masterFolder );
libdst_name = fn.GetFullPath();
if( !wxDirExists( libdst_name ) )
wxMkdir( libdst_name );
pdlg.Update( ii, libsrc_name);
try
{
PLUGIN::RELEASER src( IO_MGR::PluginFind( IO_MGR::GITHUB ) );
PLUGIN::RELEASER dst( IO_MGR::PluginFind( IO_MGR::KICAD ) );
wxArrayString footprints = src->FootprintEnumerate( libsrc_name );
for( unsigned i = 0; i < footprints.size(); ++i )
{
std::auto_ptr<MODULE> m( src->FootprintLoad( libsrc_name, footprints[i] ) );
dst->FootprintSave( libdst_name, m.get() );
// m is deleted here by auto_ptr.
}
}
catch( const IO_ERROR& ioe )
{
if( aErrorMessage )
aErrorMessage->Printf( _("Error:\n'%s'\nwhile downloading library:\n'%s'"),
GetChars( ioe.errorText ), GetChars( libsrc_name ) );
return false;
}
}
return true;
}
#endif