summaryrefslogtreecommitdiff
path: root/pcbnew/dialogs/wizard_add_fplib.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'pcbnew/dialogs/wizard_add_fplib.cpp')
-rw-r--r--pcbnew/dialogs/wizard_add_fplib.cpp863
1 files changed, 863 insertions, 0 deletions
diff --git a/pcbnew/dialogs/wizard_add_fplib.cpp b/pcbnew/dialogs/wizard_add_fplib.cpp
new file mode 100644
index 0000000..254cec3
--- /dev/null
+++ b/pcbnew/dialogs/wizard_add_fplib.cpp
@@ -0,0 +1,863 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2015 CERN
+ * @author Maciej Suminski <maciej.suminski@cern.ch>
+ * Copyright (C) 2014-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 Wizard for selecting footprint libraries consisting of 4 steps:
+ * - select source (Github/local files)
+ * - pick libraries
+ * - present a review of libraries (including validation)
+ * - select scope (global/project)
+ */
+
+#include <wx/wx.h>
+#include <wx/uri.h>
+#include <wx/dir.h>
+#include <wx/progdlg.h>
+
+#include <pgm_base.h>
+#include <project.h>
+#include <wizard_add_fplib.h>
+#include <fp_lib_table.h>
+#include <confirm.h>
+
+#include <class_module.h>
+
+#ifdef BUILD_GITHUB_PLUGIN
+#include <../github/github_getliblist.h>
+#endif
+
+// a key to store the default Kicad Github libs URL
+#define KICAD_FPLIBS_URL_KEY wxT( "kicad_fplib_url" )
+#define KICAD_FPLIBS_LAST_DOWNLOAD_DIR wxT( "kicad_fplib_last_download_dir" )
+
+// Filters for the file picker
+static const int FILTER_COUNT = 4;
+static const struct
+{
+ wxString m_Description; ///< Description shown in the file picker dialog
+ wxString m_Extension; ///< In case of folders it stands for extensions of files stored inside
+ bool m_IsFile; ///< Whether it is a folder or a file
+ IO_MGR::PCB_FILE_T m_Plugin;
+} fileFilters[FILTER_COUNT] =
+{
+ { "KiCad (folder with .kicad_mod files)", "kicad_mod", false, IO_MGR::KICAD },
+ { "Eagle 6.x (*.lbr)", "lbr", true, IO_MGR::EAGLE },
+ { "KiCad legacy (*.mod)", "mod", true, IO_MGR::LEGACY },
+ { "Geda (folder with *.fp files)", "fp", false, IO_MGR::GEDA_PCB },
+};
+
+
+// Returns the filter string for the file picker
+static wxString getFilterString()
+{
+ wxString filterInit = _( "All supported library formats|" );
+ wxString filter;
+
+ for( int i = 0; i < FILTER_COUNT; ++i )
+ {
+ // Init part
+ if( i != 0 )
+ filterInit += ";";
+
+ filterInit += "*." + fileFilters[i].m_Extension;
+
+ // Rest of the filter string
+ filter += "|" + fileFilters[i].m_Description +
+ "|" + ( fileFilters[i].m_IsFile ? "*." + fileFilters[i].m_Extension : "" );
+ }
+
+ return filterInit + filter;
+}
+
+
+// Tries to guess the plugin type basing on the path
+static boost::optional<IO_MGR::PCB_FILE_T> getPluginType( const wxString& aPath )
+{
+ if( ( aPath.StartsWith( "http://" ) || aPath.StartsWith( "https://" ) ) )
+ return boost::optional<IO_MGR::PCB_FILE_T>( IO_MGR::GITHUB );
+
+ wxFileName path( aPath );
+
+ for( int i = 0; i < FILTER_COUNT; ++i )
+ {
+ bool ok = false;
+
+ if( fileFilters[i].m_IsFile )
+ {
+ ok = path.IsFileReadable() && path.GetExt() == fileFilters[i].m_Extension;
+ }
+ else if( path.IsDirReadable() )
+ {
+ // Plugin expects a directory containing files with a specific extension
+ wxDir dir( aPath );
+
+ if( dir.IsOpened() )
+ {
+ wxString filename;
+
+ dir.GetFirst( &filename, "*." + fileFilters[i].m_Extension, wxDIR_FILES );
+
+ ok = !filename.IsEmpty();
+ }
+ }
+
+ if( ok )
+ return boost::optional<IO_MGR::PCB_FILE_T>( fileFilters[i].m_Plugin );
+ }
+
+ return boost::none;
+}
+
+
+// Checks if a filename fits specific filter
+static bool passesFilter( const wxString& aFileName, int aFilterIndex )
+{
+ wxASSERT( aFilterIndex <= FILTER_COUNT );
+ wxFileName file( aFileName );
+ boost::optional<IO_MGR::PCB_FILE_T> result = getPluginType( aFileName );
+
+ if( !result ) // does not match any supported plugin
+ return false;
+
+ if( aFilterIndex == 0 ) // any plugin will do
+ return true;
+
+ return ( fileFilters[aFilterIndex - 1].m_Plugin == *result );
+}
+
+
+WIZARD_FPLIB_TABLE::LIBRARY::LIBRARY( const wxString& aPath, const wxString& aDescription ) :
+ m_path( aPath ), m_description( aDescription ), m_status( NOT_CHECKED )
+{
+ m_plugin = getPluginType( aPath );
+}
+
+
+bool WIZARD_FPLIB_TABLE::LIBRARY::Test()
+{
+ if( !m_plugin )
+ {
+ m_status = LIBRARY::INVALID;
+ return false;
+ }
+
+ PLUGIN* p = IO_MGR::PluginFind( *m_plugin );
+ wxArrayString footprints;
+
+ if( !p )
+ {
+ m_status = LIBRARY::INVALID;
+ return false;
+ }
+
+ try
+ {
+ footprints = p->FootprintEnumerate( m_path );
+ }
+ catch( IO_ERROR& e )
+ {
+ m_status = LIBRARY::INVALID;
+ return false;
+ }
+
+ if( footprints.GetCount() == 0 )
+ {
+ m_status = LIBRARY::INVALID;
+ return false;
+ }
+
+ m_status = LIBRARY::OK;
+ return true;
+}
+
+
+wxString WIZARD_FPLIB_TABLE::LIBRARY::GetPluginName() const
+{
+ if( !m_plugin )
+ return _( "UNKNOWN" );
+
+ switch( *m_plugin )
+ {
+ case IO_MGR::LEGACY:
+ return wxT( "Legacy" );
+
+ case IO_MGR::KICAD:
+ return wxT( "KiCad" );
+
+ case IO_MGR::EAGLE:
+ return wxT( "Eagle" );
+
+ case IO_MGR::GEDA_PCB:
+ return wxT( "Geda-PCB" );
+
+ case IO_MGR::GITHUB:
+ return wxT( "Github" );
+
+ default:
+ return _( "UNKNOWN" );
+ }
+
+ /*PLUGIN* p = IO_MGR::PluginFind( *m_plugin );
+
+ if( !p )
+ return _( "UNKNOWN" );
+
+ return p->PluginName();*/
+}
+
+
+wxString WIZARD_FPLIB_TABLE::LIBRARY::GetRelativePath( const wxString& aBase, const wxString& aSubstitution ) const
+{
+ wxFileName libPath( m_path );
+
+ // Check if the library path belongs to the project folder
+ if( libPath.MakeRelativeTo( aBase ) && !libPath.GetFullPath().StartsWith( ".." ) )
+ {
+ return wxString( aSubstitution + "/" + libPath.GetFullPath() );
+ }
+
+ // Probably on another drive, so the relative path will not work
+ return wxEmptyString;
+}
+
+
+wxString WIZARD_FPLIB_TABLE::LIBRARY::GetAutoPath( LIB_SCOPE aScope ) const
+{
+ const wxString& global_env = FP_LIB_TABLE::GlobalPathEnvVariableName();
+ const wxString& project_env = PROJECT_VAR_NAME;
+ const wxString& github_env( "KIGITHUB" );
+
+ wxString rel_path;
+
+ // KISYSMOD check
+ rel_path = replaceEnv( global_env );
+
+ if( !rel_path.IsEmpty() )
+ return rel_path;
+
+ // KIGITHUB check
+ rel_path = replaceEnv( github_env, false );
+
+ if( !rel_path.IsEmpty() )
+ return rel_path;
+
+ // KIPRJMOD check
+ if( aScope == PROJECT )
+ {
+ rel_path = replaceEnv( project_env );
+
+ if( !rel_path.IsEmpty() )
+ return rel_path;
+ }
+
+ // Return the full path
+ return m_path;
+}
+
+
+wxString WIZARD_FPLIB_TABLE::LIBRARY::GetDescription() const
+{
+ if( !m_description.IsEmpty() )
+ return m_description;
+
+ wxFileName filename( m_path );
+ return filename.GetName();
+}
+
+
+wxString WIZARD_FPLIB_TABLE::LIBRARY::replaceEnv( const wxString& aEnvVar, bool aFilePath ) const
+{
+ wxString env_path;
+
+ if( !wxGetEnv( aEnvVar, &env_path ) )
+ return wxEmptyString;
+
+ //return GetRelativePath( m_path, wxString( "$(" + aEnvVar + ")" ) );
+
+ wxString result( m_path );
+
+ if( result.Replace( env_path, wxString( "$(" + aEnvVar + ")" ) ) )
+ return result;
+
+ return wxEmptyString;
+}
+
+
+WIZARD_FPLIB_TABLE::WIZARD_FPLIB_TABLE( wxWindow* aParent ) :
+ WIZARD_FPLIB_TABLE_BASE( aParent ), m_welcomeDlg( m_pages[0] ),
+ m_fileSelectDlg( m_pages[1] ), m_githubListDlg( m_pages[2] ),
+ m_reviewDlg( m_pages[3] ), m_targetDlg( m_pages[4] ), m_selectedFilter( 0 )
+{
+ m_filePicker->SetFilter( getFilterString() );
+
+ // Initialize default download dir
+ wxString default_path;
+ wxGetEnv( FP_LIB_TABLE::GlobalPathEnvVariableName(), &default_path );
+ setDownloadDir( default_path );
+ m_filePicker->SetPath( default_path );
+
+ // Restore the Github url
+ wxString githubUrl;
+
+ wxConfigBase* cfg = Pgm().CommonSettings();
+ cfg->Read( KICAD_FPLIBS_URL_KEY, &githubUrl );
+ cfg->Read( KICAD_FPLIBS_LAST_DOWNLOAD_DIR, &m_lastGithubDownloadDirectory );
+
+
+ if( !m_lastGithubDownloadDirectory.IsEmpty() )
+ {
+ setDownloadDir( m_lastGithubDownloadDirectory );
+ m_filePicker->SetPath( m_lastGithubDownloadDirectory );
+ } else {
+ m_lastGithubDownloadDirectory = default_path;
+ }
+
+ if( githubUrl.IsEmpty() )
+ githubUrl = wxT( "https://github.com/KiCad" );
+
+ SetGithubURL( githubUrl );
+
+ // Give the 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();
+
+ if( !m_radioAddGithub->GetValue() && !m_radioAddLocal->GetValue() )
+ m_radioAddLocal->SetValue( true );
+
+ setupDialogOrder();
+ updateGithubControls();
+
+ Connect( wxEVT_RADIOBUTTON, wxCommandEventHandler( WIZARD_FPLIB_TABLE::OnSourceCheck ), NULL, this );
+ Connect( wxEVT_DIRCTRL_SELECTIONCHANGED, wxCommandEventHandler( WIZARD_FPLIB_TABLE::OnSelectFiles ), NULL, this );
+ Connect( wxEVT_CHECKLISTBOX, wxCommandEventHandler( WIZARD_FPLIB_TABLE::OnCheckGithubList ), NULL, this );
+}
+
+
+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, GetGithubURL() );
+}
+
+
+WIZARD_FPLIB_TABLE::LIB_SOURCE WIZARD_FPLIB_TABLE::GetLibSource() const
+{
+ if( m_radioAddGithub->GetValue() )
+ return GITHUB;
+
+ wxASSERT( m_radioAddLocal->GetValue() );
+
+ return LOCAL;
+}
+
+
+WIZARD_FPLIB_TABLE::LIB_SCOPE WIZARD_FPLIB_TABLE::GetLibScope() const
+{
+ if( m_radioGlobal->GetValue() )
+ return GLOBAL;
+
+ wxASSERT( m_radioProject->GetValue() );
+
+ return PROJECT;
+}
+
+
+void WIZARD_FPLIB_TABLE::OnPageChanged( wxWizardEvent& aEvent )
+{
+ SetBitmap( KiBitmap( wizard_add_fplib_icon_xpm ) );
+ enableNext( true );
+
+#ifdef BUILD_GITHUB_PLUGIN
+ if( GetCurrentPage() == m_githubListDlg )
+ setupGithubList();
+ else
+#endif
+ if( GetCurrentPage() == m_fileSelectDlg )
+ setupFileSelect();
+ else if( GetCurrentPage() == m_reviewDlg )
+ setupReview();
+}
+
+
+void WIZARD_FPLIB_TABLE::OnSelectFiles( wxCommandEvent& aEvent )
+{
+ int filterIdx = m_filePicker->GetFilterIndex();
+
+ if( m_selectedFilter != filterIdx )
+ {
+ m_selectedFilter = filterIdx;
+
+ // Process the event again, as in the first iteration we cannot get the list of selected items
+ wxCommandEvent ev( wxEVT_DIRCTRL_SELECTIONCHANGED );
+ AddPendingEvent( ev );
+ return;
+ }
+
+ enableNext( checkFiles() );
+}
+
+
+void WIZARD_FPLIB_TABLE::OnCheckGithubList( wxCommandEvent& aEvent )
+{
+ wxArrayInt dummy;
+
+ enableNext( m_checkListGH->GetCheckedItems( dummy ) > 0 );
+}
+
+
+void WIZARD_FPLIB_TABLE::OnSourceCheck( wxCommandEvent& aEvent )
+{
+ updateGithubControls();
+ setupDialogOrder();
+}
+
+
+void WIZARD_FPLIB_TABLE::OnSelectAllGH( wxCommandEvent& aEvent )
+{
+ for( unsigned int i = 0; i < m_checkListGH->GetCount(); ++i )
+ m_checkListGH->Check( i, true );
+
+ // The list might be empty, e.g. in case of download error
+ wxArrayInt dummy;
+ enableNext( m_checkListGH->GetCheckedItems( dummy ) > 0 );
+}
+
+
+void WIZARD_FPLIB_TABLE::OnUnselectAllGH( wxCommandEvent& aEvent )
+{
+ for( unsigned int i = 0; i < m_checkListGH->GetCount(); ++i )
+ m_checkListGH->Check( i, false );
+
+ enableNext( false );
+}
+
+
+void WIZARD_FPLIB_TABLE::OnChangeSearch( wxCommandEvent& aEvent )
+{
+ wxString searchPhrase = m_searchCtrlGH->GetValue().Lower();
+
+ // Store the current selection
+ wxArrayInt checkedIndices;
+ m_checkListGH->GetCheckedItems( checkedIndices );
+ wxArrayString checkedStrings;
+
+ for( unsigned int i = 0; i < checkedIndices.GetCount(); ++i )
+ checkedStrings.Add( m_checkListGH->GetString( checkedIndices[i] ).AfterLast( '/' ) );
+
+ m_checkListGH->Clear();
+
+ // Rebuild the list, putting the matching entries on the top
+ int matching = 0; // number of entries matching the search phrase
+ for( unsigned int i = 0; i < m_githubLibs.GetCount(); ++i )
+ {
+ const wxString& lib = m_githubLibs[i].AfterLast( '/' );
+ bool wasChecked = ( checkedStrings.Index( lib ) != wxNOT_FOUND );
+ int insertedIdx = -1;
+
+ if( !searchPhrase.IsEmpty() && lib.Lower().Contains( searchPhrase ) )
+ {
+ insertedIdx = m_checkListGH->Insert( lib, matching++ );
+ m_checkListGH->SetSelection( insertedIdx );
+ }
+ else
+ insertedIdx = m_checkListGH->Append( lib );
+
+ if( wasChecked )
+ m_checkListGH->Check( insertedIdx );
+ }
+
+ if( !m_checkListGH->IsEmpty() )
+ m_checkListGH->EnsureVisible( 0 );
+}
+
+
+void WIZARD_FPLIB_TABLE::OnWizardFinished( wxWizardEvent& aEvent )
+{
+#ifdef BUILD_GITHUB_PLUGIN
+ // Shall we download a localy copy of the libraries
+ if( GetLibSource() == GITHUB && m_downloadGithub->GetValue() )
+ {
+ wxString error;
+ wxArrayString libs;
+
+ // Prepare a list of libraries to download
+ for( std::vector<LIBRARY>::const_iterator it = m_libraries.begin();
+ it != m_libraries.end(); ++it )
+ {
+ wxASSERT( it->GetPluginType() == IO_MGR::GITHUB );
+
+ if( it->GetStatus() != LIBRARY::INVALID )
+ libs.Add( it->GetAbsolutePath() );
+ }
+
+ if( !downloadGithubLibsFromList( libs, &error ) )
+ {
+ DisplayError( this, error );
+ m_libraries.clear();
+ }
+ else
+ {
+ // Now libraries are stored locally, so update the paths to point to the download folder
+ for( std::vector<LIBRARY>::iterator it = m_libraries.begin();
+ it != m_libraries.end(); ++it )
+ {
+ wxString path = it->GetAbsolutePath();
+ path.Replace( GetGithubURL(), getDownloadDir() );
+ it->setPath( path );
+ it->setPluginType( IO_MGR::KICAD );
+ }
+ }
+ }
+#endif
+}
+
+
+void WIZARD_FPLIB_TABLE::OnBrowseButtonClick( wxCommandEvent& aEvent )
+{
+ wxString path = getDownloadDir();
+
+ path = wxDirSelector( _("Choose a folder to save the downloaded libraries" ),
+ path, 0, wxDefaultPosition, this );
+
+ if( !path.IsEmpty() && wxDirExists( path ) )
+ {
+ setDownloadDir( path );
+
+ wxConfigBase* cfg = Pgm().CommonSettings();
+ cfg->Write( KICAD_FPLIBS_LAST_DOWNLOAD_DIR, path );
+
+ updateGithubControls();
+ }
+}
+
+
+void WIZARD_FPLIB_TABLE::OnCheckSaveCopy( wxCommandEvent& aEvent )
+{
+ updateGithubControls();
+}
+
+
+bool WIZARD_FPLIB_TABLE::checkFiles() const
+{
+ // Get current selection (files & directories)
+ wxArrayString candidates;
+ m_filePicker->GetPaths( candidates );
+
+ // Workaround, when you change filters "/" is automatically selected
+ int slash_index = candidates.Index( "/", true, true );
+ if( slash_index != wxNOT_FOUND )
+ candidates.RemoveAt( slash_index, 1 );
+
+ if( candidates.IsEmpty() )
+ return false;
+
+ // Verify all the files/folders comply to the selected library type filter
+ for( unsigned int i = 0; i < candidates.GetCount(); ++i )
+ {
+ if( !passesFilter( candidates[i], m_filePicker->GetFilterIndex() ) )
+ return false;
+ }
+
+ return true;
+}
+
+
+#ifdef BUILD_GITHUB_PLUGIN
+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 );
+ getter.GetFootprintLibraryList( aList );
+
+ wxEndBusyCursor();
+}
+
+
+// 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 )
+{
+ // Display a progress bar to show the downlaod state
+ wxProgressDialog pdlg( _( "Downloading 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( getDownloadDir() );
+ libdst_name = fn.GetFullPath();
+
+ if( !wxDirExists( libdst_name ) )
+ wxMkdir( libdst_name );
+
+ pdlg.Update( ii, libsrc_name );
+ pdlg.Refresh();
+ pdlg.Update();
+
+ 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;
+}
+
+
+void WIZARD_FPLIB_TABLE::setupGithubList()
+{
+ // Enable 'Next' only if there is at least one library selected
+ wxArrayInt checkedIndices;
+ m_checkListGH->GetCheckedItems( checkedIndices );
+ enableNext( checkedIndices.GetCount() > 0 );
+
+ // Update only if necessary
+ if( m_githubLibs.GetCount() == 0 )
+ getLibsListGithub( m_githubLibs );
+
+ m_searchCtrlGH->Clear();
+
+ // Clear the review list so it will be reloaded
+ m_libraries.clear();
+ m_listCtrlReview->DeleteAllItems();
+}
+#endif /* BUILD_GITHUB_PLUGIN */
+
+
+void WIZARD_FPLIB_TABLE::updateGithubControls()
+{
+#ifndef BUILD_GITHUB_PLUGIN
+ m_radioAddGithub->Enable( false );
+#endif
+
+ // Disable inputs that have no meaning for the selected source
+ bool githubEnabled = ( GetLibSource() == GITHUB );
+ m_textCtrlGithubURL->Enable( githubEnabled );
+ m_downloadGithub->Enable( githubEnabled );
+ m_downloadDir->Enable( githubEnabled && wantLocalCopy() );
+ m_btnBrowse->Enable( githubEnabled && wantLocalCopy() );
+
+ bool valid = !( githubEnabled && wantLocalCopy() ) || wxFileName::IsDirWritable( getDownloadDir() );
+
+ // Do not allow to go further unless there is a valid directory selected
+ m_invalidDir->Show( !valid );
+ enableNext( valid );
+}
+
+
+void WIZARD_FPLIB_TABLE::updateLibraries()
+{
+ // No need to update, the review list is ready
+ if( m_listCtrlReview->GetItemCount() != 0 )
+ return;
+
+ switch( GetLibSource() )
+ {
+ case LOCAL:
+ {
+ wxArrayString libs;
+ m_filePicker->GetPaths( libs );
+
+ // Workaround, when you change filters "/" is automatically selected
+ int slash_index = libs.Index( "/", true, true );
+ if( slash_index != wxNOT_FOUND )
+ libs.RemoveAt( slash_index, 1 );
+
+ m_libraries.reserve( libs.GetCount() );
+
+ for( unsigned int i = 0; i < libs.GetCount(); ++i )
+ m_libraries.push_back( libs[i] );
+ }
+ break;
+
+ case GITHUB:
+ {
+ wxArrayInt checkedLibs;
+ m_checkListGH->GetCheckedItems( checkedLibs );
+
+ m_libraries.reserve( checkedLibs.GetCount() );
+
+ for( unsigned int i = 0; i < checkedLibs.GetCount(); ++i )
+ m_libraries.push_back( GetGithubURL() + "/" + m_checkListGH->GetString( checkedLibs[i] ) );
+ }
+ break;
+
+ default:
+ wxASSERT( false );
+ break;
+ }
+}
+
+
+void WIZARD_FPLIB_TABLE::setupDialogOrder()
+{
+ // Alternate the wizard pages flow depending on the selected option
+ switch( GetLibSource() )
+ {
+ case LOCAL:
+ m_welcomeDlg->SetNext( m_fileSelectDlg );
+ m_fileSelectDlg->SetPrev( m_welcomeDlg );
+
+ m_fileSelectDlg->SetNext( m_reviewDlg );
+ m_reviewDlg->SetPrev( m_fileSelectDlg );
+ break;
+
+ case GITHUB:
+ m_welcomeDlg->SetNext( m_githubListDlg );
+ m_githubListDlg->SetPrev( m_welcomeDlg );
+
+ m_githubListDlg->SetNext( m_reviewDlg );
+ m_reviewDlg->SetPrev( m_githubListDlg );
+ break;
+
+ default:
+ wxASSERT( false );
+ break;
+ }
+}
+
+
+void WIZARD_FPLIB_TABLE::setupFileSelect()
+{
+ // Disable the button until something is selected
+ enableNext( checkFiles() );
+
+ // Clear the review list so it will be reloaded
+ m_libraries.clear();
+ m_listCtrlReview->DeleteAllItems();
+}
+
+
+void WIZARD_FPLIB_TABLE::setupReview()
+{
+ wxBeginBusyCursor();
+ updateLibraries();
+
+ int libTotalCount = m_libraries.size();
+ int libCount = 0;
+ bool validate = true;
+ wxProgressDialog progressDlg( _( "Please wait..." ), _( "Validating libraries" ),
+ libTotalCount, this,
+ wxPD_APP_MODAL | wxPD_CAN_ABORT | wxPD_AUTO_HIDE );
+
+ m_dvLibName->SetWidth( 280 );
+
+ // Prepare the review list
+ m_listCtrlReview->DeleteAllItems();
+
+ for( std::vector<LIBRARY>::iterator it = m_libraries.begin(); it != m_libraries.end(); ++it )
+ {
+ wxVector<wxVariant> row;
+ LIBRARY::STATUS status = it->GetStatus();
+
+ // Check if the library contents is valid
+ if( status == LIBRARY::NOT_CHECKED && validate )
+ {
+ it->Test();
+ status = it->GetStatus();
+ }
+
+ row.push_back( wxVariant( it->GetDescription() ) );
+
+ switch( it->GetStatus() )
+ {
+ case LIBRARY::NOT_CHECKED:
+ row.push_back( wxVariant( _( "NOT CHECKED" ) ) );
+ break;
+
+ case LIBRARY::OK:
+ row.push_back( wxVariant( _( "OK" ) ) );
+ break;
+
+ case LIBRARY::INVALID:
+ row.push_back( wxVariant( _( "INVALID" ) ) );
+ break;
+ }
+
+ row.push_back( wxVariant( it->GetPluginName() ) );
+
+ m_listCtrlReview->AppendItem( row );
+
+ ++libCount;
+ if( !progressDlg.Update( libCount, wxString::Format( _( "Validating libraries %d/%d" ),
+ libCount, libTotalCount ) ) )
+ validate = false;
+ }
+
+ // The list should never be empty, but who knows?
+ enableNext( m_listCtrlReview->GetItemCount() > 0 );
+
+ wxEndBusyCursor();
+}