26#include <wx/filedlg.h>
36#include <lib_table_lexer.h>
76 wxString* aMRUDirectory,
const wxString& aProjectPath,
77 const std::map<PCB_IO_MGR::PCB_FILE_T, IO_BASE::IO_FILE_DESC>& aSupportedFiles ) :
84 void SetValue(
int aRow,
int aCol,
const wxString &aValue )
override
86 wxCHECK( aRow < (
int)
size(), );
110 wxString
filter =
_(
"Footprint Library Tables" );
115 filter << wxString::Format(
_(
" (%s)|%s" ), wxFileSelectorDefaultWildcardStr,
116 wxFileSelectorDefaultWildcardStr );
124 return wxEmptyString;
131 return wxEmptyString;
163 const wxString& options = row.
Options();
164 wxString
result = options;
165 std::map<std::string, UTF8> choices;
169 pi->GetLibraryOptions( &choices );
190 wxMessageBox(
_(
"Unable to load library table." ) );
202 return wxT(
"(fp_lib_table" );
217 wxString tabTitle = aTitle;
219 if( aTable->IsReadOnly() )
220 tabTitle += wxS(
" " ) +
_(
"(read-only)" );
222 for(
int ii = 2; ii < (int)
m_notebook->GetPageCount(); ++ii )
224 wxString candidate =
m_notebook->GetPageText( ii );
226 if( candidate.EndsWith(
" *" ) )
227 candidate = candidate.Left( candidate.Length() - 2 );
229 if( candidate == tabTitle )
233 for(
int attempts = 0; attempts < 3; ++attempts )
241 AddTable( aTable.get(), tabTitle,
true );
245 for(
int attempts = 0; attempts < 3; ++attempts )
253 wxString projectPath =
m_project->GetProjectPath();
259 if( aTable->
Path().StartsWith( projectPath ) )
267 wxString* lastGlobalLibDir =
nullptr;
271 if( cfg->m_LastFootprintLibDir.IsEmpty() )
274 lastGlobalLibDir = &cfg->m_LastFootprintLibDir;
295 [
this]( wxCommandEvent& event )
303 int prevWidth =
grid->GetColSize( aCol );
305 grid->AutoSizeColumn( aCol,
false );
306 grid->SetColSize( aCol, std::max( prevWidth,
grid->GetColSize( aCol ) ) );
315 if(
grid->GetNumberRows() > 0 )
318 grid->SelectRow( 0 );
340 wxASSERT(
table.has_value() );
347 if( projectTable.has_value() )
348 AddTable( projectTable.value(),
_(
"Project Specific Libraries" ),
false );
382 if( desc.m_IsFile && !desc.m_FileExtensions.empty() )
384 entryStr << wxString::Format( wxS(
" (%s)" ),
JoinExtensions( desc.m_FileExtensions ) );
386 else if( !desc.m_IsFile && !desc.m_ExtensionsInDir.empty() )
388 midPart = wxString::Format(
_(
"folder with %s files" ),
JoinExtensions( desc.m_ExtensionsInDir ) );
389 entryStr << wxString::Format( wxS(
" (%s)" ), midPart );
392 browseMenu->Append( type, entryStr );
437 for(
int page = 0 ; page < (int)
m_notebook->GetPageCount(); ++page )
470 for(
int page = 0 ; page < (int)
m_notebook->GetPageCount(); ++page )
475 [&](
int aRow,
int aCol )
481 grid->MakeCellVisible( aRow, 0 );
482 grid->SetGridCursor( aRow, aCol );
520 if( !
cur_grid()->CommitPendingChanges() )
523 wxArrayInt selectedRows =
cur_grid()->GetSelectedRows();
525 if( selectedRows.empty() &&
cur_grid()->GetGridCursorRow() >= 0 )
526 selectedRows.push_back(
cur_grid()->GetGridCursorRow() );
528 wxArrayInt rowsToMigrate;
534 for(
int row : selectedRows )
539 if( type != kicadType && type != nestedTableType )
540 rowsToMigrate.push_back( row );
543 if( rowsToMigrate.size() <= 0 )
545 wxMessageBox(
_(
"Select one or more rows containing libraries to save as current KiCad format." ) );
550 if( rowsToMigrate.size() == 1 )
552 msg.Printf(
_(
"Save '%s' as current KiCad format and replace entry in table?" ),
557 msg.Printf(
_(
"Save %d libraries as current KiCad format and replace entries in table?" ),
558 (
int) rowsToMigrate.size() );
565 for(
int row : rowsToMigrate )
569 wxFileName legacyLib( resolvedPath );
571 if( !legacyLib.Exists() )
573 msg.Printf(
_(
"Library '%s' not found." ), relPath );
578 wxFileName newLib( resolvedPath );
580 newLib.SetName(
"" );
583 if( newLib.DirExists() )
585 msg.Printf(
_(
"Folder '%s' already exists. Do you want overwrite any existing footprints?" ),
586 newLib.GetFullPath() );
588 switch( wxMessageBox( msg,
_(
"Migrate Library" ), wxYES_NO|wxCANCEL|wxICON_QUESTION,
m_parent ) )
592 case wxCANCEL:
return;
610 newLib.GetFullPath() ) );
624 if( !
cur_grid()->CommitPendingChanges() )
631 if( event.GetEventType() == wxEVT_BUTTON )
653 title =
_(
"Select Library Table" );
667 wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_MULTIPLE );
671 if( dlg.ShowModal() == wxID_CANCEL )
674 dlg.GetPaths( files );
675 *lastDir = dlg.GetDirectory();
679 wxDirDialog dlg(
m_parent, title, *lastDir, wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST | wxDD_MULTIPLE );
681 if( dlg.ShowModal() == wxID_CANCEL )
684 dlg.GetPaths( files );
686 if( !files.IsEmpty() )
688 wxFileName first( files.front() );
689 *lastDir = first.GetPath();
698 bool addDuplicates =
false;
699 bool applyToAll =
false;
700 wxString warning =
_(
"Warning: Duplicate Nicknames" );
701 wxString msg =
_(
"An item nicknamed '%s' already exists." );
702 wxString detailedMsg =
_(
"One of the nicknames will need to be changed." );
704 for(
const wxString& filePath : files )
706 wxFileName fn( filePath );
716 if(
cur_model()->ContainsNickname( nickname ) )
722 _(
"Skip" ),
_(
"Add Anyway" ), &applyToAll ) == wxID_CANCEL;
725 doAdd = addDuplicates;
728 if( doAdd &&
cur_grid()->AppendRows( 1 ) )
730 int last_row =
cur_grid()->GetNumberRows() - 1;
740 if(
m_notebook->GetSelection() == 0 &&
path.Contains( wxT(
"${KIPRJMOD}" ) ) )
741 path = fn.GetFullPath();
747 if( !files.IsEmpty() )
757 wxAuiNotebook* notebook = (wxAuiNotebook*) aEvent.GetEventObject();
758 wxWindow* page = notebook->GetPage( aEvent.GetSelection() );
762 if( panel->GetClosable() )
764 if( !panel->GetCanClose() )
796 if( !
cur_grid()->CommitPendingChanges() )
802 if(
grid->GetNumberRows() > 0 && !
IsOK(
this, wxString::Format(
_(
"This action will reset your global library "
803 "table on disk and cannot be undone." ) ) ) )
808 wxString* lastGlobalLibDir =
nullptr;
812 if( cfg->m_LastFootprintLibDir.IsEmpty() )
815 lastGlobalLibDir = &cfg->m_LastFootprintLibDir;
824 face->PreloadLibraries( &
m_parent->Kiway() );
828 wxGridTableBase*
table =
grid->GetTable();
833 wxASSERT( newTable );
850 m_parent->m_GlobalTableChanged =
true;
854 if(
grid->GetNumberRows() > 0 )
857 grid->SelectRow( 0 );
879 if( !
cur_grid()->CommitPendingChanges() )
887 int firstNestedTable = 1;
891 if( globalTable.has_value() &&
get_model( 0 )->Table() != *globalTable.value() )
893 m_parent->m_GlobalTableChanged =
true;
896 globalTable.value()->
Save().map_error(
899 wxMessageBox(
_(
"Error saving global library table:\n\n" ) + aError.
message,
900 _(
"File Save Error" ), wxOK | wxICON_ERROR );
908 if( projectTable.has_value() &&
get_model( 1 )->Table().Path() == projectTable.value()->Path() )
910 firstNestedTable = 2;
912 if(
get_model( 1 )->Table() != *projectTable.value() )
914 m_parent->m_ProjectTableChanged =
true;
917 projectTable.value()->
Save().map_error(
920 wxMessageBox(
_(
"Error saving project library table:\n\n" ) + aError.
message,
921 _(
"File Save Error" ), wxOK | wxICON_ERROR );
927 for(
int ii = firstNestedTable; ii < (int)
m_notebook->GetPageCount(); ++ii )
944 wxRegEx re(
".*?(\\$\\{(.+?)\\})|(\\$\\((.+?)\\)).*?", wxRE_ADVANCED );
945 wxASSERT( re.IsValid() );
947 std::set< wxString > unique;
952 for(
int page = 0 ; page < (int)
m_notebook->GetPageCount(); ++page )
956 for(
int row = 0; row <
model->GetNumberRows(); ++row )
960 while( re.Matches( uri ) )
962 wxString envvar = re.GetMatch( uri, 2 );
965 if( envvar.IsEmpty() )
966 envvar = re.GetMatch( uri, 4 );
969 unique.insert( envvar );
972 uri.Replace( re.GetMatch( uri, 0 ), wxEmptyString );
985 for(
const wxString& evName : unique )
990 m_path_subs_grid->SetCellValue( row, 0, wxT(
"${" ) + evName + wxT(
"}" ) );
994 wxGetEnv( evName, &evValue );
1029 face->PreloadLibraries( aKiway );
1031 std::string payload =
"";
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
bool m_ProjectTableChanged
void InstallPanel(wxPanel *aPanel, wxAuiNotebook *aNotebook)
bool m_GlobalTableChanged
Class DIALOG_HTML_REPORTER.
WX_HTML_REPORT_BOX * m_Reporter
An options editor in the form of a two column name/value spreadsheet like (table) UI.
Dialog helper object to sit in the inheritance tree between wxDialog and any class written by wxFormB...
void openTable(const LIBRARY_TABLE_ROW &aRow) override
FP_GRID_TRICKS(PANEL_FP_LIB_TABLE *aPanel, WX_GRID *aGrid, std::function< void(wxCommandEvent &)> aAddHandler)
static bool SupportsVisibilityColumn()
wxString getTablePreamble() override
void optionsEditor(int aRow) override
PANEL_FP_LIB_TABLE * m_panel
bool supportsVisibilityColumn() override
This class builds a wxGridTableBase by wrapping an #FP_LIB_TABLE object.
FP_LIB_TABLE_GRID_DATA_MODEL(DIALOG_SHIM *aParent, WX_GRID *aGrid, const LIBRARY_TABLE &aTableToEdit, FOOTPRINT_LIBRARY_ADAPTER *aAdapter, const wxArrayString &aPluginChoices, wxString *aMRUDirectory, const wxString &aProjectPath, const std::map< PCB_IO_MGR::PCB_FILE_T, IO_BASE::IO_FILE_DESC > &aSupportedFiles)
wxString getFileTypes(WX_GRID *aGrid, int aRow) override
void SetValue(int aRow, int aCol, const wxString &aValue) override
const std::map< PCB_IO_MGR::PCB_FILE_T, IO_BASE::IO_FILE_DESC > & m_supportedFpFiles
Add mouse and command handling (such as cut, copy, and paste) to a WX_GRID instance.
WX_GRID * m_grid
I don't own the grid, but he owns me.
void SetTooltipEnable(int aCol, bool aEnable=true)
Enable the tooltip for a column.
void SetKiway(wxWindow *aDest, KIWAY *aKiway)
It is only used for debugging, since "this" is not a wxWindow*.
A minimalistic software bus for communications between various DLLs/DSOs (DSOs) within the same KiCad...
virtual void ExpressMail(FRAME_T aDestination, MAIL_T aCommand, std::string &aPayload, wxWindow *aSource=nullptr, bool aFromOtherThread=false)
Send aPayload to aDestination from aSource.
virtual KIFACE * KiFACE(FACE_T aFaceId, bool doLoad=true)
Return the KIFACE* given a FACE_T.
virtual PROJECT & Prj() const
Return the PROJECT associated with this KIWAY.
static wxString ExpandURI(const wxString &aShortURI, const PROJECT &aProject)
std::optional< LIBRARY_TABLE * > Table(LIBRARY_TABLE_TYPE aType, LIBRARY_TABLE_SCOPE aScope)
Retrieves a given table; creating a new empty project table if a valid project is loaded and the give...
void ApplyLibOverrides(LIBRARY_TABLE &aTable)
Applies stored user overrides (disabled/hidden) to rows of a read-only table.
static bool CreateGlobalTable(LIBRARY_TABLE_TYPE aType, bool aPopulateDefaultLibraries)
void LoadGlobalTables(std::initializer_list< LIBRARY_TABLE_TYPE > aTablesToLoad={})
(Re)loads the global library tables in the given list, or all tables if no list is given
void ProjectChanged()
Notify all adapters that the project has changed.
void SetOptions(const wxString &aOptions)
const wxString & Type() const
static const wxString TABLE_TYPE_NAME
const wxString & URI() const
const wxString & Nickname() const
const wxString & Options() const
LIBRARY_RESULT< void > Save()
static std::map< std::string, UTF8 > ParseOptions(const std::string &aOptionsList)
const wxString & Path() const
static UTF8 FixIllegalChars(const UTF8 &aLibItemName, bool aLib)
Replace illegal LIB_ID item name characters with underscores '_'.
This abstract base class mixes any object derived from #LIB_TABLE into wxGridTableBase so the result ...
virtual LIBRARY_TABLE_ROW & at(size_t aIndex)
int GetNumberRows() override
virtual size_t size() const
void SetChangeCallback(std::function< void()> aCallback)
LIBRARY_TABLE_ROW & At(size_t aIndex)
void SetValue(int aRow, int aCol, const wxString &aValue) override
LIB_TABLE_GRID_DATA_MODEL(DIALOG_SHIM *aParent, WX_GRID *aGrid, const LIBRARY_TABLE &aTableToEdit, LIBRARY_MANAGER_ADAPTER *aAdapter, const wxArrayString &aPluginChoices, wxString *aMRUDirectory, const wxString &aProjectPath)
static void MoveUpHandler(WX_GRID *aGrid)
LIB_TABLE_GRID_TRICKS(WX_GRID *aGrid)
static void DeleteRowHandler(WX_GRID *aGrid)
static void AppendRowHandler(WX_GRID *aGrid, const wxString &aType)
static bool VerifyTable(WX_GRID *aGrid, bool aSupportsVisibilityColumn, std::function< void(int aRow, int aCol)> aErrorHandler)
static void MoveDownHandler(WX_GRID *aGrid)
static void AddTable(wxAuiNotebook *aNotebook, const wxString &aTitle, bool aClosable)
STD_BITMAP_BUTTON * m_move_up_button
WX_GRID * m_path_subs_grid
wxAuiNotebook * m_notebook
STD_BITMAP_BUTTON * m_append_button
STD_BITMAP_BUTTON * m_move_down_button
STD_BITMAP_BUTTON * m_delete_button
SPLIT_BUTTON * m_browseButton
PANEL_FP_LIB_TABLE_BASE(wxWindow *parent, wxWindowID id=wxID_ANY, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxSize(-1,-1), long style=wxTAB_TRAVERSAL, const wxString &name=wxEmptyString)
Dialog to show and edit symbol library tables.
void OpenTable(const std::shared_ptr< LIBRARY_TABLE > &table, const wxString &aTitle)
bool m_suppressNotebookPageEvents
bool verifyTables()
Trim important fields, removes blank row entries, and checks for duplicates.
std::map< PCB_IO_MGR::PCB_FILE_T, IO_BASE::IO_FILE_DESC > m_supportedFpFiles
void onSizeGrid(wxSizeEvent &event) override
void moveUpHandler(wxCommandEvent &event) override
bool TransferDataToWindow() override
WX_GRID * cur_grid() const
void adjustPathSubsGridColumns(int aWidth)
void moveDownHandler(wxCommandEvent &event) override
wxArrayString m_pluginChoices
PANEL_FP_LIB_TABLE(DIALOG_EDIT_LIBRARY_TABLES *aParent, PROJECT *aProject)
wxString m_lastProjectLibDir
void populateEnvironReadOnlyTable()
Populate the readonly environment variable table with names and values by examining all the full_uri ...
~PANEL_FP_LIB_TABLE() override
void deleteRowHandler(wxCommandEvent &event) override
void onNotebookPageCloseRequest(wxAuiNotebookEvent &aEvent)
void populatePluginList()
FP_LIB_TABLE_GRID_DATA_MODEL * get_model(int aPage) const
FP_LIB_TABLE_GRID_DATA_MODEL * cur_model() const
void onReset(wxCommandEvent &event) override
std::vector< std::shared_ptr< LIBRARY_TABLE > > m_nestedTables
void onMigrateLibraries(wxCommandEvent &event) override
void browseLibrariesHandler(wxCommandEvent &event)
void onPageChange(wxAuiNotebookEvent &event) override
bool TransferDataFromWindow() override
void AddTable(LIBRARY_TABLE *table, const wxString &aTitle, bool aClosable)
WX_GRID * get_grid(int aPage) const
void onNotebookPageChangeRequest(wxAuiNotebookEvent &aEvent)
DIALOG_EDIT_LIBRARY_TABLES * m_parent
void appendRowHandler(wxCommandEvent &event) override
wxAuiNotebook * GetNotebook() const
static wxString GetDefaultUserFootprintsPath()
Gets the default path we point users to create projects.
wxString m_LastFootprintLibDir
static PLUGIN_REGISTRY * Instance()
static bool ConvertLibrary(const std::map< std::string, UTF8 > &aOldFileProps, const wxString &aOldFilePath, const wxString &aNewFilePath, REPORTER *aReporter)
Convert a schematic symbol library to the latest KiCad format.
static PCB_FILE_T EnumFromStr(const wxString &aFileType)
Return the PCB_FILE_T from the corresponding plugin type name: "kicad", "legacy", etc.
PCB_FILE_T
The set of file types that the PCB_IO_MGR knows about, and for which there has been a plugin written,...
@ KICAD_SEXP
S-expression Pcbnew file format.
@ PCB_FILE_UNKNOWN
0 is not a legal menu id on Mac
static PCB_IO * FindPlugin(PCB_FILE_T aFileType)
Return a #PLUGIN which the caller can use to import, export, save, or load design documents.
static PCB_FILE_T GuessPluginTypeFromLibPath(const wxString &aLibPath, int aCtl=0)
Return a plugin type given a footprint library's libPath.
static const wxString ShowType(PCB_FILE_T aFileType)
Return a brief name for a plugin given aFileType enum.
virtual ENV_VAR_MAP & GetLocalEnvVariables() const
virtual LIBRARY_MANAGER & GetLibraryManager() const
static FOOTPRINT_LIBRARY_ADAPTER * FootprintLibAdapter(PROJECT *aProject)
Container for project specific data.
void Flush()
Build the HTML messages page.
bool HasMessage() const override
Returns true if any messages were reported.
const wxString ExpandEnvVarSubstitutions(const wxString &aString, const PROJECT *aProject)
Replace any environment variable & text variable references with their values.
wxString JoinExtensions(const std::vector< std::string > &aExts)
Join a list of file extensions for use in a file dialog.
int OKOrCancelDialog(wxWindow *aParent, const wxString &aWarning, const wxString &aMessage, const wxString &aDetailedMessage, const wxString &aOKLabel, const wxString &aCancelLabel, bool *aApplyToAll)
Display a warning dialog with aMessage and returns the user response.
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
This file is part of the common library.
Declaration of the eda_3d_viewer class.
wxString NormalizePath(const wxFileName &aFilePath, const ENV_VAR_MAP *aEnvVars, const wxString &aProjectPath)
Normalize a file path to an environmental variable, if possible.
Helper functions to substitute paths with environmental variables.
Functions related to environment variables, including help functions.
static const std::string FootprintLibraryTableFileName
static const std::string KiCadFootprintLibPathExtension
std::map< wxString, ENV_VAR_ITEM > ENV_VAR_MAP
std::unique_ptr< T > IO_RELEASER
Helper to hold and release an IO_BASE object when exceptions are thrown.
This file contains miscellaneous commonly used macros and functions.
KICOMMON_API wxString GetVersionedEnvVarName(const wxString &aBaseName)
Construct a versioned environment variable based on this KiCad major version.
void InvokePcbLibTableEditor(KIWAY *aKiway, wxWindow *aCaller)
Function InvokePcbLibTableEditor shows the modal DIALOG_FP_LIB_TABLE for purposes of editing the glob...
PGM_BASE & Pgm()
The global program "get" accessor.
#define PROJECT_VAR_NAME
A variable name whose value holds the current project directory.
T * GetAppSettings(const char *aFilename)
std::vector< FAB_LAYER_COLOR > dummy
MODEL3D_FORMAT_TYPE fileType(const char *aFileName)
Container that describes file type info.
bool m_IsFile
Whether the library is a folder or a file.
wxString FileFilter() const
Implement a participant in the KIWAY alchemy.
wxString result
Test unit parsing edge cases and error handling.
Definition of file extensions used in Kicad.