KiCad PCB EDA Suite
Loading...
Searching...
No Matches
dialog_remote_symbol_config.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 3 of the License, or (at your
9 * option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
21
22#include <common.h>
25#include <pgm_base.h>
28#include <widgets/ui_common.h>
29
30#include <wx/button.h>
31#include <wx/dirdlg.h>
32#include <wx/filename.h>
33#include <wx/intl.h>
34#include <wx/listbox.h>
35#include <wx/msgdlg.h>
36#include <wx/radiobut.h>
37#include <wx/sizer.h>
38#include <wx/stattext.h>
39#include <wx/textctrl.h>
40
41
43 DIALOG_SHIM( aParent, wxID_ANY, _( "Remote Symbol Settings" ), wxDefaultPosition,
44 wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER ),
45 m_providerList( nullptr ),
46 m_providerUrlCtrl( nullptr ),
47 m_providerNameCtrl( nullptr ),
48 m_providerAccountLabel( nullptr ),
49 m_providerAuthLabel( nullptr ),
50 m_addProviderButton( nullptr ),
51 m_removeProviderButton( nullptr ),
52 m_refreshProviderButton( nullptr ),
53 m_signOutProviderButton( nullptr ),
54 m_destinationCtrl( nullptr ),
55 m_prefixCtrl( nullptr ),
56 m_prefixHint( nullptr ),
57 m_projectRadio( nullptr ),
58 m_globalRadio( nullptr ),
59 m_resetButton( nullptr ),
60 m_browseButton( nullptr ),
62{
63 wxBoxSizer* topSizer = new wxBoxSizer( wxVERTICAL );
64
65 wxStaticText* intro = new wxStaticText( this, wxID_ANY,
66 _( "Configure remote symbol providers and where downloaded libraries are stored." ) );
67 intro->Wrap( FromDIP( 460 ) );
68 topSizer->Add( intro, 0, wxALL | wxEXPAND, FromDIP( 10 ) );
69
70 wxStaticBoxSizer* providerSizer = new wxStaticBoxSizer( wxVERTICAL, this, _( "Providers" ) );
71
72 wxBoxSizer* providerTopSizer = new wxBoxSizer( wxHORIZONTAL );
73 m_providerList = new wxListBox( this, wxID_ANY );
74 m_providerList->SetMinSize( FromDIP( wxSize( 280, 150 ) ) );
75 providerTopSizer->Add( m_providerList, 1, wxRIGHT | wxEXPAND, FromDIP( 8 ) );
76
77 wxBoxSizer* providerButtonSizer = new wxBoxSizer( wxVERTICAL );
78 m_addProviderButton = new wxButton( this, wxID_ANY, _( "Add / Update" ) );
79 m_removeProviderButton = new wxButton( this, wxID_ANY, _( "Remove" ) );
80 m_refreshProviderButton = new wxButton( this, wxID_ANY, _( "Refresh Metadata" ) );
81 m_signOutProviderButton = new wxButton( this, wxID_ANY, _( "Sign Out" ) );
82 providerButtonSizer->Add( m_addProviderButton, 0, wxBOTTOM | wxEXPAND, FromDIP( 4 ) );
83 providerButtonSizer->Add( m_removeProviderButton, 0, wxBOTTOM | wxEXPAND, FromDIP( 4 ) );
84 providerButtonSizer->Add( m_refreshProviderButton, 0, wxBOTTOM | wxEXPAND, FromDIP( 4 ) );
85 providerButtonSizer->Add( m_signOutProviderButton, 0, wxEXPAND );
86 providerTopSizer->Add( providerButtonSizer, 0, wxEXPAND );
87 providerSizer->Add( providerTopSizer, 0, wxALL | wxEXPAND, FromDIP( 8 ) );
88
89 wxFlexGridSizer* providerGrid = new wxFlexGridSizer( 2, FromDIP( 6 ), FromDIP( 6 ) );
90 providerGrid->AddGrowableCol( 1, 1 );
91 providerGrid->Add( new wxStaticText( this, wxID_ANY, _( "Metadata URL:" ) ),
92 0, wxALIGN_CENTER_VERTICAL );
93 m_providerUrlCtrl = new wxTextCtrl( this, wxID_ANY );
94 providerGrid->Add( m_providerUrlCtrl, 1, wxEXPAND );
95 providerGrid->Add( new wxStaticText( this, wxID_ANY, _( "Display name:" ) ),
96 0, wxALIGN_CENTER_VERTICAL );
97 m_providerNameCtrl = new wxTextCtrl( this, wxID_ANY );
98 providerGrid->Add( m_providerNameCtrl, 1, wxEXPAND );
99 providerGrid->Add( new wxStaticText( this, wxID_ANY, _( "Last account:" ) ),
100 0, wxALIGN_CENTER_VERTICAL );
101 m_providerAccountLabel = new wxStaticText( this, wxID_ANY, _( "Not signed in" ) );
102 providerGrid->Add( m_providerAccountLabel, 1, wxEXPAND );
103 providerGrid->Add( new wxStaticText( this, wxID_ANY, _( "Auth status:" ) ),
104 0, wxALIGN_CENTER_VERTICAL );
105 m_providerAuthLabel = new wxStaticText( this, wxID_ANY, _( "Not configured" ) );
106 providerGrid->Add( m_providerAuthLabel, 1, wxEXPAND );
107 providerSizer->Add( providerGrid, 0, wxLEFT | wxRIGHT | wxBOTTOM | wxEXPAND, FromDIP( 8 ) );
108
109 topSizer->Add( providerSizer, 0, wxLEFT | wxRIGHT | wxBOTTOM | wxEXPAND, FromDIP( 10 ) );
110
111 wxFlexGridSizer* gridSizer = new wxFlexGridSizer( 2, FromDIP( 6 ), FromDIP( 6 ) );
112 gridSizer->AddGrowableCol( 1, 1 );
113
114 gridSizer->Add( new wxStaticText( this, wxID_ANY, _( "Destination directory:" ) ),
115 0, wxALIGN_CENTER_VERTICAL );
116
117 wxBoxSizer* destSizer = new wxBoxSizer( wxHORIZONTAL );
118 m_destinationCtrl = new wxTextCtrl( this, wxID_ANY );
119 m_destinationCtrl->SetMinSize( FromDIP( wxSize( 320, -1 ) ) );
120 m_destinationCtrl->SetToolTip( _(
121 "Directory where downloaded symbol, footprint, and 3D model data will be written." ) );
122 destSizer->Add( m_destinationCtrl, 1, wxALIGN_CENTER_VERTICAL );
123
124 m_browseButton = new wxButton( this, wxID_ANY, _( "Browse..." ) );
125 destSizer->Add( m_browseButton, 0, wxLEFT, FromDIP( 4 ) );
126 gridSizer->Add( destSizer, 1, wxEXPAND );
127
128 gridSizer->Add( new wxStaticText( this, wxID_ANY, _( "Library prefix:" ) ),
129 0, wxALIGN_CENTER_VERTICAL );
130 m_prefixCtrl = new wxTextCtrl( this, wxID_ANY );
131 m_prefixCtrl->SetToolTip( _( "Prefix that will be applied to the generated libraries." ) );
132 gridSizer->Add( m_prefixCtrl, 0, wxEXPAND );
133
134 gridSizer->AddSpacer( 0 );
135 m_prefixHint = new wxStaticText( this, wxID_ANY, wxString() );
136 m_prefixHint->SetFont( KIUI::GetSmallInfoFont( this ).Italic() );
137 gridSizer->Add( m_prefixHint, 0, wxEXPAND );
138
139 gridSizer->Add( new wxStaticText( this, wxID_ANY, _( "Add libraries to:" ) ),
140 0, wxALIGN_CENTER_VERTICAL );
141
142 wxBoxSizer* radioSizer = new wxBoxSizer( wxHORIZONTAL );
143 m_projectRadio = new wxRadioButton( this, wxID_ANY, _( "Project library table" ),
144 wxDefaultPosition, wxDefaultSize, wxRB_GROUP );
145 m_projectRadio->SetToolTip(
146 _( "Adds the generated libraries to the project's library tables." ) );
147 radioSizer->Add( m_projectRadio, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, FromDIP( 12 ) );
148
149 m_globalRadio = new wxRadioButton( this, wxID_ANY, _( "Global library table" ) );
150 m_globalRadio->SetToolTip(
151 _( "Adds the generated libraries to the global library tables." ) );
152 radioSizer->Add( m_globalRadio, 0, wxALIGN_CENTER_VERTICAL );
153
154 gridSizer->Add( radioSizer, 0, wxEXPAND );
155
156 topSizer->Add( gridSizer, 0, wxALL | wxEXPAND, FromDIP( 10 ) );
157
158 m_resetButton = new wxButton( this, wxID_ANY, _( "Reset to Defaults" ) );
159 m_resetButton->SetToolTip( _( "Restore the default destination and prefix." ) );
160 topSizer->Add( m_resetButton, 0, wxLEFT | wxBOTTOM, FromDIP( 10 ) );
161
162 wxStdDialogButtonSizer* buttonSizer = CreateStdDialogButtonSizer( wxOK | wxCANCEL );
163 topSizer->Add( buttonSizer, 0, wxALL | wxEXPAND, FromDIP( 10 ) );
164
165 SetSizer( topSizer );
166 topSizer->Fit( this );
167
170
172
179 this );
180 m_refreshProviderButton->Bind( wxEVT_BUTTON,
182 m_signOutProviderButton->Bind( wxEVT_BUTTON,
184}
185
186
188{
189 if( m_settings )
190 applyRemoteSettings( m_settings->m_RemoteSymbol );
191 else
193
194 return true;
195}
196
197
199{
200 wxString destination = m_destinationCtrl->GetValue();
201 wxString prefix = m_prefixCtrl->GetValue();
202
203 destination.Trim( true ).Trim( false );
204 prefix.Trim( true ).Trim( false );
205
206 if( destination.IsEmpty() )
207 {
208 wxMessageBox( _( "Please choose a destination directory." ), GetTitle(),
209 wxOK | wxICON_WARNING, this );
210 m_destinationCtrl->SetFocus();
211 return false;
212 }
213
214 if( prefix.IsEmpty() )
215 {
216 wxMessageBox( _( "Please enter a library prefix." ), GetTitle(), wxOK | wxICON_WARNING,
217 this );
218 m_prefixCtrl->SetFocus();
219 return false;
220 }
221
222 if( !m_settings )
224
225 if( !m_settings )
226 return true;
227
229
230 m_remoteSettings.destination_dir = destination;
231 m_remoteSettings.library_prefix = prefix;
232 m_remoteSettings.add_to_global_table = m_globalRadio->GetValue();
233 m_settings->m_RemoteSymbol = m_remoteSettings;
234 return true;
235}
236
237
239{
240 wxUnusedVar( aEvent );
241
242 wxString initialPath = ExpandEnvVarSubstitutions( m_destinationCtrl->GetValue(), &Prj() );
243
244 if( initialPath.IsEmpty() )
245 {
246 if( Prj().IsNullProject() )
247 initialPath = KIPLATFORM::ENV::GetDocumentsPath();
248 else
249 initialPath = Prj().GetProjectPath();
250 }
251
252 wxDirDialog dlg( this, _( "Select Destination Directory" ), initialPath );
253
254 if( dlg.ShowModal() != wxID_OK )
255 return;
256
257 wxString path = dlg.GetPath();
258
259 if( !Prj().IsNullProject() )
260 {
261 wxString projectRoot = Prj().GetProjectPath();
262 wxFileName selectedDir = wxFileName::DirName( path );
263
264 if( selectedDir.MakeRelativeTo( projectRoot ) )
265 {
266 wxString relative = selectedDir.GetFullPath();
267
268 if( relative.IsEmpty() || relative == wxS( "." ) )
269 path = wxS( "${KIPRJMOD}" );
270 else
271 path = wxString::Format( wxS( "${KIPRJMOD}/%s" ), relative );
272 }
273 }
274
275 path.Replace( wxS( "\\" ), wxS( "/" ) );
276 m_destinationCtrl->ChangeValue( path );
277}
278
279
281{
282 wxUnusedVar( aEvent );
284}
285
286
288{
289 wxUnusedVar( aEvent );
291}
292
293
295{
296 wxUnusedVar( aEvent );
299}
300
301
302void DIALOG_REMOTE_SYMBOL_CONFIG::onAddProvider( wxCommandEvent& aEvent )
303{
304 wxUnusedVar( aEvent );
305
306 wxString url = m_providerUrlCtrl->GetValue();
307 wxString name = m_providerNameCtrl->GetValue();
308 url.Trim( true ).Trim( false );
309 name.Trim( true ).Trim( false );
310
311 if( url.IsEmpty() )
312 {
313 wxMessageBox( _( "Enter a provider metadata URL first." ), GetTitle(),
314 wxOK | wxICON_WARNING, this );
315 m_providerUrlCtrl->SetFocus();
316 return;
317 }
318
319 REMOTE_PROVIDER_ENTRY& provider = m_remoteSettings.UpsertProvider( url );
320 provider.metadata_url = url;
321 provider.display_name_override = name;
322
323 if( provider.last_auth_status.IsEmpty() )
324 provider.last_auth_status = wxS( "signed_out" );
325
326 m_remoteSettings.last_used_provider_id = provider.provider_id;
328
329 for( size_t ii = 0; ii < m_remoteSettings.providers.size(); ++ii )
330 {
331 if( m_remoteSettings.providers[ii].provider_id == provider.provider_id )
332 {
333 m_providerList->SetSelection( static_cast<int>( ii ) );
334 break;
335 }
336 }
337
340}
341
342
344{
345 wxUnusedVar( aEvent );
346
347 const int selection = m_providerList->GetSelection();
348
349 if( selection == wxNOT_FOUND )
350 return;
351
352 const wxString removedId = m_remoteSettings.providers[selection].provider_id;
353 m_remoteSettings.providers.erase( m_remoteSettings.providers.begin() + selection );
354
355 if( m_remoteSettings.last_used_provider_id == removedId )
356 m_remoteSettings.last_used_provider_id.clear();
357
359}
360
361
363{
364 wxUnusedVar( aEvent );
365
366 const int selection = m_providerList->GetSelection();
367
368 if( selection == wxNOT_FOUND )
369 return;
370
374
375 if( !client.DiscoverProvider( m_remoteSettings.providers[selection].metadata_url, metadata, error ) )
376 {
377 wxMessageBox( error.message, GetTitle(), wxOK | wxICON_ERROR, this );
378 return;
379 }
380
381 if( m_remoteSettings.providers[selection].display_name_override.IsEmpty() )
382 m_providerNameCtrl->ChangeValue( metadata.provider_name );
383
384 wxMessageBox( _( "Provider metadata refreshed." ), GetTitle(), wxOK | wxICON_INFORMATION, this );
385}
386
387
389{
390 wxUnusedVar( aEvent );
391
392 const int selection = m_providerList->GetSelection();
393
394 if( selection == wxNOT_FOUND )
395 return;
396
397 SECURE_TOKEN_STORE tokenStore;
398 REMOTE_PROVIDER_ENTRY& provider = m_remoteSettings.providers[selection];
399 tokenStore.DeleteTokens( provider.provider_id, wxS( "default" ) );
400 provider.last_account_label.clear();
401 provider.last_auth_status = wxS( "signed_out" );
403}
404
405
407{
408 m_remoteSettings = aConfig;
409 m_destinationCtrl->ChangeValue( aConfig.destination_dir );
410 m_prefixCtrl->ChangeValue( aConfig.library_prefix );
411
412 if( aConfig.add_to_global_table )
413 m_globalRadio->SetValue( true );
414 else
415 m_projectRadio->SetValue( true );
416
419}
420
421
423{
424 m_providerList->Clear();
425
426 for( const REMOTE_PROVIDER_ENTRY& provider : m_remoteSettings.providers )
427 {
428 wxString label = provider.display_name_override.IsEmpty()
429 ? provider.metadata_url
430 : wxString::Format( wxS( "%s [%s]" ),
431 provider.display_name_override,
432 provider.metadata_url );
433
434 m_providerList->Append( label );
435 }
436
437 if( !m_remoteSettings.last_used_provider_id.IsEmpty() )
438 {
439 for( size_t ii = 0; ii < m_remoteSettings.providers.size(); ++ii )
440 {
441 if( m_remoteSettings.providers[ii].provider_id == m_remoteSettings.last_used_provider_id )
442 {
443 m_providerList->SetSelection( static_cast<int>( ii ) );
444 break;
445 }
446 }
447 }
448
451}
452
453
455{
456 const int selection = m_providerList->GetSelection();
457
458 if( selection == wxNOT_FOUND )
459 {
460 m_providerUrlCtrl->ChangeValue( wxEmptyString );
461 m_providerNameCtrl->ChangeValue( wxEmptyString );
462 m_providerAccountLabel->SetLabel( _( "Not signed in" ) );
463 m_providerAuthLabel->SetLabel( _( "Not configured" ) );
464 return;
465 }
466
467 const REMOTE_PROVIDER_ENTRY& provider = m_remoteSettings.providers[selection];
468 m_providerUrlCtrl->ChangeValue( provider.metadata_url );
469 m_providerNameCtrl->ChangeValue( provider.display_name_override );
470 m_providerAccountLabel->SetLabel( provider.last_account_label.IsEmpty()
471 ? _( "Not signed in" )
472 : provider.last_account_label );
473 m_providerAuthLabel->SetLabel( provider.last_auth_status.IsEmpty()
474 ? _( "Unknown" )
475 : provider.last_auth_status );
476}
477
478
480{
481 const bool hasSelection = m_providerList->GetSelection() != wxNOT_FOUND;
482 m_removeProviderButton->Enable( hasSelection );
483 m_refreshProviderButton->Enable( hasSelection );
484 m_signOutProviderButton->Enable( hasSelection );
485}
486
487
489{
490 const int selection = m_providerList->GetSelection();
491
492 if( selection == wxNOT_FOUND || selection >= static_cast<int>( m_remoteSettings.providers.size() ) )
493 return;
494
495 REMOTE_PROVIDER_ENTRY& provider = m_remoteSettings.providers[selection];
496 wxString url = m_providerUrlCtrl->GetValue();
497 wxString name = m_providerNameCtrl->GetValue();
498 url.Trim( true ).Trim( false );
499 name.Trim( true ).Trim( false );
500
501 if( url.IsEmpty() )
502 return;
503
504 provider.metadata_url = url;
505 provider.display_name_override = name;
506
507 if( provider.provider_id.IsEmpty() )
509}
510
511
513{
514 const wxString prefix = m_prefixCtrl->GetValue();
515
516 if( prefix.IsEmpty() )
517 {
518 m_prefixHint->SetLabel(
519 _( "Library names will be created with suffixes such as _symbols, _fp, and _3d." ) );
520 }
521 else
522 {
523 m_prefixHint->SetLabel( wxString::Format(
524 _( "Will create libraries like %1$s_symbols, %1$s_fp, %1$s_3d, etc." ), prefix ) );
525 }
526
527 m_prefixHint->Wrap( FromDIP( 360 ) );
528}
const char * name
void applyRemoteSettings(const REMOTE_PROVIDER_SETTINGS &aConfig)
void onSignOutProvider(wxCommandEvent &aEvent)
void onAddProvider(wxCommandEvent &aEvent)
REMOTE_PROVIDER_SETTINGS m_remoteSettings
void onResetDefaults(wxCommandEvent &aEvent)
void onRefreshProvider(wxCommandEvent &aEvent)
void onProviderSelected(wxCommandEvent &aEvent)
void onBrowseDestination(wxCommandEvent &aEvent)
void onRemoveProvider(wxCommandEvent &aEvent)
void onPrefixChanged(wxCommandEvent &aEvent)
void SetInitialFocus(wxWindow *aWindow)
Sets the window (usually a wxTextCtrl) that should be focused when the dialog is shown.
Definition dialog_shim.h:82
void SetupStandardButtons(std::map< int, wxString > aLabels={})
void finishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
DIALOG_SHIM(wxWindow *aParent, wxWindowID id, const wxString &title, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize, long style=wxDEFAULT_FRAME_STYLE|wxRESIZE_BORDER, const wxString &name=wxDialogNameStr)
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
virtual const wxString GetProjectPath() const
Return the full path of the project.
Definition project.cpp:177
bool DiscoverProvider(const wxString &aProviderUrl, REMOTE_PROVIDER_METADATA &aMetadata, REMOTE_PROVIDER_ERROR &aError) const
bool DeleteTokens(const wxString &aProviderId, const wxString &aAccountId)
const wxString ExpandEnvVarSubstitutions(const wxString &aString, const PROJECT *aProject)
Replace any environment variable & text variable references with their values.
Definition common.cpp:558
The common library.
#define _(s)
wxString GetDocumentsPath()
Retrieves the operating system specific path for a user's documents.
KICOMMON_API wxFont GetSmallInfoFont(wxWindow *aWindow)
see class PGM_BASE
T * GetAppSettings(const char *aFilename)
wxString provider_id
wxString last_account_label
wxString last_auth_status
wxString display_name_override
wxString metadata_url
static wxString CreateProviderId(const wxString &aMetadataUrl)
std::string path
Functions to provide common constants and other functions to assist in making a consistent UI.