38#include <wx/filedlg.h>
46#include <lib_table_lexer.h>
91 return m_rows.insert( aIterator, aRow );
98 return m_rows.erase( aFirst, aLast );
107 void SetValue(
int aRow,
int aCol,
const wxString& aValue )
override
109 wxCHECK( aRow < (
int)
size(), );
150 wxString result = options;
151 std::map<std::string, UTF8> choices;
156 pi->GetLibraryOptions( &choices );
161 if( options != result )
174 size_t ndx = cb_text.find(
"(design_block_lib_table" );
176 if( ndx != std::string::npos )
182 LIB_TABLE_LEXER lexer( &slr );
188 tmp_tbl.
Parse( &lexer );
202 for(
unsigned i = 0; i < tmp_tbl.
GetCount(); ++i )
206 m_grid->AutoSizeColumns(
false );
213 m_grid->AutoSizeColumns(
false );
222 const wxString& aGlobalTblPath,
224 const wxString& aProjectTblPath,
225 const wxString& aProjectBasePath ) :
227 m_globalTable( aGlobalTable ),
228 m_projectTable( aProjectTable ),
229 m_project( aProject ),
230 m_projectBasePath( aProjectBasePath ),
240 wxArrayString choices;
256 [&](
WX_GRID* aGrid,
int aCol )
258 int prevWidth = aGrid->GetColSize( aCol );
260 aGrid->AutoSizeColumn( aCol,
false );
261 aGrid->SetColSize( aCol, std::max( prevWidth, aGrid->GetColSize( aCol ) ) );
270 aGrid->SetSelectionMode( wxGrid::wxGridSelectRows );
272 wxGridCellAttr* attr =
new wxGridCellAttr;
288 return wxEmptyString;
292 aGrid->SetColAttr(
COL_URI, attr );
294 attr =
new wxGridCellAttr;
295 attr->SetEditor(
new wxGridCellChoiceEditor( choices ) );
296 aGrid->SetColAttr(
COL_TYPE, attr );
298 attr =
new wxGridCellAttr;
299 attr->SetRenderer(
new wxGridCellBoolRenderer() );
316 if( aGrid->GetNumberRows() > 0 )
317 aGrid->SelectRow( 0 );
365 auto joinExts = [](
const std::vector<std::string>& aExts )
369 for(
const std::string& ext : aExts )
371 if( !joined.empty() )
372 joined << wxS(
", " );
374 joined << wxS(
"*." ) << ext;
384 if( desc.m_IsFile && !desc.m_FileExtensions.empty() )
386 entryStr << wxString::Format( wxS(
" (%s)" ), joinExts( desc.m_FileExtensions ) );
388 else if( !desc.m_IsFile && !desc.m_ExtensionsInDir.empty() )
390 wxString midPart = wxString::Format(
_(
"folder with %s files" ), joinExts( desc.m_ExtensionsInDir ) );
392 entryStr << wxString::Format( wxS(
" (%s)" ), midPart );
395 browseMenu->Append( type, entryStr );
457 for(
int r = 0; r < model->GetNumberRows(); )
459 wxString nick = model->GetValue( r,
COL_NICKNAME ).Trim(
false ).Trim();
460 wxString uri = model->GetValue( r,
COL_URI ).Trim(
false ).Trim();
461 unsigned illegalCh = 0;
466 msg =
_(
"A library table row nickname and path cells are empty." );
468 msg =
_(
"A library table row nickname cell is empty." );
470 msg =
_(
"A library table row path cell is empty." );
472 wxWindow* topLevelParent = wxGetTopLevelParent(
this );
474 wxMessageDialog badCellDlg( topLevelParent, msg,
_(
"Invalid Row Definition" ),
475 wxYES_NO | wxCENTER | wxICON_QUESTION | wxYES_DEFAULT );
476 badCellDlg.SetExtendedMessage(
_(
"Empty cells will result in all rows that are "
477 "invalid to be removed from the table." ) );
478 badCellDlg.SetYesNoLabels( wxMessageDialog::ButtonLabel(
_(
"Remove Invalid Cells" ) ),
479 wxMessageDialog::ButtonLabel(
_(
"Cancel Table Update" ) ) );
481 if( badCellDlg.ShowModal() == wxID_NO )
488 model->GetView()->ClearSelection();
489 model->DeleteRows( r, 1 );
493 msg = wxString::Format(
_(
"Illegal character '%c' in nickname '%s'." ), illegalCh, nick );
499 model->GetView()->MakeCellVisible( r, 0 );
500 model->GetView()->SetGridCursor( r, 1 );
502 wxWindow* topLevelParent = wxGetTopLevelParent(
this );
504 wxMessageDialog errdlg( topLevelParent, msg,
_(
"Library Nickname Error" ) );
512 model->SetValue( r,
COL_URI, uri );
528 for(
int r1 = 0; r1 < model->GetNumberRows() - 1; ++r1 )
532 for(
int r2 = r1 + 1; r2 < model->GetNumberRows(); ++r2 )
538 msg = wxString::Format(
_(
"Multiple libraries cannot share the same nickname ('%s')." ),
549 wxWindow* topLevelParent = wxGetTopLevelParent(
this );
551 wxMessageDialog errdlg( topLevelParent, msg,
_(
"Library Nickname Error" ) );
564 for(
unsigned int r = 0; r <
table->GetCount(); ++r )
586 msg.Printf(
_(
"Design block library '%s' failed to load." ), row.
GetNickName() );
588 wxWindow* topLevelParent = wxGetTopLevelParent(
this );
589 wxMessageDialog errdlg( topLevelParent, msg + wxS(
"\n" ) + ioe.
What(),
_(
"Error Loading Library" ) );
611 [&]() -> std::pair<int, int>
634 wxArrayInt selectedRows =
m_cur_grid->GetSelectedRows();
635 wxGridCellCoordsArray cells =
m_cur_grid->GetSelectedCells();
636 wxGridCellCoordsArray blockTopLeft =
m_cur_grid->GetSelectionBlockTopLeft();
637 wxGridCellCoordsArray blockBotRight =
m_cur_grid->GetSelectionBlockBottomRight();
640 for(
unsigned ii = 0; ii < cells.GetCount(); ii++ )
641 selectedRows.Add( cells[ii].GetRow() );
644 if( !blockTopLeft.IsEmpty() && !blockBotRight.IsEmpty() )
646 for(
int i = blockTopLeft[0].GetRow(); i <= blockBotRight[0].GetRow(); ++i )
647 selectedRows.Add( i );
651 if( selectedRows.size() == 0 &&
m_cur_grid->GetGridCursorRow() >= 0 )
652 selectedRows.Add(
m_cur_grid->GetGridCursorRow() );
654 if( selectedRows.size() == 0 )
660 std::sort( selectedRows.begin(), selectedRows.end() );
669 for(
int ii = selectedRows.GetCount() - 1; ii >= 0; ii-- )
671 int row = selectedRows[ii];
673 if( row != last_row )
680 if(
m_cur_grid->GetNumberRows() > 0 && curRow >= 0 )
691 boost::ptr_vector<LIB_TABLE_ROW>::auto_type move_me = tbl->
m_rows.release( tbl->
m_rows.begin() + row );
693 tbl->
m_rows.insert( tbl->
m_rows.begin() + row - 1, move_me.release() );
696 wxGridTableMessage msg( tbl, wxGRIDTABLE_NOTIFY_ROWS_INSERTED, row - 1, 0 );
697 tbl->GetView()->ProcessTableMessage( msg );
708 boost::ptr_vector<LIB_TABLE_ROW>::auto_type move_me = tbl->
m_rows.release( tbl->
m_rows.begin() + row );
710 tbl->
m_rows.insert( tbl->
m_rows.begin() + row + 1, move_me.release() );
713 wxGridTableMessage msg( tbl, wxGRIDTABLE_NOTIFY_ROWS_INSERTED, row, 0 );
714 tbl->GetView()->ProcessTableMessage( msg );
725 wxArrayInt selectedRows =
m_cur_grid->GetSelectedRows();
727 if( selectedRows.empty() &&
m_cur_grid->GetGridCursorRow() >= 0 )
728 selectedRows.push_back(
m_cur_grid->GetGridCursorRow() );
730 wxArrayInt rowsToMigrate;
734 for(
int row : selectedRows )
737 rowsToMigrate.push_back( row );
740 if( rowsToMigrate.size() <= 0 )
742 wxMessageBox( wxString::Format(
_(
"Select one or more rows containing libraries "
743 "to save as current KiCad format." ) ) );
748 if( rowsToMigrate.size() == 1 )
750 msg.Printf(
_(
"Save '%s' as current KiCad format and replace entry in table?" ),
755 msg.Printf(
_(
"Save %d libraries as current KiCad format and replace entries in table?" ),
756 (
int) rowsToMigrate.size() );
763 for(
int row : rowsToMigrate )
768 wxFileName legacyLib( resolvedPath );
770 if( !legacyLib.Exists() )
772 msg.Printf(
_(
"Library '%s' not found." ), relPath );
777 wxFileName newLib( resolvedPath );
779 newLib.SetName(
"" );
782 if( newLib.DirExists() )
784 msg.Printf(
_(
"Folder '%s' already exists. Do you want overwrite any existing design "
786 newLib.GetFullPath() );
788 switch( wxMessageBox( msg,
_(
"Migrate Library" ), wxYES_NO | wxCANCEL | wxICON_QUESTION,
m_parent ) )
792 case wxCANCEL:
return;
800 newLib.GetFullPath() ) )
808 relPath = newLib.GetFullPath();
815 msg.Printf(
_(
"Failed to save design block library file '%s'." ), newLib.GetFullPath() );
831 if( event.GetEventType() == wxEVT_BUTTON )
843 wxLogWarning( wxT(
"File type selection event received but could not find the file type in the table" ) );
860 wxWindow* topLevelParent = wxGetTopLevelParent(
this );
864 wxFileDialog dlg( topLevelParent, title, *lastDir, wxEmptyString, fileDesc.
FileFilter(),
865 wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_MULTIPLE );
867 if( dlg.ShowModal() == wxID_CANCEL )
870 dlg.GetPaths( files );
871 *lastDir = dlg.GetDirectory();
875 wxDirDialog dlg( topLevelParent, title, *lastDir,
876 wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST | wxDD_MULTIPLE );
878 if( dlg.ShowModal() == wxID_CANCEL )
881 dlg.GetPaths( files );
883 if( !files.IsEmpty() )
885 wxFileName first( files.front() );
886 *lastDir = first.GetPath();
895 bool addDuplicates =
false;
896 bool applyToAll =
false;
897 wxString warning =
_(
"Warning: Duplicate Nicknames" );
898 wxString msg =
_(
"A library nicknamed '%s' already exists." );
899 wxString detailedMsg =
_(
"One of the nicknames will need to be changed after "
900 "adding this library." );
902 for(
const wxString& filePath : files )
904 wxFileName fn( filePath );
911 if(
cur_model()->ContainsNickname( nickname ) )
917 wxString::Format( msg, nickname ), detailedMsg,
918 _(
"Skip" ),
_(
"Add Anyway" ), &applyToAll )
922 doAdd = addDuplicates;
927 int last_row =
m_cur_grid->GetNumberRows() - 1;
939 if(
m_pageNdx == 0 &&
path.Contains( wxT(
"${KIPRJMOD}" ) ) )
940 path = fn.GetFullPath();
946 if( !files.IsEmpty() )
948 int new_row =
m_cur_grid->GetNumberRows() - 1;
1006 wxRegEx re(
".*?(\\$\\{(.+?)\\})|(\\$\\((.+?)\\)).*?", wxRE_ADVANCED );
1007 wxASSERT( re.IsValid() );
1009 std::set<wxString> unique;
1019 for(
int row = 0; row < tbl->GetNumberRows(); ++row )
1021 wxString uri = tbl->GetValue( row,
COL_URI );
1023 while( re.Matches( uri ) )
1025 wxString envvar = re.GetMatch( uri, 2 );
1028 if( envvar.IsEmpty() )
1029 envvar = re.GetMatch( uri, 4 );
1032 unique.insert( envvar );
1035 uri.Replace( re.GetMatch( uri, 0 ), wxEmptyString );
1049 for(
const wxString& evName : unique )
1054 m_path_subs_grid->SetCellValue( row, 0, wxT(
"${" ) + evName + wxT(
"}" ) );
1058 wxGetEnv( evName, &evValue );
1083 projectTable =
nullptr;
1087 projectTable, projectTablePath,
1097 globalTable->
Save( globalTablePath );
1101 msg.Printf(
_(
"Error saving global library table:\n\n%s" ), ioe.
What() );
1102 wxMessageBox( msg,
_(
"File Save Error" ), wxOK | wxICON_ERROR );
1110 projectTable->
Save( projectTablePath );
1114 msg.Printf(
_(
"Error saving project-specific library table:\n\n%s" ), ioe.
What() );
1115 wxMessageBox( msg,
_(
"File Save Error" ), wxOK | wxICON_ERROR );
1119 std::string payload =
"";
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
void paste_text(const wxString &cb_text) override
handle specialized clipboard text, with leading "(design_block_lib_table", OR spreadsheet formatted t...
DIALOG_EDIT_LIBRARY_TABLES * m_dialog
void optionsEditor(int aRow) override
DESIGN_BLOCK_GRID_TRICKS(DIALOG_EDIT_LIBRARY_TABLES *aParent, WX_GRID *aGrid)
@ KICAD_SEXP
S-expression KiCad file format.
static const wxString ShowType(DESIGN_BLOCK_FILE_T aFileType)
static DESIGN_BLOCK_FILE_T GuessPluginTypeFromLibPath(const wxString &aLibPath, int aCtl=0)
static DESIGN_BLOCK_FILE_T EnumFromStr(const wxString &aFileType)
static bool ConvertLibrary(std::map< std::string, UTF8 > *aOldFileProps, const wxString &aOldFilePath, const wxString &aNewFilePath)
Convert a design block library to the latest KiCad format.
static DESIGN_BLOCK_IO * FindPlugin(DESIGN_BLOCK_FILE_T aFileType)
This class builds a wxGridTableBase by wrapping an DESIGN_BLOCK_LIB_TABLE object.
LIB_TABLE_ROW * at(size_t aIndex) override
void push_back(LIB_TABLE_ROW *aRow) override
DESIGN_BLOCK_LIB_TABLE_GRID(const DESIGN_BLOCK_LIB_TABLE &aTableToEdit)
LIB_TABLE_ROWS_ITER erase(LIB_TABLE_ROWS_ITER aFirst, LIB_TABLE_ROWS_ITER aLast) override
LIB_TABLE_ROW * makeNewRow() override
void SetValue(int aRow, int aCol, const wxString &aValue) override
LIB_TABLE_ROWS_ITER insert(LIB_TABLE_ROWS_ITER aIterator, LIB_TABLE_ROW *aRow) override
LIB_TABLE_ROWS_ITER begin() override
size_t size() const override
Hold a record identifying a library accessed by the appropriate design block library #PLUGIN object i...
bool Refresh() override
Attempt to reload the library.
static wxString GetGlobalTableFileName()
virtual void Parse(LIB_TABLE_LEXER *aLexer) override
Parse the #LIB_TABLE_LEXER s-expression library table format into the appropriate LIB_TABLE_ROW objec...
static const wxString GlobalPathEnvVariableName()
Return the name of the environment variable used to hold the directory of locally installed "KiCad sp...
static DESIGN_BLOCK_LIB_TABLE & GetGlobalLibTable()
bool m_ProjectTableChanged
void InstallPanel(wxPanel *aPanel)
bool m_GlobalTableChanged
An options editor in the form of a two column name/value spreadsheet like (table) UI.
void SetInitialFocus(wxWindow *aWindow)
Sets the window (usually a wxTextCtrl) that should be focused when the dialog is shown.
Editor for wxGrid cells that adds a file/folder browser to the grid input field.
Add mouse and command handling (such as cut, copy, and paste) to a WX_GRID instance.
virtual void paste_text(const wxString &cb_text)
WX_GRID * m_grid
I don't own the grid, but he owns me.
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
virtual const wxString What() const
A composite of Problem() and Where()
wxString m_lastDesignBlockLibDir
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)
Send aPayload to aDestination from aSource.
virtual PROJECT & Prj() const
Return the PROJECT associated with this KIWAY.
static unsigned FindIllegalLibraryNameChar(const UTF8 &aLibraryName)
Looks for characters that are illegal in library nicknames.
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 c...
void SetValue(int aRow, int aCol, const wxString &aValue) override
bool AppendRows(size_t aNumRows=1) override
int GetNumberRows() override
Hold a record identifying a library accessed by the appropriate plug in object in the LIB_TABLE.
const wxString & GetOptions() const
Return the options string, which may hold a password or anything else needed to instantiate the under...
virtual const wxString GetType() const =0
Return the type of library represented by this row.
void SetParent(LIB_TABLE *aParent)
const wxString & GetNickName() const
const wxString GetFullURI(bool aSubstituted=false) const
Return the full location specifying URI for the LIB, either in original UI form or in environment var...
LIB_TABLE_ROW * clone() const
bool GetIsEnabled() const
void SetOptions(const wxString &aOptions)
Change the library options strings.
static std::map< std::string, UTF8 > * ParseOptions(const std::string &aOptionsList)
Parses aOptionsList and places the result into a #PROPERTIES object which is returned.
LIB_TABLE_ROW & At(unsigned aIndex)
Get the 'n'th LIB_TABLE_ROW object.
void TransferRows(LIB_TABLE_ROWS &aRowsList)
Takes ownership of another list of rows; the original list will be freed.
LIB_TABLE_ROWS m_rows
Owning set of rows.
unsigned GetCount() const
Get the number of rows contained in the table.
void Save(const wxString &aFileName) const
Write this library table to aFileName in s-expression form.
Class PANEL_DESIGN_BLOCK_LIB_TABLE_BASE.
WX_GRID * m_path_subs_grid
STD_BITMAP_BUTTON * m_move_up_button
STD_BITMAP_BUTTON * m_delete_button
wxButton * m_migrate_libs_button
SPLIT_BUTTON * m_browseButton
STD_BITMAP_BUTTON * m_append_button
STD_BITMAP_BUTTON * m_move_down_button
Dialog to show and edit symbol library tables.
void moveUpHandler(wxCommandEvent &event) override
void onMigrateLibraries(wxCommandEvent &event) override
void adjustPathSubsGridColumns(int aWidth)
DESIGN_BLOCK_LIB_TABLE_GRID * project_model() const
bool TransferDataFromWindow() override
void browseLibrariesHandler(wxCommandEvent &event)
void populateEnvironReadOnlyTable()
Populate the readonly environment variable table with names and values by examining all the full_uri ...
DESIGN_BLOCK_LIB_TABLE_GRID * cur_model() const
DESIGN_BLOCK_LIB_TABLE * m_globalTable
std::map< DESIGN_BLOCK_IO_MGR::DESIGN_BLOCK_FILE_T, IO_BASE::IO_FILE_DESC > m_supportedDesignBlockFiles
void moveDownHandler(wxCommandEvent &event) override
PANEL_DESIGN_BLOCK_LIB_TABLE(DIALOG_EDIT_LIBRARY_TABLES *aParent, PROJECT *aProject, DESIGN_BLOCK_LIB_TABLE *aGlobalTable, const wxString &aGlobalTblPath, DESIGN_BLOCK_LIB_TABLE *aProjectTable, const wxString &aProjectTblPath, const wxString &aProjectBasePath)
DIALOG_EDIT_LIBRARY_TABLES * m_parent
void OnUpdateUI(wxUpdateUIEvent &event) override
wxString m_lastProjectLibDir
void appendRowHandler(wxCommandEvent &event) override
wxString m_projectBasePath
DESIGN_BLOCK_LIB_TABLE_GRID * global_model() const
DESIGN_BLOCK_LIB_TABLE * m_projectTable
void populatePluginList()
~PANEL_DESIGN_BLOCK_LIB_TABLE() override
void onSizeGrid(wxSizeEvent &event) override
void deleteRowHandler(wxCommandEvent &event) override
bool verifyTables()
Trim important fields, removes blank row entries, and checks for duplicates.
static wxString GetDefaultUserDesignBlocksPath()
Gets the default path we point users to create projects.
virtual ENV_VAR_MAP & GetLocalEnvVariables() const
Container for project specific data.
virtual const wxString DesignBlockLibTblName() const
Return the path and file name of this projects design block library table.
virtual const wxString GetProjectPath() const
Return the full path of the project.
virtual DESIGN_BLOCK_LIB_TABLE * DesignBlockLibs()
Return the table of design block libraries.
virtual bool IsNullProject() const
Check if this project is a null project (i.e.
Is a LINE_READER that reads from a multiline 8 bit wide std::string.
void OnMoveRowUp(const std::function< void(int row)> &aMover)
void SetTable(wxGridTableBase *table, bool aTakeOwnership=false)
Hide wxGrid's SetTable() method with one which doesn't mess up the grid column widths when setting th...
void OnMoveRowDown(const std::function< void(int row)> &aMover)
void OnAddRow(const std::function< std::pair< int, int >()> &aAdder)
void ClearRows()
wxWidgets recently added an ASSERT which fires if the position is greater than or equal to the number...
bool CommitPendingChanges(bool aQuietMode=false)
Close any open cell edit controls.
const wxString ExpandEnvVarSubstitutions(const wxString &aString, const PROJECT *aProject)
Replace any environment variable & text variable references with their values.
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.
void DisplayError(wxWindow *aParent, const wxString &aText)
Display an error or warning message box with aMessage.
This file is part of the common library.
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 KiCadDesignBlockLibPathExtension
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.
LIB_TABLE_ROWS::iterator LIB_TABLE_ROWS_ITER
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 InvokeEditDesignBlockLibTable(KIWAY *aKiway, wxWindow *aParent)
PGM_BASE & Pgm()
The global program "get" accessor.
#define PROJECT_VAR_NAME
A variable name whose value holds the current project directory.
std::vector< FAB_LAYER_COLOR > dummy
MODEL3D_FORMAT_TYPE fileType(const char *aFileName)
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Container that describes file type info.
bool m_IsFile
Whether the library is a folder or a file.
wxString FileFilter() const
A filename or source description, a problem input line, a line number, a byte offset,...
Definition of file extensions used in Kicad.