25#include <wx/display.h>
26#include <wx/filedlg.h>
27#include <wx/filename.h>
30#include <wx/settings.h>
31#include <wx/stdpaths.h>
81template <
typename MAP>
82static bool isAutofilled(
const MAP& aAutofilled,
const typename MAP::key_type& aKey,
const std::string& aValue )
84 auto it = aAutofilled.find( aKey );
86 return it != aAutofilled.end() && it->second == aValue;
114 return _(
"The server rejected the user name or password." );
116 case FAILURE::UNREACHABLE:
117 return _(
"Could not reach the database server; check that it is running." );
119 case FAILURE::TIMEOUT:
120 return wxString::Format(
_(
"The server did not answer within %d seconds." ), aSource.
timeout );
122 case FAILURE::NO_DSN:
124 return _(
"The connection string names a data source or driver that is not configured." );
126 return wxString::Format(
_(
"There is no ODBC data source named '%s'." ),
From_UTF8( aSource.
dsn ) );
128 case FAILURE::NO_DRIVER:
129 return _(
"The ODBC driver for this data source is not installed." );
131 case FAILURE::UNKNOWN:
135 return _(
"Could not connect to the database." );
150 static const std::vector<AUTOFILL_FIELD> fields = {
151 {
"Value", {
_HKI(
"Value" ) },
true },
152 {
"Datasheet", {
_HKI(
"Datasheet" ),
_HKI(
"data sheet" ) },
false }
161 return std::string(
"field." ) + aFieldName;
169 for(
const wxString& term : aTerms )
171 role.
terms.push_back( term );
173 if( wxString translated = wxGetTranslation( term ); translated != term )
174 role.
terms.push_back( translated );
179 if(
auto it = cfg->m_DatabaseColumnChoices.find( aChoiceId ); it != cfg->m_DatabaseColumnChoices.end() )
191 if( wxString::FromUTF8( field.
name ).IsSameAs( aName,
false ) )
201 const wxString& aDefaultDir ) :
219 { m_cbKeyCol, [](
DATABASE_LIB_TABLE& t ) -> std::string& {
return t.key_col; },
false,
_(
"key" ),
220 "key", {
_HKI(
"id" ),
_HKI(
"key" ) } },
221 { m_cbSymbolsCol, [](
DATABASE_LIB_TABLE& t ) -> std::string& {
return t.symbols_col; },
false,
222 _(
"symbols" ),
"symbols", {
_HKI(
"symbol" ),
_HKI(
"sym" ) } },
223 { m_cbFootprintsCol, [](
DATABASE_LIB_TABLE& t ) -> std::string& {
return t.footprints_col; },
false,
224 _(
"footprints" ),
"footprints", {
_HKI(
"footprint" ),
_HKI(
"fp" ) } },
225 { m_cbPinsCol, [](
DATABASE_LIB_TABLE& t ) -> std::string& {
return t.pins_col; },
true,
_(
"pin map" ),
226 "pins", {
_HKI(
"pin map" ),
_HKI(
"pins" ) } },
227 { m_cbDescriptionCol, [](
DATABASE_LIB_TABLE& t ) -> std::string& {
return t.properties.description; },
228 true,
_(
"description" ),
"description", {
_HKI(
"description" ),
_HKI(
"desc" ) } },
229 { m_cbKeywordsCol, [](
DATABASE_LIB_TABLE& t ) -> std::string& {
return t.properties.keywords; },
true,
230 _(
"keywords" ),
"keywords", {
_HKI(
"keywords" ),
_HKI(
"tags" ) } },
231 { m_cbFpFiltersCol, [](
DATABASE_LIB_TABLE& t ) -> std::string& {
return t.properties.footprint_filters; },
232 true,
_(
"footprint filters" ),
"footprint_filters",
233 {
_HKI(
"footprint filters" ),
_HKI(
"fp filters" ) } },
234 { m_cbExclSimCol, [](
DATABASE_LIB_TABLE& t ) -> std::string& {
return t.properties.exclude_from_sim; },
235 true,
_(
"exclude from simulation" ),
"exclude_from_sim",
236 {
_HKI(
"exclude from simulation" ),
_HKI(
"exclude from sim" ) } },
237 { m_cbExclBomCol, [](
DATABASE_LIB_TABLE& t ) -> std::string& {
return t.properties.exclude_from_bom; },
238 true,
_(
"exclude from BOM" ),
"exclude_from_bom", {
_HKI(
"exclude from BOM" ) } },
239 { m_cbExclBoardCol, [](
DATABASE_LIB_TABLE& t ) -> std::string& {
return t.properties.exclude_from_board; },
240 true,
_(
"exclude from board" ),
"exclude_from_board", {
_HKI(
"exclude from board" ) } }
250 m_settings = std::make_unique<DATABASE_LIB_SETTINGS>( std::string() );
251 m_settings->SetReadOnly(
true );
252 m_settings->ResetToDefaults();
257 fn.Assign( aDblPath );
259 m_path = fn.GetFullPath();
261 isNew = !wxFileExists( m_path );
264 m_canSave = loaded && !m_settings->IsFutureFormat();
269 m_settings->Set(
"source.type", std::string(
"odbc" ) );
273 for( wxWindow* window = aParent; window && !frame; window = window->GetParent() )
279 if( drawFrame && drawFrame->
GetCanvas() )
285 m_previewSizer->Add( m_preview, 1, wxEXPAND | wxALL, 5 );
299 wxGridCellAttr* attr =
new wxGridCellAttr;
300 attr->SetRenderer(
new wxGridCellBoolRenderer() );
301 attr->SetEditor(
new wxGridCellBoolEditor() );
302 attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
303 m_fieldsGrid->SetColAttr( col, attr );
306 m_fieldsGrid->PushEventHandler(
new GRID_TRICKS( m_fieldsGrid ) );
307 m_dataGrid->PushEventHandler(
new GRID_TRICKS( m_dataGrid ) );
310 m_btnTest->SetMinSize( m_btnTest->GetBestSize() );
313 m_stConnectionStatus->SetMinSize( wxSize( FromDIP( 40 ), -1 ) );
314 m_stDsnDriver->SetMinSize( wxSize( FromDIP( 40 ), -1 ) );
315 m_stSymbolExample->SetMinSize( wxSize( FromDIP( 40 ), -1 ) );
317 if( m_unnamed && m_defaultDir.IsEmpty() )
318 m_defaultDir = wxStandardPaths::Get().GetDocumentsDir();
320 m_stCwdHelp->SetLabel( m_unnamed ? wxString::Format(
_(
"${CWD} is replaced by %s (the folder the file will "
323 : wxString::Format(
_(
"${CWD} is replaced by %s" ), fn.GetPath() ) );
326 m_stNoLibraries->Wrap( FromDIP( 160 ) );
330 m_infoBar->ShowMessage(
_(
"This file could not be read and is shown read-only." ), wxICON_ERROR );
332 else if( m_settings->IsFutureFormat() )
334 m_infoBar->ShowMessage(
_(
"This file was written by a newer version of KiCad and is shown read-only." ),
339 m_infoBar->ShowMessage(
_(
"Choose a data source and click Test Connection, then add a library on the "
341 wxICON_INFORMATION );
351 for(
const COLUMN_ROLE& role : m_roles )
355 role.combo->Bind( wxEVT_KILL_FOCUS,
356 [
this]( wxFocusEvent& aEvent )
367 m_fieldsGrid->GetGridColLabelWindow()->Bind( wxEVT_MOTION,
368 [
this]( wxMouseEvent& aEvent )
370 const wxString tips[] = {
371 _(
"Database column the field reads its value from" ),
372 _(
"Name of the symbol field" ),
373 _(
"Show the field on the schematic when the symbol is placed" ),
374 _(
"Show the field as a column in the symbol chooser" ),
375 _(
"Show the field name before its value" ),
376 _(
"Take position and style from the symbol's own field of the same name" )
379 int x = m_fieldsGrid->CalcUnscrolledPosition( aEvent.GetPosition() ).x;
380 int col = m_fieldsGrid->XToCol( x );
382 bool validCol = col >= 0 && col < static_cast<int>( std::size( tips ) );
384 m_fieldsGrid->GetGridColLabelWindow()->SetToolTip( validCol ? tips[col] : wxString() );
392 SetTitle( m_unnamed ?
_(
"New Database Library" )
393 : wxString::Format(
_(
"Database Library Settings (%s)" ), fn.GetFullName() ) );
395 SetupStandardButtons();
398 m_sdbSizerOK->Disable();
401 wxSize fullSize = GetBestSize();
404 for( wxScrolledWindow* page : { m_connectionPage, m_librariesPage } )
406 page->SetMinSize( wxSize( -1, FromDIP( 200 ) ) );
407 page->SetSize( wxSize( page->GetSize().x, FromDIP( 200 ) ) );
410 finishDialogSettings();
413 m_initialSize.IncTo( fullSize );
414 m_connectionPage->FitInside();
415 m_librariesPage->FitInside();
440 bool useConnectionString = !
source.connection_string.empty();
441 bool passwordInFile = !
source.password.empty();
452 m_rbDSN->SetValue( !useConnectionString );
505 std::string password =
source.password;
512 if( !password.empty() && ( !sameLogin || password !=
m_keyringLogin.password ) )
516 DisplayError(
this,
_(
"The password could not be saved in the system keyring, which needs a "
517 "user name and a running keyring service.\n\n"
518 "Check 'Save password in the library file' to keep it there instead." ) );
522 else if( password.empty() && sameLogin && !
m_keyringLogin.password.empty() )
538 source.password = password;
569 std::set<std::string> nicknames;
571 for(
size_t ii = 0; ii <
m_settings->m_Tables.size(); ++ii )
575 wxWindow* focus =
nullptr;
578 if(
table.table.empty() &&
table.key_col.empty() )
580 msg = wxString::Format(
_(
"Library '%s' needs a table and a key column." ),
name );
583 else if(
table.table.empty() )
585 msg = wxString::Format(
_(
"Library '%s' needs a table." ),
name );
588 else if(
table.key_col.empty() )
590 msg = wxString::Format(
_(
"Library '%s' needs a key column." ),
name );
593 else if( !nicknames.insert(
table.name ).second )
595 msg = wxString::Format(
_(
"More than one library is named '%s'." ),
name );
636 wxString
filter =
_(
"KiCad database library files" )
642 wxFileDialog dlg(
this,
_(
"Save Database Library" ), dir,
name + wxS(
"." ) + ext,
filter,
643 wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
647 if( dlg.ShowModal() != wxID_OK )
650 wxFileName fn( dlg.GetPath() );
654 if( fn.GetFullPath() != dlg.GetPath() && fn.FileExists()
655 && !
IsOK(
this, wxString::Format(
_(
"Overwrite '%s'?" ), fn.GetFullPath() ) ) )
660 wxString oldBase =
cwdDir();
661 m_path = fn.GetFullPath();
664 m_settings->Internals()->SetFromString(
"meta.filename", std::string(
m_settings->GetFullFilename().ToUTF8() ) );
665 m_stCwdHelp->SetLabel( wxString::Format(
_(
"${CWD} is replaced by %s" ),
cwdDir() ) );
668 if( oldBase !=
cwdDir() &&
m_settings->m_Source.connection_string.find(
"${CWD}" ) != std::string::npos )
671 showInfo(
_(
"The data source uses ${CWD} and was tested again in the folder you chose. "
672 "Check the result, then click OK to save." ),
673 wxICON_INFORMATION );
700 wxString prompt =
m_unnamed ?
_(
"Save the new database library before closing?" )
701 : wxString::Format(
_(
"Save changes to '%s' before closing?" ),
702 wxFileName(
m_path ).GetFullName() );
733 if( !aEvent.CanVeto() )
774 wxString current =
m_cbDSN->GetValue();
782 m_cbDSN->ChangeValue( current );
794 text =
_(
"Not configured on this computer" );
815 wxExecute( wxS(
"odbcad32.exe" ), wxEXEC_SYNC );
823 bool useDSN =
m_rbDSN->GetValue();
824 wxSizer* sbSource =
m_rbDSN->GetContainingSizer();
826 sbSource->Show(
m_cbDSN->GetContainingSizer(), useDSN );
873 wxString driver = wxString::Format( wxS(
"Driver={%s};" ),
m_choiceDriver->GetStringSelection() );
875 wxRegEx existing( wxS(
"Driver=\\{[^}]*\\};?" ), wxRE_ICASE | wxRE_ADVANCED );
877 if( !existing.Replace( &
text, driver, 1 ) )
913 source.connection_string.clear();
939 if(
source.dsn.empty() &&
source.connection_string.empty() )
946 auto job = std::make_shared<CONNECT_JOB>();
961 job->connected = job->conn->Connect();
964 job->conn->GetTables( job->tables );
972 job->owner->onConnectFinished( job );
986 m_btnTest->SetLabel(
_(
"Test Connection" ) );
996 m_btnTest->SetLabel(
_(
"Test Connection" ) );
998 if( aJob->connected )
1000 m_conn = std::move( aJob->conn );
1001 m_tables = std::move( aJob->tables );
1008 From_UTF8( aJob->conn->GetLastError() ) );
1022 wxArrayString tables;
1035 const wxString& aDetails )
1038 m_stConnectionStatus->SetToolTip( aDetails.IsEmpty() ? aText : aText + wxS(
"\n\n" ) + aDetails );
1057 static const std::vector<std::string>
empty;
1059 if( !
m_conn || aTable.empty() )
1066 it =
m_columns.emplace( aTable, std::vector<std::string>() ).first;
1067 m_conn->GetColumns( aTable, it->second );
1076 wxArrayString names;
1122 control->Enable( lib !=
nullptr );
1126 role.combo->Enable( lib !=
nullptr );
1149 wxArrayString columns;
1155 wxArrayString optionalColumns = columns;
1156 optionalColumns.Insert( wxEmptyString, 0 );
1162 role.combo->Set( role.optional ? optionalColumns : columns );
1163 role.combo->ChangeValue(
From_UTF8( role.value( shown ) ) );
1166 wxGridCellAttr* attr =
new wxGridCellAttr;
1188 std::string value =
TO_UTF8( role.combo->GetValue() );
1191 wxFont font = role.combo->GetFont();
1192 wxFontStyle style = autofilled ? wxFONTSTYLE_ITALIC : wxFONTSTYLE_NORMAL;
1196 wxWindow* focus = wxWindow::FindFocus();
1197 bool typing = focus && ( focus == role.combo || focus->GetParent() == role.combo );
1199 if( font.GetStyle() != style && !typing )
1201 font.SetStyle( style );
1202 role.combo->SetFont( font );
1218 std::erase( lib->
name,
'/' );
1223 role.value( *lib ) =
TO_UTF8( role.combo->GetValue() );
1257 copy.name +=
"-copy";
1320 if( aEvent.GetEventObject() == role.combo )
1396 std::set<std::string> taken;
1397 std::vector<const COLUMN_ROLE*> roles;
1398 std::vector<const AUTOFILL_FIELD*> fields;
1399 std::vector<DB_AUTOFILL::ROLE> requests;
1403 const std::string& value = role.value( *lib );
1408 taken.insert( value );
1412 roles.push_back( &role );
1413 requests.push_back(
autofillRole( role.autofillId, role.terms ) );
1420 requests.back().excluded.insert( column );
1432 fields.push_back( &def );
1439 taken.insert( field.
column );
1442 std::vector<std::string> columns;
1446 if( !taken.contains( column ) )
1447 columns.push_back( column );
1452 for(
size_t ii = 0; ii < roles.size(); ++ii )
1454 roles[ii]->value( *lib ) = chosen[ii];
1458 for(
size_t ii = 0; ii < fields.size(); ++ii )
1461 const std::string& column = chosen[roles.size() + ii];
1464 if( column.empty() )
1502 return aValue ? wxS(
"1" ) : wxS(
"" );
1505 for(
int row = 0; row < static_cast<int>( lib->
fields.size() ); ++row )
1518 for(
int col = 0; col <
m_fieldsGrid->GetNumberCols(); ++col )
1526 int row = aEvent.GetRow();
1528 if( !lib || row < 0 || row >=
static_cast<int>( lib->
fields.size() ) )
1533 wxString value =
m_fieldsGrid->GetCellValue( row, aEvent.GetCol() );
1534 bool checked = value == wxS(
"1" );
1536 switch( aEvent.GetCol() )
1551 if( wxString::FromUTF8( field.
name ).IsSameAs( def.name,
false ) )
1573 [&]() -> std::pair<int, int>
1575 lib->
fields.emplace_back();
1611 lib->fields.erase( lib->fields.begin() + row );
1628 std::set<std::string> mapped;
1631 mapped.insert( role.value( *lib ) );
1634 mapped.insert( field.
column );
1638 if( !mapped.contains( column ) )
1639 lib->
fields.emplace_back( column, column,
false,
false,
false,
false );
1657 if( field.
column == aColumn )
1683 for(
int col = 0; col < static_cast<int>(
m_sampleColumns.size() ); ++col )
1685 for(
int row = 0; row < static_cast<int>(
m_sampleRows.size() ); ++row )
1692 if(
const std::string* value = std::any_cast<std::string>( &it->second ) )
1722 if( symbol.IsEmpty() )
1724 wxString key =
_(
"<key>" );
1732 text = wxString::Format(
_(
"Symbols appear as %s" ), symbol );
1751 m_stDataStatus->SetLabel(
_(
"Choose a library on the Libraries page to see its table." ) );
1761 std::map<std::string, wxString> roles;
1765 const std::string& column = role.value( *lib );
1767 if( !column.empty() )
1768 roles.emplace( column, role.label );
1771 for(
int col = 0; col <
m_dataGrid->GetNumberCols(); ++col )
1776 if(
auto role = roles.find( column ); role != roles.end() )
1777 label += wxS(
"\n" ) + role->second;
1779 label += wxS(
"\n" ) + wxString::Format(
_(
"field '%s'" ), field->name_wx );
1786 : wxString::Format(
_(
"first %zu rows" ),
m_sampleRows.size() );
1788 m_stDataStatus->SetLabel( wxString::Format(
_(
"Library '%s', table '%s', %s. Click a column header to map it." ),
1796 int col = aEvent.GetCol();
1808 int fieldId = wxWindow::NewControlId();
1810 menu.Append( fieldId, mapped ?
_(
"Remove Field Mapping" ) :
_(
"Map as Field" ) );
1811 menu.AppendSeparator();
1813 std::map<int, const COLUMN_ROLE*> roleIds;
1817 int id = wxWindow::NewControlId();
1818 roleIds[id] = &role;
1819 menu.AppendCheckItem(
id, wxString::Format(
_(
"Use for %s" ), role.label ) )
1820 ->Check( role.value( *lib ) == column );
1823 int choice = GetPopupMenuSelectionFromUser( menu );
1825 if(
auto it = roleIds.find( choice ); it != roleIds.end() )
1829 role.
value( *lib ) = role.
value( *lib ) == column ? std::string() : column;
1837 if( choice != fieldId )
1842 std::erase_if( lib->
fields,
1845 return aField.column == column;
1850 lib->
fields.emplace_back( column, column,
false,
false,
false,
false );
1862 int row = aEvent.GetRow();
1878 m_infoBar->ShowMessage( aMessage, aIcon );
1892 int overhead =
m_editPanel->GetSize().x - page->GetClientSize().x;
1896 if( !page->HasScrollbar( wxVERTICAL ) )
1897 overhead += wxSystemSettings::GetMetric( wxSYS_VSCROLL_X, page );
1900 needed = std::max( needed, page->GetSizer()->CalcMin().x + overhead );
1905 const int deficit = needed +
m_splitter->GetSashSize() + previewWidth -
m_splitter->GetClientSize().x;
1909 wxRect display = wxDisplay(
this ).GetClientArea();
1910 wxSize size = GetSize();
1912 SetSize( std::min( size.x + deficit, display.width ), size.y );
1918 std::max(
m_splitter->GetClientSize().x - previewWidth, 0 ) ) );
1921 wxSize
minSize = GetMinSize();
1937 if( !
m_conn || aTable.empty() )
1966 wxArrayString warnings;
1969 warnings.Add(
_(
"Choose a table." ) );
1984 const std::vector<std::string>* columns =
1993 repeats = it->second;
1996 for(
size_t ii = 0; ii <
m_roles.size(); ++ii )
2000 wxArrayString warnings;
2004 const std::string& value = role.
value( *lib );
2009 warnings.Add(
_(
"Choose a key column." ) );
2011 else if( columns && !columns->empty() && !
alg::contains( *columns, value ) )
2013 warnings.Add( wxString::Format(
_(
"Column '%s' is not in table '%s'." ),
From_UTF8( value ),
2017 if( isKey && repeats > 0 )
2019 warnings.Add( wxString::Format(
_(
"'%s' repeats in %zu of the first %zu rows, and parts that share "
2020 "a key hide each other. Choose a column with a unique value per "
2056 wxArrayString messages;
2060 if( issue.field == aField )
2061 messages.Add( issue.message );
2073 [&](
const wxString& aStatus,
const wxString& aDetails = wxEmptyString )
2075 m_tableError = aDetails.IsEmpty() ? wxString() : aStatus + wxS(
"\n" ) + aDetails;
2079 m_preview->SetSymbols( wxEmptyString, {} );
2084 return clear(
_(
"Add a library on the Libraries page to preview it." ) );
2087 return clear(
_(
"Connecting..." ) );
2090 return clear(
_(
"Not connected to a database." ) );
2092 if( lib->
table.empty() )
2093 return clear(
_(
"Choose a table." ) );
2108 size_t count = symbols.size();
2112 status =
_(
"Choose a key column." );
2114 status = wxString::Format(
_(
"Key column '%s' is not in table '%s'." ),
From_UTF8( lib->
key_col ),
2117 status = wxString::Format(
_(
"%zu symbols." ), count );
2119 status = wxString::Format(
_(
"%zu symbols from the first %zu rows." ), count,
m_sampleRows.size() );
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
FAILURE
Why a connection attempt failed, as far as the driver's report tells.
static FAILURE ClassifyFailure(const std::string &aState, const std::string &aMessage)
Classifies a driver error from its SQLSTATE, falling back to its text since drivers disagree on state...
static std::vector< std::string > ListDrivers()
std::string GetLastState() const
std::string GetLastError() const
static std::vector< DATA_SOURCE > ListDataSourceDetails()
Shows symbols that are not in any library table the way the symbol chooser does: a searchable library...
wxStaticText * m_stSymbolExample
STD_BITMAP_BUTTON * m_btnAddField
STD_BITMAP_BUTTON * m_btnMoveFieldDown
STD_BITMAP_BUTTON * m_btnMoveLibraryDown
STD_BITMAP_BUTTON * m_btnDuplicateLibrary
wxStaticText * m_stDsnDriver
wxComboBox * m_cbSymbolsCol
DIALOG_DATABASE_LIB_SETTINGS_BASE(wxWindow *parent, wxWindowID id=wxID_ANY, const wxString &title=_("Database Library Settings"), const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxSize(1200, 760), long style=wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER)
wxScrolledWindow * m_connectionPage
wxScrolledWindow * m_librariesPage
STD_BITMAP_BUTTON * m_btnRemoveLibrary
wxStaticText * m_stDataStatus
STD_BITMAP_BUTTON * m_btnMoveLibraryUp
wxCheckBox * m_cbGloballyUniqueKeys
wxStaticText * m_stCwdHelp
wxCheckBox * m_cbPasswordInFile
wxStaticText * m_stConnectionStatus
wxTextCtrl * m_txtDescription
void m_splitterOnIdle(wxIdleEvent &)
wxSpinCtrl * m_spinCacheSize
wxButton * m_btnAddUnmapped
wxRadioButton * m_rbConnectionString
wxButton * m_btnAddFirstLibrary
STD_BITMAP_BUTTON * m_btnRemoveField
wxStaticText * m_stNoLibraries
wxTextCtrl * m_txtPassword
wxSpinCtrl * m_spinTimeout
STD_BITMAP_BUTTON * m_btnMoveFieldUp
wxChoice * m_choiceDriver
wxTextCtrl * m_txtLibName
wxSplitterWindow * m_splitter
wxTextCtrl * m_txtConnectionString
wxButton * m_btnManageDsn
wxSpinCtrl * m_spinCacheAge
void updateTableWarning()
Marks the table field when it is required and missing or could not be read.
void onConnectFinished(const std::shared_ptr< CONNECT_JOB > &aJob)
void onSplitterIdle(wxIdleEvent &aEvent)
bool m_loading
Set while controls are filled from the settings, so their change events are ignored.
SYMBOL_LIBRARY_ADAPTER * m_libs
int m_currentLibrary
Index into m_settings->m_Tables of the library shown on the Libraries page, or -1.
void updateLibraryListHints()
Shows the empty state of the library list only while it is empty.
std::set< wxComboBox * > m_userRoles
Role combos the user set for the current library, which autofill leaves alone.
std::map< std::string, std::string > m_newChoices
Columns the user chose this session, keyed like EESCHEMA_SETTINGS::m_DatabaseColumnChoices.
std::map< std::string, size_t > m_sampleRepeats
void OnSourceSpinChanged(wxSpinEvent &aEvent) override
wxArrayString previewIssues(SCH_IO_DATABASE::PREVIEW_ISSUE::FIELD aField) const
void markUserRole(const COLUMN_ROLE &aRole, const std::string &aValue)
Records that the user chose aValue for aRole, so autofill leaves it alone.
void autofillColumns()
Maps columns of the chosen table to roles and fields the user has not set.
bool m_canSave
False when the file is unreadable or from a newer KiCad, since saving would lose its contents.
void markDirty()
Restarts the debounce before the preview is rebuilt.
void updateDsnDriver()
Shows which driver the chosen data source uses.
void loadDataSources()
Fills the data source list from the ODBC driver manager, keeping what is typed.
bool TransferDataFromWindow() override
void autofillTable()
Picks the table named like the library while the user has not chosen one.
bool ensureSample(const std::string &aTable)
Reads aTable's first rows unless they are already loaded; false if they could not be read.
std::vector< DATABASE_CONNECTION::ROW > m_sampleRows
void onCancel(wxCommandEvent &aEvent)
DATABASE_SOURCE m_keyringLogin
DSN login and keyring password at load, so an untouched login never rewrites the keyring.
void updateAutofillStyle()
Italicizes the role combos that still hold an autofilled value.
@ STAY
The user wants to keep editing.
@ SAVED
The user chose to save, which ended the dialog with wxID_OK.
@ DISCARD
Nothing to keep, or the user chose to discard it.
bool m_unnamed
True until a new library has been given a file.
void OnSourceChanged(wxCommandEvent &aEvent) override
void updateSourceControls()
void OnDataLabelRightClick(wxGridEvent &aEvent) override
void OnMoveFieldUp(wxCommandEvent &aEvent) override
void OnAddField(wxCommandEvent &aEvent) override
~DIALOG_DATABASE_LIB_SETTINGS() override
DIALOG_DATABASE_LIB_SETTINGS(wxWindow *aParent, const wxString &aDblPath, SYMBOL_LIBRARY_ADAPTER *aLibs, const wxString &aDefaultDir=wxEmptyString)
WX_DEBOUNCED_ACTION m_previewDebounce
Coalesces edits into one preview refresh.
std::vector< COLUMN_ROLE > m_roles
std::vector< std::string > m_sampleColumns
void refreshTables()
Refreshes the table list and everything built on it after the connection changes.
void moveLibrary(int aDelta)
void OnAddLibrary(wxCommandEvent &aEvent) override
void OnAddUnmappedColumns(wxCommandEvent &aEvent) override
void updateSymbolExample()
Shows how the current library's symbols will be named.
void updateDataLabels()
Refreshes only the Data page column labels, which follow mapping edits.
void OnMoveLibraryDown(wxCommandEvent &aEvent) override
bool m_flagMissing
Set once OK found a missing table or key, which is then flagged inline.
void connect()
Starts connecting with the current settings; the table list refreshes when it finishes.
std::map< std::string, std::vector< std::string > > m_columns
void OnInsertDriver(wxCommandEvent &aEvent) override
void OnLibraryChanged(wxCommandEvent &aEvent) override
DB_LIB_PREVIEW_PANEL * m_preview
std::string m_cleanSnapshot
settingsSnapshot() when the dialog opened, to tell whether closing loses anything
void swapFields(DATABASE_LIB_TABLE &aLib, int aRow, int aOther)
wxString m_tableError
Why the table could not be read, shown on the table warning icon.
void OnMoveLibraryUp(wxCommandEvent &aEvent) override
bool chooseSavePath()
Asks where to save a library that has no file yet; false if the user cancelled.
bool TransferDataToWindow() override
void onCloseWindow(wxCloseEvent &aEvent)
const DATABASE_FIELD_MAPPING * fieldForColumn(const std::string &aColumn)
std::map< std::string, std::string > m_autoFields
void OnTestConnection(wxCommandEvent &aEvent) override
std::vector< FIELD_WARNING_ICON * > m_roleIcons
One per entry of m_roles.
SCH_IO_DATABASE::PREVIEW_ISSUES m_previewIssues
Problems found while building the preview symbols, shown on the icons of the fields they came from.
void updateColumnWarnings()
Marks each column field for a missing key, a column the table does not have, keys that repeat in the ...
std::vector< DATABASE_CONNECTION::DATA_SOURCE > m_dataSources
FIELD_WARNING_ICON * m_tableIcon
void OnMoveFieldDown(wxCommandEvent &aEvent) override
std::map< wxComboBox *, std::string > m_autoRoles
CLOSE_ACTION confirmClose()
Asks what to do with unsaved edits before the dialog closes without OK.
void OnSourceTypeChanged(wxCommandEvent &aEvent) override
std::unique_ptr< DATABASE_CONNECTION > m_conn
void OnRemoveLibrary(wxCommandEvent &aEvent) override
void showInfo(const wxString &aMessage, int aIcon)
Replaces the info bar message, which can be dismissed.
void OnTableChanged(wxCommandEvent &aEvent) override
void OnManageDataSources(wxCommandEvent &aEvent) override
std::string m_autoTable
Autofilled values for the current library, which a later autofill may replace.
std::vector< std::string > m_tables
void OnSettingChanged(wxCommandEvent &aEvent) override
std::shared_ptr< CONNECT_JOB > m_connectJob
const std::vector< std::string > & columnsFor(const std::string &aTable)
bool validateLibraries()
Shows the first problem that stops the settings from being saved.
void OnRemoveField(wxCommandEvent &aEvent) override
std::string m_sampleTable
Rows of m_sampleTable shared by the Data page and the preview.
void OnDuplicateLibrary(wxCommandEvent &aEvent) override
void OnLibrarySelected(wxCommandEvent &aEvent) override
DATABASE_LIB_TABLE * currentLibrary()
void OnFieldCellChanged(wxGridEvent &aEvent) override
void cancelConnect()
Abandons a connection attempt in progress, whose result is then discarded.
std::unique_ptr< DATABASE_LIB_SETTINGS > m_settings
void setConnectionStatus(const wxString &aText, bool aError, const wxString &aDetails=wxEmptyString)
Shows a one-line status; the full driver report goes in the tooltip.
void OnDataCellSelected(wxGridEvent &aEvent) override
void OnSettingSpinChanged(wxSpinEvent &aEvent) override
std::string settingsSnapshot()
Every setting as the file would hold it, plus where the password is kept.
void EndDialogShim(int aReturnCode)
A mode agnostic way to close a dialog.
The base frame for deriving all KiCad main window classes.
The base class for create windows for drawing purpose.
virtual EDA_DRAW_PANEL_GAL * GetCanvas() const
Return a pointer to GAL-based canvas of given EDA draw frame.
GAL_TYPE GetBackend() const
Return the type of backend currently used by GAL canvas.
@ GAL_TYPE_OPENGL
OpenGL implementation.
static GAL_TYPE ResolveStoredCanvasType(int aStoredCanvasType)
Convert a stored canvas type setting into a backend that can actually be used.
A warning icon drawn inside the right edge of a field, left of its dropdown button when it has one,...
Add mouse and command handling (such as cut, copy, and paste) to a WX_GRID instance.
static std::unique_ptr< DATABASE_CONNECTION > CreateConnection(const DATABASE_LIB_SETTINGS &aSettings, bool aConnectNow=true, const wxString &aBaseDir=wxEmptyString)
Opens a connection described by aSettings, expanding ${CWD} in a connection string to the directory h...
static wxString SymbolNameForRow(const DATABASE_LIB_TABLE &aTable, bool aGloballyUniqueKeys, const DATABASE_CONNECTION::ROW &aRow, std::string *aRawKey=nullptr)
static std::vector< std::unique_ptr< LIB_SYMBOL > > BuildPreviewSymbols(SYMBOL_LIBRARY_ADAPTER *aLibs, const DATABASE_LIB_TABLE &aTable, bool aGloballyUniqueKeys, const std::vector< DATABASE_CONNECTION::ROW > &aRows, PREVIEW_ISSUES *aIssues)
Builds symbols from already-fetched rows exactly as the library would name and load them,...
RAII class that sets an value at construction and resets it to the original value at destruction.
An interface to the global shared library manager that is schematic-specific and linked to one projec...
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
bool HandleUnsavedChanges(wxWindow *aParent, const wxString &aMessage, const std::function< bool()> &aSaveFunction)
Display a dialog with Save, Cancel and Discard Changes buttons.
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 DefaultDatabaseLibFileName(const wxString &aLibName)
std::unique_ptr< DATABASE_LIB_SETTINGS > LoadDatabaseLibSettingsReadOnly(const wxString &aPath, bool *aLoaded)
Loads a database library settings file without allowing the load itself (e.g.
bool StoreDatabasePassword(const DATABASE_SOURCE &aSource, const std::string &aPassword)
Stores the password for the source's DSN login in the system keyring, or removes the entry when the p...
bool GetDatabasePassword(const DATABASE_SOURCE &aSource, std::string &aPassword, const DATABASE_SECRET_LOOKUP &aLookup)
DSN passwords that are not saved in the (often shared) library file live in the system keyring,...
static DB_AUTOFILL::ROLE autofillRole(const std::string &aChoiceId, const std::vector< wxString > &aTerms)
static DATABASE_FIELD_MAPPING * findField(DATABASE_LIB_TABLE &aLib, const char *aName)
static bool isAutofilled(const MAP &aAutofilled, const typename MAP::key_type &aKey, const std::string &aValue)
True if autofill wrote aValue for aKey and the user has not changed it since.
static constexpr int PREVIEW_DEBOUNCE_MS
Delay after the last edit before the preview is rebuilt.
static void relayoutPage(wxScrolledWindow *aPage)
Re-lays out a scrolled page and refits its scroll area after its contents change size.
static constexpr int PREVIEW_MIN_WIDTH_DIP
Narrowest the preview next to the settings can be before its tree columns are cut off.
static wxString displayName(const DATABASE_LIB_TABLE &aTable)
static constexpr size_t PREVIEW_ROW_LIMIT
Rows read for the Data page and preview; enough to judge a mapping without loading a whole table.
@ FIELD_COL_VISIBLE_ON_ADD
@ FIELD_COL_VISIBLE_IN_CHOOSER
static std::string fieldChoiceId(const char *aFieldName)
static wxString describeFailure(const DATABASE_CONNECTION &aConn, const DATABASE_SOURCE &aSource)
static const std::vector< AUTOFILL_FIELD > & autofillFields()
static bool empty(const wxTextEntryBase *aCtrl)
const int minSize
Push and Shove router track width and via size dialog.
static const std::string DatabaseLibraryFileExtension
Some functions to handle hotkeys in KiCad.
static wxString From_UTF8(const char *cstring)
Convert a UTF8 encoded C string to a wxString for all wxWidgets build modes.
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
std::vector< std::string > AssignColumns(const std::vector< std::string > &aColumns, const std::vector< ROLE > &aRoles)
Chooses a column for each role, best scores first, so no column serves two roles.
void RememberChoice(std::vector< std::string > &aHistory, const std::string &aColumn)
Moves aColumn to the front of a role's history, dropping repeats and the oldest entries.
std::string MatchTable(const std::vector< std::string > &aTables, const std::string &aLibraryName)
std::map< std::string, size_t > RepeatCounts(const std::vector< std::map< std::string, std::any > > &aRows)
Counts, per column, the rows whose value already appeared in an earlier row, with NULL counted as emp...
bool contains(const _Container &__container, _Value __value)
Returns true if the container contains the given value.
PGM_BASE & Pgm()
The global program "get" accessor.
T * GetAppSettings(const char *aFilename)
KIWAY Kiway(KFCTL_STANDALONE)
A symbol field that autofill maps from a like-named column.
std::vector< wxString > terms
A data source configured in the ODBC driver manager.
bool visible_in_chooser
Whether the column is shown by default in the chooser.
std::string column
Database column name.
std::string name
KiCad field name.
void SetName(const std::string &aName)
bool inherit_properties
Whether or not to inherit properties from symbol field.
bool visible_on_add
Whether to show the field when placing the symbol.
bool show_name
Whether or not to show the field name as well as its value.
A database library table will be mapped to a sub-library provided by the database library entry in th...
std::string key_col
Unique key column name (will form part of the LIB_ID)
std::string name
KiCad library nickname (will form part of the LIB_ID)
std::vector< DATABASE_FIELD_MAPPING > fields
std::string table
Database table to pull content from.
std::string connection_string
One mapping to fill, such as the key column or the Value field.
std::vector< std::string > remembered
Columns the user chose before, most recent first.
std::vector< wxString > terms
Words to look for, in English and translated.
One column mapping on the Libraries page: its combo, its setting and its Data page label.
std::string &(* value)(DATABASE_LIB_TABLE &)
const char * autofillId
Key of the remembered column choices for this role.
A problem found while previewing, tagged with the setting that caused it.
PCB_VIA::VIA_PARAMETER_ERROR::FIELD FIELD
thread_pool & GetKiCadThreadPool()
Get a reference to the current thread pool.
wxString AddFileExtListToFilter(const std::vector< std::string > &aExts)
Build the wildcard extension file dialog wildcard filter to add to the base message dialog.
Definition of file extensions used in Kicad.