Browse Source

CHANGED: retire the select-lib-table dialogs.

We now allow the user to specify which in the
New Library dialog.

Also retires the "Export power symbols too" dialog.

Also gives a bunch of file and library dialogs
more explicit titles.

Also removes separate code-paths for Export to
Library and Export to New Library.  The regular
code path has a "New Library..." button now.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/16323
pull/18/head
Jeff Young 3 months ago
parent
commit
55a36c1ce7
  1. 4
      common/dialogs/dialog_page_settings.cpp
  2. 24
      common/dialogs/eda_list_dialog.cpp
  3. 7
      common/dialogs/eda_list_dialog_base.cpp
  4. 597
      common/dialogs/eda_list_dialog_base.fbp
  5. 4
      common/dialogs/eda_list_dialog_base.h
  6. 37
      common/eda_draw_frame.cpp
  7. 2
      common/tool/design_block_control.cpp
  8. 135
      common/widgets/design_block_pane.cpp
  9. 24
      common/widgets/design_block_pane.h
  10. 4
      common/widgets/grid_text_button_helpers.cpp
  11. 4
      eeschema/dialogs/dialog_sim_model.cpp
  12. 13
      eeschema/menubar.cpp
  13. 191
      eeschema/sch_base_frame.cpp
  14. 20
      eeschema/sch_base_frame.h
  15. 37
      eeschema/symbol_editor/symbol_edit_frame.cpp
  16. 82
      eeschema/symbol_editor/symbol_editor.cpp
  17. 9
      eeschema/symbol_editor/symbol_editor_import_export.cpp
  18. 12
      eeschema/tools/sch_actions.cpp
  19. 1
      eeschema/tools/sch_actions.h
  20. 74
      eeschema/tools/sch_editor_control.cpp
  21. 19
      eeschema/widgets/symbol_library_save_as_filedlg_hook.h
  22. 9
      include/eda_draw_frame.h
  23. 14
      include/eda_list_dialog.h
  24. 11
      include/pcb_base_frame.h
  25. 1
      include/project.h
  26. 13
      include/widgets/filedlg_hook_embed_file.h
  27. 60
      include/widgets/filedlg_hook_new_library.h
  28. 3
      pcbnew/files.cpp
  29. 385
      pcbnew/footprint_libraries_utils.cpp
  30. 2
      pcbnew/load_select_footprint.cpp
  31. 3
      pcbnew/menubar_pcb_editor.cpp
  32. 40
      pcbnew/pcb_base_edit_frame.h
  33. 8
      pcbnew/tools/board_editor_control.cpp
  34. 1
      pcbnew/tools/board_editor_control.h
  35. 12
      pcbnew/tools/pcb_actions.cpp
  36. 1
      pcbnew/tools/pcb_actions.h
  37. 8
      pcbnew/tools/pcb_control.cpp

4
common/dialogs/dialog_page_settings.cpp

@ -40,7 +40,7 @@
#include <drawing_sheet/ds_painter.h>
#include <string_utils.h>
#include <widgets/std_bitmap_button.h>
#include <widgets/filedlg_open_embed_file.h>
#include <widgets/filedlg_hook_embed_file.h>
#include <wx/valgen.h>
#include <wx/tokenzr.h>
#include <wx/filedlg.h>
@ -799,7 +799,7 @@ void DIALOG_PAGES_SETTINGS::OnWksFileSelection( wxCommandEvent& event )
}
// Display a file picker dialog
FILEDLG_OPEN_EMBED_FILE customize;
FILEDLG_HOOK_EMBED_FILE customize;
wxFileDialog fileDialog( this, _( "Drawing Sheet File" ), path, name,
FILEEXT::DrawingSheetFileWildcard(),
wxFD_DEFAULT_STYLE | wxFD_FILE_MUST_EXIST );

24
common/dialogs/eda_list_dialog.cpp

@ -27,6 +27,7 @@
#include <eda_draw_frame.h>
#include <string_utils.h>
#include <macros.h>
#include <wx/checkbox.h>
#include "lib_tree_model_adapter.h"
// wxWidgets spends *far* too long calculating column widths (most of it, believe it or
@ -40,7 +41,8 @@ static int DEFAULT_COL_WIDTHS[] = { 200, 300 };
EDA_LIST_DIALOG::EDA_LIST_DIALOG( wxWindow* aParent, const wxString& aTitle,
const wxArrayString& aItemHeaders,
const std::vector<wxArrayString>& aItemList,
const wxString& aPreselectText, bool aSortList ) :
const wxString& aPreselectText, bool aSortList,
const std::vector<std::pair<wxString, bool*>>& aExtraCheckboxes ) :
EDA_LIST_DIALOG_BASE( aParent, wxID_ANY, aTitle ),
m_sortList( aSortList )
{
@ -61,6 +63,19 @@ EDA_LIST_DIALOG::EDA_LIST_DIALOG( wxWindow* aParent, const wxString& aTitle,
// columns, different column names, and column widths.
m_hash_key = TO_UTF8( aTitle );
if( !aExtraCheckboxes.empty() )
{
m_ExtrasSizer->AddSpacer( 5 );
for( const auto& [label, valuePtr] : aExtraCheckboxes )
{
wxCheckBox* cb = new wxCheckBox( this, wxID_ANY, label );
cb->SetValue( *valuePtr );
m_ExtrasSizer->Add( cb, 0, wxBOTTOM, 5 );
m_extraCheckboxMap[cb] = valuePtr;
}
}
SetupStandardButtons();
Layout();
@ -209,6 +224,13 @@ wxString EDA_LIST_DIALOG::GetTextSelection( int aColumn )
}
void EDA_LIST_DIALOG::GetExtraCheckboxValues()
{
for( const auto& [checkbox, valuePtr] : m_extraCheckboxMap )
*valuePtr = checkbox->GetValue();
}
void EDA_LIST_DIALOG::Append( const wxArrayString& itemList )
{
long itemIndex = m_listBox->InsertItem( m_listBox->GetItemCount(), itemList[0] );

7
common/dialogs/eda_list_dialog_base.cpp

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b)
// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6)
// http://www.wxformbuilder.org/
//
// PLEASE DO *NOT* EDIT THIS FILE!
@ -31,6 +31,11 @@ EDA_LIST_DIALOG_BASE::EDA_LIST_DIALOG_BASE( wxWindow* parent, wxWindowID id, con
m_filterBox = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
bMargins->Add( m_filterBox, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 );
m_ExtrasSizer = new wxBoxSizer( wxVERTICAL );
bMargins->Add( m_ExtrasSizer, 0, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 );
bSizerMain->Add( bMargins, 1, wxEXPAND|wxRIGHT|wxLEFT, 5 );

597
common/dialogs/eda_list_dialog_base.fbp

@ -1,297 +1,314 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<wxFormBuilder_Project>
<FileVersion major="1" minor="16" />
<object class="Project" expanded="1">
<property name="class_decoration"></property>
<property name="code_generation">C++</property>
<property name="disconnect_events">1</property>
<property name="disconnect_mode">source_name</property>
<property name="disconnect_php_events">0</property>
<property name="disconnect_python_events">0</property>
<property name="embedded_files_path">res</property>
<property name="encoding">UTF-8</property>
<property name="event_generation">connect</property>
<property name="file">eda_list_dialog_base</property>
<property name="first_id">1000</property>
<property name="help_provider">none</property>
<property name="image_path_wrapper_function_name"></property>
<property name="indent_with_spaces"></property>
<property name="internationalize">1</property>
<property name="name">eda_list_dialog_base</property>
<property name="namespace"></property>
<property name="path">.</property>
<property name="precompiled_header"></property>
<property name="relative_path">1</property>
<property name="skip_lua_events">1</property>
<property name="skip_php_events">1</property>
<property name="skip_python_events">1</property>
<property name="ui_table">UI</property>
<property name="use_array_enum">0</property>
<property name="use_enum">0</property>
<property name="use_microsoft_bom">0</property>
<object class="Dialog" expanded="1">
<property name="aui_managed">0</property>
<property name="aui_manager_style">wxAUI_MGR_DEFAULT</property>
<property name="bg"></property>
<property name="center">wxBOTH</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="enabled">1</property>
<property name="event_handler">decl_pure_virtual</property>
<property name="extra_style"></property>
<property name="fg"></property>
<property name="font"></property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="maximum_size"></property>
<property name="minimum_size">-1,-1</property>
<property name="name">EDA_LIST_DIALOG_BASE</property>
<property name="pos"></property>
<property name="size"></property>
<property name="style">wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER</property>
<property name="subclass">DIALOG_SHIM; dialog_shim.h</property>
<property name="title"></property>
<property name="tooltip"></property>
<property name="two_step_creation">0</property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnSize">onSize</event>
<object class="wxBoxSizer" expanded="1">
<FileVersion major="1" minor="18"/>
<object class="Project" expanded="true">
<property name="code_generation">C++</property>
<property name="cpp_class_decoration"></property>
<property name="cpp_disconnect_events">1</property>
<property name="cpp_event_generation">connect</property>
<property name="cpp_help_provider">none</property>
<property name="cpp_namespace"></property>
<property name="cpp_precompiled_header"></property>
<property name="cpp_use_array_enum">0</property>
<property name="cpp_use_enum">0</property>
<property name="embedded_files_path">res</property>
<property name="encoding">UTF-8</property>
<property name="file">eda_list_dialog_base</property>
<property name="first_id">1000</property>
<property name="internationalize">1</property>
<property name="lua_skip_events">1</property>
<property name="lua_ui_table">UI</property>
<property name="name">eda_list_dialog_base</property>
<property name="path">.</property>
<property name="php_disconnect_events">0</property>
<property name="php_disconnect_mode">source_name</property>
<property name="php_skip_events">1</property>
<property name="python_disconnect_events">0</property>
<property name="python_disconnect_mode">source_name</property>
<property name="python_image_path_wrapper_function_name"></property>
<property name="python_indent_with_spaces"></property>
<property name="python_skip_events">1</property>
<property name="relative_path">1</property>
<property name="use_microsoft_bom">0</property>
<property name="use_native_eol">0</property>
<object class="Dialog" expanded="true">
<property name="aui_managed">0</property>
<property name="aui_manager_style">wxAUI_MGR_DEFAULT</property>
<property name="bg"></property>
<property name="center">wxBOTH</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="drag_accept_files">0</property>
<property name="enabled">1</property>
<property name="event_handler">decl_pure_virtual</property>
<property name="extra_style"></property>
<property name="fg"></property>
<property name="font"></property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="maximum_size"></property>
<property name="minimum_size">-1,-1</property>
<property name="name">EDA_LIST_DIALOG_BASE</property>
<property name="pos"></property>
<property name="size"></property>
<property name="style">wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER</property>
<property name="subclass">DIALOG_SHIM; dialog_shim.h</property>
<property name="title"></property>
<property name="tooltip"></property>
<property name="two_step_creation">0</property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnSize">onSize</event>
<object class="wxBoxSizer" expanded="true">
<property name="minimum_size"></property>
<property name="name">bSizerMain</property>
<property name="orient">wxVERTICAL</property>
<property name="permission">none</property>
<object class="sizeritem" expanded="true">
<property name="border">5</property>
<property name="flag">wxEXPAND|wxRIGHT|wxLEFT</property>
<property name="proportion">1</property>
<object class="wxBoxSizer" expanded="true">
<property name="minimum_size"></property>
<property name="name">bMargins</property>
<property name="orient">wxVERTICAL</property>
<property name="permission">none</property>
<object class="sizeritem" expanded="true">
<property name="border">5</property>
<property name="flag">wxALL</property>
<property name="proportion">0</property>
<object class="wxStaticText" expanded="true">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="drag_accept_files">0</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Items:</property>
<property name="markup">0</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="name">bSizerMain</property>
<property name="moveable">1</property>
<property name="name">m_listLabel</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass"></property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<property name="wrap">-1</property>
</object>
</object>
<object class="sizeritem" expanded="true">
<property name="border">5</property>
<property name="flag">wxBOTTOM|wxRIGHT|wxLEFT|wxEXPAND</property>
<property name="proportion">3</property>
<object class="wxListCtrl" expanded="true">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="drag_accept_files">0</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size">280,150</property>
<property name="moveable">1</property>
<property name="name">m_listBox</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style">wxLC_HRULES|wxLC_REPORT|wxLC_SINGLE_SEL|wxLC_VRULES</property>
<property name="subclass"></property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style">wxBORDER_SIMPLE|wxVSCROLL</property>
<event name="OnListItemActivated">onListItemActivated</event>
</object>
</object>
<object class="sizeritem" expanded="true">
<property name="border">5</property>
<property name="flag">wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT</property>
<property name="proportion">0</property>
<object class="wxTextCtrl" expanded="true">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="drag_accept_files">0</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="maxlength">0</property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_filterBox</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass"></property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="value"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnText">textChangeInFilterBox</event>
</object>
</object>
<object class="sizeritem" expanded="true">
<property name="border">5</property>
<property name="flag">wxEXPAND|wxTOP|wxRIGHT|wxLEFT</property>
<property name="proportion">0</property>
<object class="wxBoxSizer" expanded="true">
<property name="minimum_size"></property>
<property name="name">m_ExtrasSizer</property>
<property name="orient">wxVERTICAL</property>
<property name="permission">none</property>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxEXPAND|wxRIGHT|wxLEFT</property>
<property name="proportion">1</property>
<object class="wxBoxSizer" expanded="1">
<property name="minimum_size"></property>
<property name="name">bMargins</property>
<property name="orient">wxVERTICAL</property>
<property name="permission">none</property>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxALL</property>
<property name="proportion">0</property>
<object class="wxStaticText" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Items:</property>
<property name="markup">0</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_listLabel</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass"></property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<property name="wrap">-1</property>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxBOTTOM|wxRIGHT|wxLEFT|wxEXPAND</property>
<property name="proportion">3</property>
<object class="wxListCtrl" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size">280,150</property>
<property name="moveable">1</property>
<property name="name">m_listBox</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style">wxLC_HRULES|wxLC_REPORT|wxLC_SINGLE_SEL|wxLC_VRULES</property>
<property name="subclass"></property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style">wxBORDER_SIMPLE|wxVSCROLL</property>
<event name="OnListItemActivated">onListItemActivated</event>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT</property>
<property name="proportion">0</property>
<object class="wxTextCtrl" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="maxlength"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_filterBox</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass"></property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="value"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnText">textChangeInFilterBox</event>
</object>
</object>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxEXPAND</property>
<property name="proportion">0</property>
<object class="wxBoxSizer" expanded="1">
<property name="minimum_size"></property>
<property name="name">m_ButtonsSizer</property>
<property name="orient">wxHORIZONTAL</property>
<property name="permission">public</property>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxALL</property>
<property name="proportion">1</property>
<object class="wxStdDialogButtonSizer" expanded="1">
<property name="Apply">0</property>
<property name="Cancel">1</property>
<property name="ContextHelp">0</property>
<property name="Help">0</property>
<property name="No">0</property>
<property name="OK">1</property>
<property name="Save">0</property>
<property name="Yes">0</property>
<property name="minimum_size"></property>
<property name="name">m_sdbSizer</property>
<property name="permission">protected</property>
</object>
</object>
</object>
</object>
<property name="permission">public</property>
</object>
</object>
</object>
</object>
<object class="sizeritem" expanded="true">
<property name="border">5</property>
<property name="flag">wxEXPAND</property>
<property name="proportion">0</property>
<object class="wxBoxSizer" expanded="true">
<property name="minimum_size"></property>
<property name="name">m_ButtonsSizer</property>
<property name="orient">wxHORIZONTAL</property>
<property name="permission">public</property>
<object class="sizeritem" expanded="true">
<property name="border">5</property>
<property name="flag">wxALL</property>
<property name="proportion">1</property>
<object class="wxStdDialogButtonSizer" expanded="true">
<property name="Apply">0</property>
<property name="Cancel">1</property>
<property name="ContextHelp">0</property>
<property name="Help">0</property>
<property name="No">0</property>
<property name="OK">1</property>
<property name="Save">0</property>
<property name="Yes">0</property>
<property name="minimum_size"></property>
<property name="name">m_sdbSizer</property>
<property name="permission">protected</property>
</object>
</object>
</object>
</object>
</object>
</object>
</object>
</wxFormBuilder_Project>

4
common/dialogs/eda_list_dialog_base.h

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b)
// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6)
// http://www.wxformbuilder.org/
//
// PLEASE DO *NOT* EDIT THIS FILE!
@ -25,7 +25,6 @@
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
/// Class EDA_LIST_DIALOG_BASE
///////////////////////////////////////////////////////////////////////////////
@ -48,6 +47,7 @@ class EDA_LIST_DIALOG_BASE : public DIALOG_SHIM
public:
wxBoxSizer* m_ExtrasSizer;
wxBoxSizer* m_ButtonsSizer;
EDA_LIST_DIALOG_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );

37
common/eda_draw_frame.cpp

@ -66,6 +66,7 @@
#include <widgets/msgpanel.h>
#include <widgets/properties_panel.h>
#include <widgets/net_inspector_panel.h>
#include <widgets/filedlg_hook_new_library.h>
#include <wx/event.h>
#include <wx/snglinst.h>
#include <widgets/ui_common.h>
@ -1158,35 +1159,20 @@ wxString EDA_DRAW_FRAME::GetFullScreenDesc() const
}
bool EDA_DRAW_FRAME::LibraryFileBrowser( bool doOpen, wxFileName& aFilename,
bool EDA_DRAW_FRAME::LibraryFileBrowser( const wxString& aTitle, bool doOpen, wxFileName& aFilename,
const wxString& wildcard, const wxString& ext,
bool isDirectory, bool aIsGlobal,
const wxString& aGlobalPath )
bool isDirectory, FILEDLG_HOOK_NEW_LIBRARY* aFileDlgHook )
{
wxString prompt = doOpen ? _( "Select Library" ) : _( "New Library" );
aFilename.SetExt( ext );
wxString projectDir = Prj().IsNullProject() ? aFilename.GetPath() : Prj().GetProjectPath();
wxString defaultDir;
wxString defaultDir = aFilename.GetPath();
if( aIsGlobal )
{
if( !GetMruPath().IsEmpty() && !GetMruPath().StartsWith( projectDir ) )
defaultDir = GetMruPath();
else
defaultDir = aGlobalPath;
}
else
{
if( !GetMruPath().IsEmpty() && GetMruPath().StartsWith( projectDir ) )
defaultDir = GetMruPath();
else
defaultDir = projectDir;
}
if( defaultDir.IsEmpty() )
defaultDir = GetMruPath();
if( isDirectory && doOpen )
{
wxDirDialog dlg( this, prompt, defaultDir, wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST );
wxDirDialog dlg( this, aTitle, defaultDir, wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST );
if( dlg.ShowModal() == wxID_CANCEL )
return false;
@ -1200,9 +1186,12 @@ bool EDA_DRAW_FRAME::LibraryFileBrowser( bool doOpen, wxFileName& aFilename,
if( aFilename.GetName().empty() )
aFilename.SetName( wxS( "Library" ) );
wxFileDialog dlg( this, prompt, defaultDir, aFilename.GetFullName(),
wildcard, doOpen ? wxFD_OPEN | wxFD_FILE_MUST_EXIST
: wxFD_SAVE | wxFD_CHANGE_DIR | wxFD_OVERWRITE_PROMPT );
wxFileDialog dlg( this, aTitle, defaultDir, aFilename.GetFullName(), wildcard,
doOpen ? wxFD_OPEN | wxFD_FILE_MUST_EXIST
: wxFD_SAVE | wxFD_CHANGE_DIR | wxFD_OVERWRITE_PROMPT );
if( aFileDlgHook )
dlg.SetCustomizeHook( *aFileDlgHook );
if( dlg.ShowModal() == wxID_CANCEL )
return false;

2
common/tool/design_block_control.cpp

@ -118,7 +118,7 @@ int DESIGN_BLOCK_CONTROL::UnpinLibrary( const TOOL_EVENT& aEvent )
int DESIGN_BLOCK_CONTROL::NewLibrary( const TOOL_EVENT& aEvent )
{
if( getDesignBlockPane()->CreateNewDesignBlockLibrary() != wxEmptyString )
if( !getDesignBlockPane()->CreateNewDesignBlockLibrary( _( "New Design Block Library" ) ).IsEmpty() )
{
notifyOtherFrames();
return 0;

135
common/widgets/design_block_pane.cpp

@ -31,21 +31,20 @@
#include <widgets/design_block_pane.h>
#include <dialog_design_block_properties.h>
#include <widgets/panel_design_block_chooser.h>
#include <widgets/filedlg_hook_new_library.h>
#include <kiface_base.h>
#include <core/kicad_algo.h>
#include <template_fieldnames.h>
#include <wx/button.h>
#include <wx/checkbox.h>
#include <wx/sizer.h>
#include <wx/choicdlg.h>
#include <wx/msgdlg.h>
#include <wx/textdlg.h>
#include <confirm.h>
#include <wildcards_and_files_ext.h>
#include <tool/tool_manager.h>
DESIGN_BLOCK_PANE::DESIGN_BLOCK_PANE( EDA_DRAW_FRAME* aParent, const LIB_ID* aPreselect,
std::vector<LIB_ID>& aHistoryList ) : WX_PANEL( aParent ), m_frame( aParent )
std::vector<LIB_ID>& aHistoryList ) :
WX_PANEL( aParent ),
m_frame( aParent )
{
m_frame->Bind( wxEVT_AUI_PANE_CLOSE, &DESIGN_BLOCK_PANE::OnClosed, this );
m_frame->Bind( EDA_LANG_CHANGED, &DESIGN_BLOCK_PANE::OnLanguageChanged, this );
@ -141,48 +140,27 @@ DESIGN_BLOCK* DESIGN_BLOCK_PANE::GetSelectedDesignBlock( bool aUseCacheLib, bool
}
wxString DESIGN_BLOCK_PANE::CreateNewDesignBlockLibrary( const wxString& aLibName, const wxString& aProposedName )
wxString DESIGN_BLOCK_PANE::CreateNewDesignBlockLibrary( const wxString& aDialogTitle )
{
return createNewDesignBlockLibrary( aLibName, aProposedName, selectDesignBlockLibTable() );
return createNewDesignBlockLibrary( aDialogTitle );
}
wxString DESIGN_BLOCK_PANE::createNewDesignBlockLibrary( const wxString& aLibName, const wxString& aProposedName,
DESIGN_BLOCK_LIB_TABLE* aTable )
wxString DESIGN_BLOCK_PANE::createNewDesignBlockLibrary( const wxString& aDialogTitle )
{
if( aTable == nullptr )
return wxEmptyString;
wxFileName fn;
bool doAdd = false;
bool isGlobal = ( aTable == &DESIGN_BLOCK_LIB_TABLE::GetGlobalLibTable() );
wxString initialPath = aProposedName;
wxFileName fn;
bool isGlobal = false;
FILEDLG_HOOK_NEW_LIBRARY tableChooser( isGlobal );
if( initialPath.IsEmpty() )
initialPath = isGlobal ? PATHS::GetDefaultUserDesignBlocksPath() : m_frame->Prj().GetProjectPath();
if( aLibName.IsEmpty() )
if( !m_frame->LibraryFileBrowser( aDialogTitle, false, fn, FILEEXT::KiCadDesignBlockLibPathWildcard(),
FILEEXT::KiCadDesignBlockLibPathExtension, false, &tableChooser ) )
{
fn = initialPath;
if( !m_frame->LibraryFileBrowser( false, fn, FILEEXT::KiCadDesignBlockLibPathWildcard(),
FILEEXT::KiCadDesignBlockLibPathExtension, false, isGlobal, initialPath ) )
{
return wxEmptyString;
}
doAdd = true;
return wxEmptyString;
}
else
{
fn = EnsureFileExtension( aLibName, FILEEXT::KiCadDesignBlockLibPathExtension );
if( !fn.IsAbsolute() )
{
fn.SetName( aLibName );
fn.MakeAbsolute( initialPath );
}
}
isGlobal = tableChooser.GetUseGlobalTable();
DESIGN_BLOCK_LIB_TABLE* libTable = isGlobal ? &DESIGN_BLOCK_LIB_TABLE::GetGlobalLibTable()
: m_frame->Prj().DesignBlockLibs();
// We can save libs only using DESIGN_BLOCK_IO_MGR::KICAD_SEXP format (.pretty libraries)
DESIGN_BLOCK_IO_MGR::DESIGN_BLOCK_FILE_T piType = DESIGN_BLOCK_IO_MGR::KICAD_SEXP;
@ -235,37 +213,19 @@ wxString DESIGN_BLOCK_PANE::createNewDesignBlockLibrary( const wxString& aLibNam
return wxEmptyString;
}
if( doAdd )
AddDesignBlockLibrary( libPath, aTable );
AddDesignBlockLibrary( aDialogTitle, libPath, libTable );
return libPath;
}
bool DESIGN_BLOCK_PANE::AddDesignBlockLibrary( const wxString& aFilename, DESIGN_BLOCK_LIB_TABLE* aTable )
bool DESIGN_BLOCK_PANE::AddDesignBlockLibrary( const wxString& aDialogTitle, const wxString& aFilename,
DESIGN_BLOCK_LIB_TABLE* aTable )
{
if( aTable == nullptr )
aTable = selectDesignBlockLibTable();
if( aTable == nullptr )
return wxEmptyString;
bool isGlobal = ( aTable == &DESIGN_BLOCK_LIB_TABLE::GetGlobalLibTable() );
bool isGlobal = ( aTable == &DESIGN_BLOCK_LIB_TABLE::GetGlobalLibTable() );
wxFileName fn( aFilename );
if( aFilename.IsEmpty() )
{
if( !m_frame->LibraryFileBrowser( true, fn, FILEEXT::KiCadDesignBlockLibPathWildcard(),
FILEEXT::KiCadDesignBlockLibPathExtension, true, isGlobal,
PATHS::GetDefaultUserDesignBlocksPath() ) )
{
return false;
}
}
wxString libPath = fn.GetFullPath();
wxString libName = fn.GetName();
wxString libPath = fn.GetFullPath();
wxString libName = fn.GetName();
if( libName.IsEmpty() )
return false;
@ -291,14 +251,14 @@ bool DESIGN_BLOCK_PANE::AddDesignBlockLibrary( const wxString& aFilename, DESIGN
try
{
DESIGN_BLOCK_LIB_TABLE_ROW* row =
new DESIGN_BLOCK_LIB_TABLE_ROW( libName, normalizedPath, type, wxEmptyString, description );
DESIGN_BLOCK_LIB_TABLE_ROW* row = new DESIGN_BLOCK_LIB_TABLE_ROW( libName, normalizedPath, type,
wxEmptyString, description );
aTable->InsertRow( row );
if( isGlobal )
DESIGN_BLOCK_LIB_TABLE::GetGlobalLibTable().Save( DESIGN_BLOCK_LIB_TABLE::GetGlobalTableFileName() );
aTable->Save( DESIGN_BLOCK_LIB_TABLE::GetGlobalTableFileName() );
else
m_frame->Prj().DesignBlockLibs()->Save( m_frame->Prj().DesignBlockLibTblName() );
aTable->Save( m_frame->Prj().DesignBlockLibTblName() );
}
catch( const IO_ERROR& ioe )
{
@ -469,46 +429,3 @@ bool DESIGN_BLOCK_PANE::checkOverwrite( wxWindow* aFrame, wxString& libname, wxS
return true;
}
DESIGN_BLOCK_LIB_TABLE* DESIGN_BLOCK_PANE::selectDesignBlockLibTable( bool aOptional )
{
// If no project is loaded, always work with the global table
if( m_frame->Prj().IsNullProject() )
{
DESIGN_BLOCK_LIB_TABLE* ret = &DESIGN_BLOCK_LIB_TABLE::GetGlobalLibTable();
if( aOptional )
{
wxMessageDialog dlg( m_frame, _( "Add the library to the global library table?" ),
_( "Add To Global Library Table" ), wxYES_NO );
if( dlg.ShowModal() != wxID_OK )
ret = nullptr;
}
return ret;
}
wxArrayString libTableNames;
libTableNames.Add( _( "Global" ) );
libTableNames.Add( _( "Project" ) );
wxSingleChoiceDialog dlg( m_frame, _( "Choose the Library Table to add the library to:" ),
_( "Add To Library Table" ), libTableNames );
if( aOptional )
{
dlg.FindWindow( wxID_CANCEL )->SetLabel( _( "Skip" ) );
dlg.FindWindow( wxID_OK )->SetLabel( _( "Add" ) );
}
if( dlg.ShowModal() != wxID_OK )
return nullptr;
switch( dlg.GetSelection() )
{
case 0: return &DESIGN_BLOCK_LIB_TABLE::GetGlobalLibTable();
case 1: return m_frame->Prj().DesignBlockLibs();
default: return nullptr;
}
}

24
common/widgets/design_block_pane.h

@ -62,26 +62,21 @@ public:
void RefreshLibs();
/**
* If a library name is given, creates a new design block library in the project folder
* with the given name. If no library name is given it prompts user for a library path,
* then creates a new design block library at that location.
* If library exists, user is warned about that, and is given a chance
* to abort the new creation, and in that case existing library is first deleted.
* Creates a new design block library.
*
* @param aProposedName is the initial path and filename shown in the file chooser dialog.
* @return The newly created library path if library was successfully created, else
* wxEmptyString because user aborted or error.
*/
wxString CreateNewDesignBlockLibrary( const wxString& aLibName = wxEmptyString,
const wxString& aProposedName = wxEmptyString );
wxString CreateNewDesignBlockLibrary( const wxString& aDialogTitle );
/**
* Add an existing library to either the global or project library table.
* Add an existing library to a library table (presumed to be either the global or project
* design block table).
*
* @param aFileName the library to add; a file open dialog will be displayed if empty.
* @return true if successfully added.
*/
bool AddDesignBlockLibrary( const wxString& aFilename, DESIGN_BLOCK_LIB_TABLE* aTable );
bool AddDesignBlockLibrary( const wxString& aDialogTitle, const wxString& aFilename,
DESIGN_BLOCK_LIB_TABLE* aTable );
bool DeleteDesignBlockLibrary( const wxString& aLibName, bool aConfirm );
@ -101,9 +96,8 @@ protected:
PANEL_DESIGN_BLOCK_CHOOSER* m_chooserPanel = nullptr;
private:
bool checkOverwrite( wxWindow* aFrame, wxString& libname, wxString& newName );
DESIGN_BLOCK_LIB_TABLE* selectDesignBlockLibTable( bool aOptional = false );
wxString createNewDesignBlockLibrary( const wxString& aLibName, const wxString& aProposedName,
DESIGN_BLOCK_LIB_TABLE* aTable );
bool checkOverwrite( wxWindow* aFrame, wxString& libname, wxString& newName );
wxString createNewDesignBlockLibrary( const wxString& aDialogTitle );
};
#endif

4
common/widgets/grid_text_button_helpers.cpp

@ -39,7 +39,7 @@
#include <env_paths.h>
#include <pgm_base.h>
#include <widgets/wx_grid.h>
#include <widgets/filedlg_open_embed_file.h>
#include <widgets/filedlg_hook_embed_file.h>
#include <widgets/grid_text_button_helpers.h>
#include <eda_doc.h>
@ -366,7 +366,7 @@ protected:
if( filename.IsEmpty() || filename == wxT( "~" ) )
{
FILEDLG_OPEN_EMBED_FILE customize;
FILEDLG_HOOK_EMBED_FILE customize;
wxFileDialog openFileDialog( this, _( "Open file" ), "", "",
_( "All Files" ) + wxT( " (*.*)|*.*" ),

4
eeschema/dialogs/dialog_sim_model.cpp

@ -44,7 +44,7 @@
#include <sch_edit_frame.h>
#include <sim/sim_model_l_mutual.h>
#include <sim/spice_circuit_model.h>
#include <widgets/filedlg_open_embed_file.h>
#include <widgets/filedlg_hook_embed_file.h>
#include <wx/filedlg.h>
#include <wx/log.h>
@ -1256,7 +1256,7 @@ void DIALOG_SIM_MODEL<T>::onBrowseButtonClick( wxCommandEvent& aEvent )
wxString path = s_mruPath.IsEmpty() ? Prj().GetProjectPath() : s_mruPath;
wxFileDialog dlg( this, _( "Browse Models" ), path );
FILEDLG_OPEN_EMBED_FILE customize( false );
FILEDLG_HOOK_EMBED_FILE customize( false );
dlg.SetCustomizeHook( customize );

13
eeschema/menubar.cpp

@ -115,10 +115,9 @@ void SCH_EDIT_FRAME::doReCreateMenuBar()
ACTION_MENU* submenuExport = new ACTION_MENU( false, selTool );
submenuExport->SetTitle( _( "Export" ) );
submenuExport->SetIcon( BITMAPS::export_file );
submenuExport->Add( SCH_ACTIONS::drawSheetOnClipboard, ACTION_MENU::NORMAL, _( "Drawing to Clipboard" ) );
submenuExport->Add( SCH_ACTIONS::exportNetlist, ACTION_MENU::NORMAL, _( "Netlist..." ) );
submenuExport->Add( SCH_ACTIONS::exportSymbolsToLibrary, ACTION_MENU::NORMAL, _( "Symbols to Library..." ) );
submenuExport->Add( SCH_ACTIONS::exportSymbolsToNewLibrary, ACTION_MENU::NORMAL, _( "Symbols to New Library..." ) );
submenuExport->Add( SCH_ACTIONS::drawSheetOnClipboard, ACTION_MENU::NORMAL, _( "Drawing to Clipboard" ) );
submenuExport->Add( SCH_ACTIONS::exportNetlist, ACTION_MENU::NORMAL, _( "Netlist..." ) );
submenuExport->Add( SCH_ACTIONS::exportSymbolsToLibrary, ACTION_MENU::NORMAL, _( "Symbols..." ) );
fileMenu->Add( submenuExport );
fileMenu->AppendSeparator();
@ -166,9 +165,9 @@ void SCH_EDIT_FRAME::doReCreateMenuBar()
submenuAttributes->SetTitle( _( "Attributes" ) );
submenuAttributes->Add( SCH_ACTIONS::setExcludeFromSimulation, ACTION_MENU::CHECK );
submenuAttributes->Add( SCH_ACTIONS::setExcludeFromBOM, ACTION_MENU::CHECK );
submenuAttributes->Add( SCH_ACTIONS::setExcludeFromBoard, ACTION_MENU::CHECK );
submenuAttributes->Add( SCH_ACTIONS::setDNP, ACTION_MENU::CHECK );
submenuAttributes->Add( SCH_ACTIONS::setExcludeFromBOM, ACTION_MENU::CHECK );
submenuAttributes->Add( SCH_ACTIONS::setExcludeFromBoard, ACTION_MENU::CHECK );
submenuAttributes->Add( SCH_ACTIONS::setDNP, ACTION_MENU::CHECK );
editMenu->Add( submenuAttributes );

191
eeschema/sch_base_frame.cpp

@ -28,6 +28,8 @@
#include <lib_tree_model_adapter.h>
#include <pgm_base.h>
#include <eda_list_dialog.h>
#include <widgets/filedlg_hook_new_library.h>
#include <symbol_library_manager.h>
#include <eeschema_settings.h>
#include <gal/graphics_abstraction_layer.h>
#include <project/project_file.h>
@ -277,50 +279,6 @@ bool SCH_BASE_FRAME::saveSymbolLibTables( bool aGlobal, bool aProject )
}
SYMBOL_LIB_TABLE* SCH_BASE_FRAME::SelectSymLibTable( bool aOptional )
{
// If no project is loaded, always work with the global table
if( Prj().IsNullProject() )
{
SYMBOL_LIB_TABLE* ret = &SYMBOL_LIB_TABLE::GetGlobalLibTable();
if( aOptional )
{
wxMessageDialog dlg( this, _( "Add the library to the global library table?" ),
_( "Add To Global Library Table" ), wxYES_NO );
if( dlg.ShowModal() != wxID_OK )
ret = nullptr;
}
return ret;
}
wxArrayString libTableNames;
libTableNames.Add( _( "Global" ) );
libTableNames.Add( _( "Project" ) );
wxSingleChoiceDialog dlg( this, _( "Choose the Library Table to add the library to:" ),
_( "Add To Library Table" ), libTableNames );
if( aOptional )
{
dlg.FindWindow( wxID_CANCEL )->SetLabel( _( "Skip" ) );
dlg.FindWindow( wxID_OK )->SetLabel( _( "Add" ) );
}
if( dlg.ShowModal() != wxID_OK )
return nullptr;
switch( dlg.GetSelection() )
{
case 0: return &SYMBOL_LIB_TABLE::GetGlobalLibTable();
case 1: return PROJECT_SCH::SchSymbolLibTable( &Prj() );
default: return nullptr;
}
}
void SCH_BASE_FRAME::RedrawScreen( const VECTOR2I& aCenterPoint, bool aWarpPointer )
{
GetCanvas()->GetView()->SetCenter( aCenterPoint );
@ -600,75 +558,126 @@ void SCH_BASE_FRAME::handleIconizeEvent( wxIconizeEvent& aEvent )
}
wxString SCH_BASE_FRAME::SelectLibraryFromList()
void SCH_BASE_FRAME::GetLibraryItemsForListDialog( wxArrayString& aHeaders,
std::vector<wxArrayString>& aItemsToDisplay )
{
COMMON_SETTINGS* cfg = Pgm().GetCommonSettings();
PROJECT& prj = Prj();
if( PROJECT_SCH::SchSymbolLibTable( &prj )->IsEmpty() )
{
ShowInfoBarError( _( "No symbol libraries are loaded." ) );
return wxEmptyString;
}
wxArrayString headers;
headers.Add( _( "Library" ) );
COMMON_SETTINGS* cfg = Pgm().GetCommonSettings();
PROJECT_FILE& project = Prj().GetProjectFile();
SYMBOL_LIB_TABLE* tbl = PROJECT_SCH::SchSymbolLibTable( &Prj() );
std::vector<wxString> libNicknames = tbl->GetLogicalLibs();
std::vector< wxArrayString > itemsToDisplay;
std::vector< wxString > libNicknames = PROJECT_SCH::SchSymbolLibTable( &prj )->GetLogicalLibs();
aHeaders.Add( _( "Library" ) );
aHeaders.Add( _( "Description" ) );
for( const wxString& name : libNicknames )
for( const wxString& nickname : libNicknames )
{
// Exclude read only libraries.
if( !PROJECT_SCH::SchSymbolLibTable( &prj )->IsSymbolLibWritable( name ) )
continue;
if( alg::contains( prj.GetProjectFile().m_PinnedSymbolLibs, name )
|| alg::contains( cfg->m_Session.pinned_symbol_libs, name ) )
if( alg::contains( project.m_PinnedSymbolLibs, nickname )
|| alg::contains( cfg->m_Session.pinned_symbol_libs, nickname ) )
{
wxArrayString item;
item.Add( LIB_TREE_MODEL_ADAPTER::GetPinningSymbol() + name );
itemsToDisplay.push_back( item );
item.Add( LIB_TREE_MODEL_ADAPTER::GetPinningSymbol() + nickname );
item.Add( tbl->GetDescription( nickname ) );
aItemsToDisplay.push_back( item );
}
}
for( const wxString& name : libNicknames )
for( const wxString& nickname : libNicknames )
{
// Exclude read only libraries.
if( !PROJECT_SCH::SchSymbolLibTable( &prj )->IsSymbolLibWritable( name ) )
continue;
if( !alg::contains( prj.GetProjectFile().m_PinnedSymbolLibs, name )
&& !alg::contains( cfg->m_Session.pinned_symbol_libs, name ) )
if( !alg::contains( project.m_PinnedSymbolLibs, nickname )
&& !alg::contains( cfg->m_Session.pinned_symbol_libs, nickname ) )
{
wxArrayString item;
item.Add( name );
itemsToDisplay.push_back( item );
item.Add( nickname );
item.Add( tbl->GetDescription( nickname ) );
aItemsToDisplay.push_back( item );
}
}
}
wxString oldLibName = prj.GetRString( PROJECT::SCH_LIB_SELECT );
EDA_LIST_DIALOG dlg( this, _( "Select Symbol Library" ), headers, itemsToDisplay, oldLibName,
false );
wxString SCH_BASE_FRAME::SelectLibrary( const wxString& aDialogTitle, const wxString& aListLabel,
const std::vector<std::pair<wxString, bool*>>& aExtraCheckboxes )
{
static const int ID_MAKE_NEW_LIBRARY = wxID_HIGHEST;
if( dlg.ShowModal() != wxID_OK )
return wxEmptyString;
// Keep asking the user for a new name until they give a valid one or cancel the operation
while( true )
{
wxArrayString headers;
std::vector<wxArrayString> itemsToDisplay;
wxString libName = dlg.GetTextSelection();
GetLibraryItemsForListDialog( headers, itemsToDisplay );
if( !libName.empty() )
{
if( PROJECT_SCH::SchSymbolLibTable( &prj )->HasLibrary( libName ) )
prj.SetRString( PROJECT::SCH_LIB_SELECT, libName );
else
libName = wxEmptyString;
}
wxString libraryName = Prj().GetRString( PROJECT::SCH_LIB_SELECT );
EDA_LIST_DIALOG dlg( this, aDialogTitle, headers, itemsToDisplay, libraryName, false, aExtraCheckboxes );
dlg.SetListLabel( aListLabel );
wxButton* newLibraryButton = new wxButton( &dlg, ID_MAKE_NEW_LIBRARY, _( "New Library..." ) );
dlg.m_ButtonsSizer->Prepend( 80, 20 );
dlg.m_ButtonsSizer->Prepend( newLibraryButton, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 10 );
newLibraryButton->Bind( wxEVT_BUTTON,
[&dlg]( wxCommandEvent& )
{
dlg.EndModal( ID_MAKE_NEW_LIBRARY );
}, ID_MAKE_NEW_LIBRARY );
dlg.Layout();
dlg.GetSizer()->Fit( &dlg );
int ret = dlg.ShowModal();
switch( ret )
{
case wxID_CANCEL:
return wxEmptyString;
case wxID_OK:
libraryName = dlg.GetTextSelection();
Prj().SetRString( PROJECT::SCH_LIB_SELECT, libraryName );
dlg.GetExtraCheckboxValues();
return libraryName;
case ID_MAKE_NEW_LIBRARY:
{
SYMBOL_LIBRARY_MANAGER mgr( *this );
wxFileName fn( Prj().GetRString( PROJECT::SCH_LIB_PATH ) );
bool useGlobalTable = false;
FILEDLG_HOOK_NEW_LIBRARY tableChooser( useGlobalTable );
return libName;
if( !LibraryFileBrowser( _( "Create New Library" ), false, fn, FILEEXT::KiCadSymbolLibFileWildcard(),
FILEEXT::KiCadSymbolLibFileExtension, false, &tableChooser ) )
{
break;
}
libraryName = fn.GetName();
Prj().SetRString( PROJECT::SCH_LIB_PATH, fn.GetPath() );
useGlobalTable = tableChooser.GetUseGlobalTable();
SYMBOL_LIB_TABLE* libTable = useGlobalTable ? &SYMBOL_LIB_TABLE::GetGlobalLibTable()
: PROJECT_SCH::SchSymbolLibTable( &Prj() );
if( libTable->HasLibrary( libraryName, false ) )
{
DisplayError( this, wxString::Format( _( "Library '%s' already exists." ), libraryName ) );
break;
}
if( !mgr.CreateLibrary( fn.GetFullPath(), *libTable ) )
DisplayError( this, wxString::Format( _( "Could not add library '%s'." ), libraryName ) );
break;
}
default:
break;
}
}
}

20
eeschema/sch_base_frame.h

@ -188,19 +188,15 @@ public:
/**
* Display a list of loaded libraries and allows the user to select a library.
*
* This list is sorted, with the library cache always at end of the list
*
* @param aDialogTitle title for the dialog window
* @param aListLabel label over the list of libraries
* @param aExtraCheckboxes [optional] list of label/valuePointer pairs from which to construct extra
* checkboxes in the dialog. Values are written back to the pointers when
* the dialog is finished.
* @return the library nickname used in the symbol library table.
*/
wxString SelectLibraryFromList();
/**
* Display a dialog asking the user to select a symbol library table.
*
* @param aOptional if set the Cancel button will be relabelled "Skip".
* @return Pointer to the selected symbol library table or nullptr if canceled.
*/
SYMBOL_LIB_TABLE* SelectSymLibTable( bool aOptional = false );
wxString SelectLibrary( const wxString& aDialogTitle, const wxString& aListLabel,
const std::vector<std::pair<wxString, bool*>>& aExtraCheckboxes = {} );
virtual void RedrawScreen( const VECTOR2I& aCenterPoint, bool aWarpPointer );
@ -269,6 +265,8 @@ public:
SCH_SELECTION_TOOL* GetSelectionTool() override;
void GetLibraryItemsForListDialog( wxArrayString& aHeaders, std::vector<wxArrayString>& aItemsToDisplay );
protected:
void handleActivateEvent( wxActivateEvent& aEvent ) override;

37
eeschema/symbol_editor/symbol_edit_frame.cpp

@ -79,6 +79,7 @@
#include <widgets/sch_properties_panel.h>
#include <widgets/symbol_tree_pane.h>
#include <widgets/wx_aui_utils.h>
#include <widgets/filedlg_hook_new_library.h>
#include <wildcards_and_files_ext.h>
#include <panel_sym_lib_table.h>
#include <string_utils.h>
@ -1076,18 +1077,13 @@ bool SYMBOL_EDIT_FRAME::SynchronizePins()
wxString SYMBOL_EDIT_FRAME::AddLibraryFile( bool aCreateNew )
{
// Select the target library table (global/project)
SYMBOL_LIB_TABLE* libTable = SelectSymLibTable();
wxFileName fn = m_libMgr->GetUniqueLibraryName();
bool useGlobalTable = false;
FILEDLG_HOOK_NEW_LIBRARY tableChooser( useGlobalTable );
if( !libTable )
return wxEmptyString;
wxFileName fn = m_libMgr->GetUniqueLibraryName();
if( !LibraryFileBrowser( !aCreateNew, fn, FILEEXT::KiCadSymbolLibFileWildcard(),
FILEEXT::KiCadSymbolLibFileExtension, false,
( libTable == &SYMBOL_LIB_TABLE::GetGlobalLibTable() ),
PATHS::GetDefaultUserSymbolsPath() ) )
if( !LibraryFileBrowser( aCreateNew ? _( "New Symbol Library" ) : _( "Add Symbol Library" ),
!aCreateNew, fn, FILEEXT::KiCadSymbolLibFileWildcard(),
FILEEXT::KiCadSymbolLibFileExtension, false, &tableChooser ) )
{
return wxEmptyString;
}
@ -1097,12 +1093,17 @@ wxString SYMBOL_EDIT_FRAME::AddLibraryFile( bool aCreateNew )
if( libName.IsEmpty() )
return wxEmptyString;
useGlobalTable = tableChooser.GetUseGlobalTable();
if( m_libMgr->LibraryExists( libName ) )
{
DisplayError( this, wxString::Format( _( "Library '%s' already exists." ), libName ) );
return wxEmptyString;
}
SYMBOL_LIB_TABLE* libTable = useGlobalTable ? &SYMBOL_LIB_TABLE::GetGlobalLibTable()
: PROJECT_SCH::SchSymbolLibTable( &Prj() );
if( aCreateNew )
{
if( !m_libMgr->CreateLibrary( fn.GetFullPath(), *libTable ) )
@ -1135,15 +1136,8 @@ wxString SYMBOL_EDIT_FRAME::AddLibraryFile( bool aCreateNew )
void SYMBOL_EDIT_FRAME::DdAddLibrary( wxString aLibFile )
{
// Select the target library table (global/project)
SYMBOL_LIB_TABLE* libTable = SelectSymLibTable();
if( !libTable )
return;
wxFileName fn = wxFileName( aLibFile );
wxString libName = fn.GetName();
wxString libName = fn.GetName();
if( libName.IsEmpty() )
return;
@ -1154,14 +1148,13 @@ void SYMBOL_EDIT_FRAME::DdAddLibrary( wxString aLibFile )
return;
}
if( !m_libMgr->AddLibrary( fn.GetFullPath(), *libTable ) )
if( !m_libMgr->AddLibrary( fn.GetFullPath(), *PROJECT_SCH::SchSymbolLibTable( &Prj() ) ) )
{
DisplayError( this, _( "Could not open the library file." ) );
return;
}
bool globalTable = ( libTable == &SYMBOL_LIB_TABLE::GetGlobalLibTable() );
saveSymbolLibTables( globalTable, !globalTable );
saveSymbolLibTables( false, true );
std::string packet = fn.GetFullPath().ToStdString();
this->Kiway().ExpressMail( FRAME_SCH_SYMBOL_EDITOR, MAIL_LIB_EDIT, packet );

82
eeschema/symbol_editor/symbol_editor.cpp

@ -49,8 +49,7 @@
#include <project_sch.h>
#include <string_utils.h>
#include "symbol_saveas_type.h"
#include <widgets/symbol_filedlg_save_as.h>
#include <widgets/symbol_library_save_as_filedlg_hook.h>
#include <io/kicad/kicad_io_utils.h>
@ -91,7 +90,7 @@ void SYMBOL_EDIT_FRAME::SelectActiveLibrary( const wxString& aLibrary )
wxString selectedLib = aLibrary;
if( selectedLib.empty() )
selectedLib = SelectLibraryFromList();
selectedLib = SelectLibrary( _( "Select Symbol Library" ), _( "Library:" ) );
if( !selectedLib.empty() )
SetCurLib( selectedLib );
@ -348,7 +347,7 @@ void SYMBOL_EDIT_FRAME::CreateNewSymbol( const wxString& aInheritFrom )
if( !m_libMgr->LibraryExists( lib ) )
{
lib = SelectLibraryFromList();
lib = SelectLibrary( _( "New Symbol" ), _( "Create symbol in library:" ) );
if( !m_libMgr->LibraryExists( lib ) )
return;
@ -709,7 +708,7 @@ public:
// Add a suffix until we find a name that doesn't conflict
RENAME,
// Could have a mode that asks for every one, be then we'll need a fancier
// SAVE_AS_DIALOG subdialog with Overwrite/Rename/Prompt/Cancel
// SAVE_SYMBOL_AS_DIALOG subdialog with Overwrite/Rename/Prompt/Cancel
// PROMPT
};
@ -827,52 +826,24 @@ enum SAVE_AS_IDS
};
class SAVE_AS_DIALOG : public EDA_LIST_DIALOG
class SAVE_SYMBOL_AS_DIALOG : public EDA_LIST_DIALOG
{
public:
using SymLibNameValidator =
std::function<int( const wxString& libName, const wxString& symbolName )>;
using SymLibNameValidator = std::function<int( const wxString& libName, const wxString& symbolName )>;
SAVE_AS_DIALOG( SYMBOL_EDIT_FRAME* aParent, const wxString& aSymbolName,
const wxString& aLibraryPreselect, SymLibNameValidator aValidator,
SYMBOL_SAVE_AS_HANDLER::CONFLICT_STRATEGY& aConflictStrategy ) :
SAVE_SYMBOL_AS_DIALOG( SYMBOL_EDIT_FRAME* aParent, const wxString& aSymbolName,
const wxString& aLibraryPreselect, SymLibNameValidator aValidator,
SYMBOL_SAVE_AS_HANDLER::CONFLICT_STRATEGY& aConflictStrategy ) :
EDA_LIST_DIALOG( aParent, _( "Save Symbol As" ), false ),
m_validator( std::move( aValidator ) ), m_conflictStrategy( aConflictStrategy )
m_validator( std::move( aValidator ) ),
m_conflictStrategy( aConflictStrategy )
{
COMMON_SETTINGS* cfg = Pgm().GetCommonSettings();
PROJECT_FILE& project = aParent->Prj().GetProjectFile();
SYMBOL_LIB_TABLE* tbl = PROJECT_SCH::SchSymbolLibTable( &Prj() );
std::vector<wxString> libNicknames = tbl->GetLogicalLibs();
wxArrayString headers;
std::vector<wxArrayString> itemsToDisplay;
headers.Add( _( "Nickname" ) );
headers.Add( _( "Description" ) );
for( const wxString& nickname : libNicknames )
{
if( alg::contains( project.m_PinnedSymbolLibs, nickname )
|| alg::contains( cfg->m_Session.pinned_symbol_libs, nickname ) )
{
wxArrayString item;
item.Add( LIB_TREE_MODEL_ADAPTER::GetPinningSymbol() + nickname );
item.Add( tbl->GetDescription( nickname ) );
itemsToDisplay.push_back( item );
}
}
for( const wxString& nickname : libNicknames )
{
if( !alg::contains( project.m_PinnedSymbolLibs, nickname )
&& !alg::contains( cfg->m_Session.pinned_symbol_libs, nickname ) )
{
wxArrayString item;
item.Add( nickname );
item.Add( tbl->GetDescription( nickname ) );
itemsToDisplay.push_back( item );
}
}
aParent->GetLibraryItemsForListDialog( headers, itemsToDisplay );
initDialog( headers, itemsToDisplay, aLibraryPreselect );
SetListLabel( _( "Save in library:" ) );
@ -989,8 +960,8 @@ void SYMBOL_EDIT_FRAME::saveSymbolCopyAs( bool aOpenCopy )
* If we save over a symbol that is in the inheritance chain of the symbol we're
* saving, we'll end up with a circular inheritance chain, which is bad.
*/
const auto& [inAncestry, inDescendents] =
CheckSavingIntoOwnInheritance( *m_libMgr, *symbol, newName, newLib );
const auto& [inAncestry, inDescendents] = CheckSavingIntoOwnInheritance( *m_libMgr, *symbol,
newName, newLib );
if( inAncestry )
{
@ -1012,8 +983,8 @@ void SYMBOL_EDIT_FRAME::saveSymbolCopyAs( bool aOpenCopy )
return wxID_CANCEL;
}
const std::vector<wxString> conflicts =
CheckForParentalChainConflicts( *m_libMgr, *symbol, newName, newLib );
const std::vector<wxString> conflicts = CheckForParentalChainConflicts( *m_libMgr, *symbol,
newName, newLib );
if( conflicts.size() == 1 && conflicts.front() == newName )
{
@ -1023,12 +994,10 @@ void SYMBOL_EDIT_FRAME::saveSymbolCopyAs( bool aOpenCopy )
UnescapeString( newName ),
newLib );
KIDIALOG errorDlg( this, msg, _( "Confirmation" ),
wxOK | wxCANCEL | wxICON_WARNING );
KIDIALOG errorDlg( this, msg, _( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
errorDlg.SetOKLabel( _( "Overwrite" ) );
return errorDlg.ShowModal() == wxID_OK ? ID_OVERWRITE_CONFLICTS
: (int) wxID_CANCEL;
return errorDlg.ShowModal() == wxID_OK ? ID_OVERWRITE_CONFLICTS : (int) wxID_CANCEL;
}
else if( !conflicts.empty() )
{
@ -1046,10 +1015,8 @@ void SYMBOL_EDIT_FRAME::saveSymbolCopyAs( bool aOpenCopy )
msg += _( "\nDo you want to overwrite all of them, or rename the new symbols?" );
KIDIALOG errorDlg( this, msg, _( "Confirmation" ),
wxYES_NO | wxCANCEL | wxICON_WARNING );
errorDlg.SetYesNoCancelLabels( _( "Overwrite All" ), _( "Rename All" ),
_( "Cancel" ) );
KIDIALOG errorDlg( this, msg, _( "Confirmation" ), wxYES_NO | wxCANCEL | wxICON_WARNING );
errorDlg.SetYesNoCancelLabels( _( "Overwrite All" ), _( "Rename All" ), _( "Cancel" ) );
switch( errorDlg.ShowModal() )
{
@ -1067,7 +1034,7 @@ void SYMBOL_EDIT_FRAME::saveSymbolCopyAs( bool aOpenCopy )
// Keep asking the user for a new name until they give a valid one or cancel the operation
while( !done )
{
SAVE_AS_DIALOG dlg( this, symbolName, libraryName, dialogValidatorFunc, strategy );
SAVE_SYMBOL_AS_DIALOG dlg( this, symbolName, libraryName, dialogValidatorFunc, strategy );
int ret = dlg.ShowModal();
@ -1579,11 +1546,10 @@ bool SYMBOL_EDIT_FRAME::saveLibrary( const wxString& aLibrary, bool aNewFile )
wxString wildcards = FILEEXT::KiCadSymbolLibFileWildcard();
wxFileDialog dlg( this, wxString::Format( _( "Save Library '%s' As..." ), aLibrary ),
default_path, fn.GetFullName(), wildcards,
wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
wxFileDialog dlg( this, wxString::Format( _( "Save Library '%s' As..." ), aLibrary ), default_path,
fn.GetFullName(), wildcards, wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
SYMBOL_FILEDLG_SAVE_AS saveAsHook( type );
SYMBOL_LIBRARY_SAVE_AS_FILEDLG_HOOK saveAsHook( type );
dlg.SetCustomizeHook( saveAsHook );
if( dlg.ShowModal() == wxID_CANCEL )

9
eeschema/symbol_editor/symbol_editor_import_export.cpp

@ -35,7 +35,6 @@
#include <wx/filename.h>
#include <wx/filedlg.h>
#include <string_utils.h>
#include <io/eagle/eagle_parser.h>
void SYMBOL_EDIT_FRAME::ImportSymbol()
@ -44,12 +43,10 @@ void SYMBOL_EDIT_FRAME::ImportSymbol()
wxString libName = getTargetLib();
if( !m_libMgr->LibraryExists( libName ) )
{
libName = SelectLibraryFromList();
libName = SelectLibrary( _( "Import Symbol" ), _( "Import symbol to library:" ) );
if( !m_libMgr->LibraryExists( libName ) )
return;
}
if( !m_libMgr->LibraryExists( libName ) )
return;
wxString fileFiltersStr;
wxString allWildcardsStr;

12
eeschema/tools/sch_actions.cpp

@ -1183,19 +1183,11 @@ TOOL_ACTION SCH_ACTIONS::generateBOMExternal( TOOL_ACTION_ARGS()
TOOL_ACTION SCH_ACTIONS::exportSymbolsToLibrary( TOOL_ACTION_ARGS()
.Name( "eeschema.EditorControl.exportSymbolsToLibrary" )
.Scope( AS_GLOBAL )
.FriendlyName( _( "Export Symbols to Library..." ) )
.Tooltip( _( "Add symbols used in schematic to an existing symbol library\n"
.FriendlyName( _( "Export Symbols..." ) )
.Tooltip( _( "Add symbols from schematic to a new or an existing symbol library\n"
"(does not remove other symbols from this library)" ) )
.Icon( BITMAPS::library_archive ) );
TOOL_ACTION SCH_ACTIONS::exportSymbolsToNewLibrary( TOOL_ACTION_ARGS()
.Name( "eeschema.EditorControl.exportSymbolsToNewLibrary" )
.Scope( AS_GLOBAL )
.FriendlyName( _( "Export Symbols to New Library..." ) )
.Tooltip( _( "Create a new symbol library using the symbols used in the schematic\n"
"(if the library already exists it will be replaced)" ) )
.Icon( BITMAPS::library_archive_as ) );
TOOL_ACTION SCH_ACTIONS::selectOnPCB( TOOL_ACTION_ARGS()
.Name( "eeschema.EditorControl.selectOnPCB" )
.Scope( AS_GLOBAL )

1
eeschema/tools/sch_actions.h

@ -179,7 +179,6 @@ public:
static TOOL_ACTION generateBOMExternal;
static TOOL_ACTION addSymbolToSchematic;
static TOOL_ACTION exportSymbolsToLibrary;
static TOOL_ACTION exportSymbolsToNewLibrary;
// Attribute Toggles
static TOOL_ACTION setExcludeFromBOM;

74
eeschema/tools/sch_editor_control.cpp

@ -350,10 +350,18 @@ void SCH_EDITOR_CONTROL::doCrossProbeSchToPcb( const TOOL_EVENT& aEvent, bool aF
int SCH_EDITOR_CONTROL::ExportSymbolsToLibrary( const TOOL_EVENT& aEvent )
{
bool savePowerSymbols = IsOK( m_frame,
_( "Include power symbols in schematic to the library?" ) );
bool savePowerSymbols = false;
bool map = false;
SYMBOL_LIBRARY_MANAGER mgr( *m_frame );
wxString targetLib;
targetLib = m_frame->SelectLibrary( _( "Export Symbols" ), _( "Export symbols to library:" ),
{ { _( "Include power symbols in export" ), &savePowerSymbols },
{ _( "Update schematic symbols to link to exported symbols" ), &map }
} );
bool createNew = aEvent.IsAction( &SCH_ACTIONS::exportSymbolsToNewLibrary );
if( targetLib.empty() )
return 0;
SCH_SHEET_LIST sheets = m_frame->Schematic().BuildSheetListSortedByPageNumbers();
SCH_REFERENCE_LIST symbols;
@ -381,62 +389,11 @@ int SCH_EDITOR_CONTROL::ExportSymbolsToLibrary( const TOOL_EVENT& aEvent )
symbolMap[id].emplace_back( symbol );
}
SYMBOL_LIBRARY_MANAGER mgr( *m_frame );
wxString targetLib;
if( createNew )
{
wxFileName fn;
SYMBOL_LIB_TABLE* libTable = m_frame->SelectSymLibTable();
if( !libTable ) // Cancelled by user
return 0;
if( !m_frame->LibraryFileBrowser( false, fn, FILEEXT::KiCadSymbolLibFileWildcard(),
FILEEXT::KiCadSymbolLibFileExtension, false,
( libTable == &SYMBOL_LIB_TABLE::GetGlobalLibTable() ),
PATHS::GetDefaultUserSymbolsPath() ) )
{
return 0;
}
targetLib = fn.GetName();
if( libTable->HasLibrary( targetLib, false ) )
{
DisplayError( m_frame, wxString::Format( _( "Library '%s' already exists." ),
targetLib ) );
return 0;
}
// if the "new" library is in fact an existing library and the used asked for replacing
// it by the recreated lib, erase it:
if( fn.FileExists() )
wxRemoveFile( fn.GetFullPath() );
if( !mgr.CreateLibrary( fn.GetFullPath(), *libTable ) )
{
DisplayError( m_frame, wxString::Format( _( "Could not add library '%s'." ),
targetLib ) );
return 0;
}
}
else
{
targetLib = m_frame->SelectLibraryFromList();
}
if( targetLib.IsEmpty() )
return 0;
bool map = IsOK( m_frame, _( "Update symbols in schematic to refer to new library?" ) );
bool append = false;
SCH_COMMIT commit( m_frame );
SYMBOL_LIB_TABLE_ROW* row = mgr.GetLibrary( targetLib );
bool append = false;
SCH_COMMIT commit( m_frame );
SYMBOL_LIB_TABLE_ROW* row = mgr.GetLibrary( targetLib );
SCH_IO_MGR::SCH_FILE_T type = SCH_IO_MGR::EnumFromStr( row->GetType() );
IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( type ) );
IO_RELEASER<SCH_IO> pi( SCH_IO_MGR::FindPlugin( type ) );
wxFileName dest = row->GetFullURI( true );
dest.Normalize( FN_NORMALIZE_FLAGS | wxPATH_NORM_ENV_VARS );
@ -3146,7 +3103,6 @@ void SCH_EDITOR_CONTROL::setTransitions()
Go( &SCH_EDITOR_CONTROL::RepairSchematic, SCH_ACTIONS::repairSchematic.MakeEvent() );
Go( &SCH_EDITOR_CONTROL::ExportSymbolsToLibrary, SCH_ACTIONS::exportSymbolsToLibrary.MakeEvent() );
Go( &SCH_EDITOR_CONTROL::ExportSymbolsToLibrary, SCH_ACTIONS::exportSymbolsToNewLibrary.MakeEvent() );
Go( &SCH_EDITOR_CONTROL::PlaceLinkedDesignBlock, SCH_ACTIONS::placeLinkedDesignBlock.MakeEvent() );
Go( &SCH_EDITOR_CONTROL::SaveToLinkedDesignBlock, SCH_ACTIONS::saveToLinkedDesignBlock.MakeEvent() );

19
eeschema/widgets/symbol_filedlg_save_as.h → eeschema/widgets/symbol_library_save_as_filedlg_hook.h

@ -23,20 +23,19 @@
#include <symbol_editor/symbol_saveas_type.h>
#include <wx/filedlgcustomize.h>
class SYMBOL_FILEDLG_SAVE_AS : public wxFileDialogCustomizeHook
class SYMBOL_LIBRARY_SAVE_AS_FILEDLG_HOOK : public wxFileDialogCustomizeHook
{
public:
SYMBOL_FILEDLG_SAVE_AS( SYMBOL_SAVEAS_TYPE aOption ) : m_option( aOption ){};
SYMBOL_LIBRARY_SAVE_AS_FILEDLG_HOOK( SYMBOL_SAVEAS_TYPE aOption ) :
m_option( aOption )
{};
virtual void AddCustomControls( wxFileDialogCustomize& customizer ) override
{
m_simpleSaveAs = customizer.AddRadioButton( _( "Do not update library tables" ) );
m_replaceTableEntry =
customizer.AddRadioButton( _( "Update existing library table entry" ) );
m_addGlobalTableEntry =
customizer.AddRadioButton( _( "Add new global library table entry" ) );
m_addProjectTableEntry =
customizer.AddRadioButton( _( "Add new project library table entry" ) );
m_simpleSaveAs = customizer.AddRadioButton( _( "Do not update library tables" ) );
m_replaceTableEntry = customizer.AddRadioButton( _( "Update existing library table entry" ) );
m_addGlobalTableEntry = customizer.AddRadioButton( _( "Add new global library table entry" ) );
m_addProjectTableEntry = customizer.AddRadioButton( _( "Add new project library table entry" ) );
// Note, due to windows api, wx does not actually support calling SetValue( false ) (it asserts)
if( m_option == SYMBOL_SAVEAS_TYPE::NORMAL_SAVE_AS )
@ -74,7 +73,7 @@ private:
wxFileDialogRadioButton* m_addGlobalTableEntry = nullptr;
wxFileDialogRadioButton* m_addProjectTableEntry = nullptr;
wxDECLARE_NO_COPY_CLASS( SYMBOL_FILEDLG_SAVE_AS );
wxDECLARE_NO_COPY_CLASS( SYMBOL_LIBRARY_SAVE_AS_FILEDLG_HOOK );
};
#endif

9
include/eda_draw_frame.h

@ -52,6 +52,7 @@ class HOTKEY_CYCLE_POPUP;
class PROPERTIES_PANEL;
class NET_INSPECTOR_PANEL;
enum class BITMAP_TYPE;
class FILEDLG_HOOK_NEW_LIBRARY;
namespace KIGFX
{
@ -184,17 +185,19 @@ public:
virtual COLOR_SETTINGS* GetColorSettings( bool aForceRefresh = false ) const;
/**
* @param aTitle dialog title
* @param doOpen if true runs an Open Library browser, otherwise New Library
* @param aFilename for New may contain a default name; in both cases return the chosen
* filename.
* @param wildcard a wildcard to filter the displayed files
* @param ext the library file extension
* @param isDirectory indicates the library files are directories
* @param aFileDlgHook optional; adds customized controls to dialog
* @return true for OK; false for Cancel.
*/
bool LibraryFileBrowser( bool doOpen, wxFileName& aFilename, const wxString& wildcard,
const wxString& ext, bool isDirectory = false, bool aIsGlobal = false,
const wxString& aGlobalPath = wxEmptyString );
bool LibraryFileBrowser( const wxString& aTitle, bool doOpen, wxFileName& aFilename,
const wxString& wildcard, const wxString& ext, bool isDirectory,
FILEDLG_HOOK_NEW_LIBRARY* aFileDlgHook = nullptr );
void CommonSettingsChanged( int aFlags ) override;

14
include/eda_list_dialog.h

@ -30,6 +30,7 @@
class EDA_DRAW_FRAME;
class wxCheckBox;
/**
* A dialog which shows:
@ -52,7 +53,8 @@ public:
EDA_LIST_DIALOG( wxWindow* aParent, const wxString& aTitle, const wxArrayString& aItemHeaders,
const std::vector<wxArrayString>& aItemList,
const wxString& aPreselectText = wxEmptyString,
bool aSortList = true );
bool aSortList = true,
const std::vector<std::pair<wxString, bool*>>& aExtraCheckboxes = {} );
EDA_LIST_DIALOG( wxWindow* aParent, const wxString& aTitle, bool aSortList = true );
@ -71,6 +73,11 @@ public:
*/
wxString GetTextSelection( int aColumn = 0 );
/**
* Fills in the value pointers from the checkboxes after the dialog has run.
*/
void GetExtraCheckboxValues();
long GetSelection();
bool Show( bool show ) override;
@ -88,8 +95,9 @@ private:
private:
// The list of items, locally stored
std::vector<wxArrayString> m_itemsList;
bool m_sortList;
std::vector<wxArrayString> m_itemsList;
bool m_sortList;
std::map<wxCheckBox*, bool*> m_extraCheckboxMap;
};

11
include/pcb_base_frame.h

@ -240,14 +240,6 @@ public:
*/
GENERAL_COLLECTORS_GUIDE GetCollectorsGuide();
/**
* Put up a dialog and allows the user to pick a library, for unspecified use.
*
* @param aNicknameExisting is the current choice to highlight.
* @return the library or wxEmptyString on abort.
*/
wxString SelectLibrary( const wxString& aNicknameExisting );
/**
* Must be called after a change in order to set the "modify" flag and update other data
* structures and GUI elements.
@ -398,6 +390,9 @@ public:
*/
void OnFpChangeDebounceTimer( wxTimerEvent& aEvent );
void GetLibraryItemsForListDialog( wxArrayString& aHeaders,
std::vector<wxArrayString>& aItemsToDisplay );
protected:
bool canCloseWindow( wxCloseEvent& aCloseEvent ) override;

1
include/project.h

@ -225,6 +225,7 @@ public:
VIEWER_3D_PATH,
VIEWER_3D_FILTER_INDEX,
PCB_LIB_PATH,
PCB_LIB_NICKNAME,
PCB_FOOTPRINT,
PCB_FOOTPRINT_EDITOR_FP_NAME,

13
include/widgets/filedlg_open_embed_file.h → include/widgets/filedlg_hook_embed_file.h

@ -17,23 +17,22 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef KICAD_FILEDLG_OPEN_EMBED_FILE_H
#define KICAD_FILEDLG_OPEN_EMBED_FILE_H
#pragma once
#include <wx/wx.h>
#include <wx/filedlgcustomize.h>
class FILEDLG_OPEN_EMBED_FILE : public wxFileDialogCustomizeHook
class FILEDLG_HOOK_EMBED_FILE : public wxFileDialogCustomizeHook
{
public:
FILEDLG_OPEN_EMBED_FILE( bool aDefaultEmbed = true ) :
FILEDLG_HOOK_EMBED_FILE( bool aDefaultEmbed = true ) :
m_embed( aDefaultEmbed )
{};
virtual void AddCustomControls( wxFileDialogCustomize& customizer ) override
{
m_cb = customizer.AddCheckBox( _( "Embed File" ) );
m_cb = customizer.AddCheckBox( _( "Embed file" ) );
m_cb->SetValue( m_embed );
}
@ -49,7 +48,5 @@ private:
wxFileDialogCheckBox* m_cb = nullptr;
wxDECLARE_NO_COPY_CLASS( FILEDLG_OPEN_EMBED_FILE );
wxDECLARE_NO_COPY_CLASS( FILEDLG_HOOK_EMBED_FILE );
};
#endif //KICAD_FILEDLG_OPEN_EMBED_FILE_H

60
include/widgets/filedlg_hook_new_library.h

@ -0,0 +1,60 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright The 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 3 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, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <wx/wx.h>
#include <wx/filedlgcustomize.h>
class FILEDLG_HOOK_NEW_LIBRARY : public wxFileDialogCustomizeHook
{
public:
FILEDLG_HOOK_NEW_LIBRARY( bool aDefaultUseGlobalTable ) :
m_useGlobalTable( aDefaultUseGlobalTable )
{};
virtual void AddCustomControls( wxFileDialogCustomize& customizer ) override
{
m_addGlobalTableEntry = customizer.AddRadioButton( _( "Add new library to global library table" ) );
customizer.AddStaticText( wxS( " " ) );
m_addProjectTableEntry = customizer.AddRadioButton( _( "Add new library to project library table" ) );
if( m_useGlobalTable )
m_addGlobalTableEntry->SetValue( true );
else
m_addProjectTableEntry->SetValue( true );
}
virtual void TransferDataFromCustomControls() override
{
m_useGlobalTable = m_addGlobalTableEntry->GetValue();
}
bool GetUseGlobalTable() const { return m_useGlobalTable; }
private:
bool m_useGlobalTable;
wxFileDialogRadioButton* m_addGlobalTableEntry = nullptr;
wxFileDialogRadioButton* m_addProjectTableEntry = nullptr;
wxDECLARE_NO_COPY_CLASS( FILEDLG_HOOK_NEW_LIBRARY );
};

3
pcbnew/files.cpp

@ -832,7 +832,8 @@ bool PCB_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
// The footprints are saved in a new .pretty library.
// If this library already exists, all previous footprints will be deleted
std::vector<FOOTPRINT*> loadedFootprints = pi->GetImportedCachedLibraryFootprints();
wxString newLibPath = CreateNewProjectLibrary( libNickName );
wxString newLibPath = CreateNewProjectLibrary( _( "New Footprint Library" ),
libNickName );
// Only create the new library if CreateNewLibrary succeeded (note that this fails if
// the library already exists and the user aborts after seeing the warning message

385
pcbnew/footprint_libraries_utils.cpp

@ -43,6 +43,7 @@
#include <footprint_edit_frame.h>
#include <wildcards_and_files_ext.h>
#include <pcb_io/kicad_sexpr/pcb_io_kicad_sexpr.h>
#include <widgets/filedlg_hook_new_library.h>
#include <env_paths.h>
#include <paths.h>
#include <settings/settings_manager.h>
@ -52,11 +53,13 @@
#include <footprint_viewer_frame.h>
#include <io/kicad/kicad_io_utils.h>
#include <view/view_controls.h>
#include <wx/choicdlg.h>
#include <wx/filedlg.h>
#include <wx/fswatcher.h>
static constexpr int ID_MAKE_NEW_LIBRARY = 4173;
// unique, "file local" translations:
@ -272,7 +275,7 @@ void FOOTPRINT_EDIT_FRAME::ExportFootprint( FOOTPRINT* aFootprint )
if( fp == nullptr )
{
DisplayErrorMessage( this, wxString::Format( _( "Insufficient permissions to write file '%s'." ),
dlg.GetPath() ) );
dlg.GetPath() ) );
return;
}
@ -293,49 +296,55 @@ void FOOTPRINT_EDIT_FRAME::ExportFootprint( FOOTPRINT* aFootprint )
}
wxString PCB_BASE_EDIT_FRAME::CreateNewProjectLibrary( const wxString& aLibName,
const wxString& aProposedName )
wxString PCB_BASE_EDIT_FRAME::CreateNewProjectLibrary( const wxString& aDialogTitle, const wxString& aLibName )
{
return createNewLibrary( aLibName, aProposedName, PROJECT_PCB::PcbFootprintLibs( &Prj() ) );
return createNewLibrary( aDialogTitle, aLibName, wxEmptyString, PROJECT_PCB::PcbFootprintLibs( &Prj() ) );
}
wxString PCB_BASE_EDIT_FRAME::CreateNewLibrary( const wxString& aLibName,
const wxString& aProposedName )
wxString PCB_BASE_EDIT_FRAME::CreateNewLibrary( const wxString& aDialogTitle, const wxString& aInitialPath )
{
FP_LIB_TABLE* table = selectLibTable();
return createNewLibrary( aLibName, aProposedName, table );
return createNewLibrary( aDialogTitle, wxEmptyString, aInitialPath, nullptr );
}
wxString PCB_BASE_EDIT_FRAME::createNewLibrary( const wxString& aLibName,
const wxString& aProposedName,
FP_LIB_TABLE* aTable )
wxString PCB_BASE_EDIT_FRAME::createNewLibrary( const wxString& aDialogTitle, const wxString& aLibName,
const wxString& aInitialPath, FP_LIB_TABLE* aTable )
{
// Kicad cannot write legacy format libraries, only .pretty new format because the legacy
// format cannot handle current features.
// The footprint library is actually a directory.
if( aTable == nullptr )
return wxEmptyString;
wxFileName fn;
bool doAdd = false;
bool isGlobal = false;
FP_LIB_TABLE* libTable = PROJECT_PCB::PcbFootprintLibs( &Prj() );
FILEDLG_HOOK_NEW_LIBRARY tableChooser( isGlobal );
FILEDLG_HOOK_NEW_LIBRARY* fileDlgHook = &tableChooser;
wxString initialPath = aProposedName.IsEmpty() ? Prj().GetProjectPath() : aProposedName;
wxFileName fn;
bool doAdd = false;
bool isGlobal = ( aTable == &GFootprintTable );
if( aTable )
{
isGlobal = ( aTable == &GFootprintTable );
libTable = aTable;
fileDlgHook = nullptr;
}
if( aLibName.IsEmpty() )
{
fn = initialPath;
fn = aInitialPath.IsEmpty() ? Prj().GetProjectPath() : aInitialPath;
if( !LibraryFileBrowser( false, fn, FILEEXT::KiCadFootprintLibPathWildcard(),
FILEEXT::KiCadFootprintLibPathExtension, false, isGlobal,
PATHS::GetDefaultUserFootprintsPath() ) )
if( !LibraryFileBrowser( aDialogTitle, false, fn, FILEEXT::KiCadFootprintLibPathWildcard(),
FILEEXT::KiCadFootprintLibPathExtension, false, fileDlgHook ) )
{
return wxEmptyString;
}
if( fileDlgHook )
{
isGlobal = fileDlgHook->GetUseGlobalTable();
libTable = isGlobal ? &GFootprintTable : PROJECT_PCB::PcbFootprintLibs( &Prj() );
}
doAdd = true;
}
else
@ -345,13 +354,13 @@ wxString PCB_BASE_EDIT_FRAME::createNewLibrary( const wxString& aLibName,
if( !fn.IsAbsolute() )
{
fn.SetName( aLibName );
fn.MakeAbsolute( initialPath );
fn.MakeAbsolute( Prj().GetProjectPath() );
}
}
// We can save fp libs only using PCB_IO_MGR::KICAD_SEXP format (.pretty libraries)
PCB_IO_MGR::PCB_FILE_T piType = PCB_IO_MGR::KICAD_SEXP;
wxString libPath = fn.GetFullPath();
wxString libPath = fn.GetFullPath();
try
{
@ -401,76 +410,101 @@ wxString PCB_BASE_EDIT_FRAME::createNewLibrary( const wxString& aLibName,
}
if( doAdd )
AddLibrary( libPath, aTable );
AddLibrary( aDialogTitle, libPath, libTable );
return libPath;
}
FP_LIB_TABLE* PCB_BASE_EDIT_FRAME::selectLibTable( bool aOptional )
wxString PCB_BASE_EDIT_FRAME::SelectLibrary( const wxString& aDialogTitle, const wxString& aListLabel,
const std::vector<std::pair<wxString, bool*>>& aExtraCheckboxes )
{
// If no project is loaded, always work with the global table
if( Prj().IsNullProject() )
// Keep asking the user for a new name until they give a valid one or cancel the operation
while( true )
{
FP_LIB_TABLE* ret = &GFootprintTable;
wxArrayString headers;
std::vector<wxArrayString> itemsToDisplay;
if( aOptional )
{
wxMessageDialog dlg( this, _( "Add the library to the global library table?" ),
_( "Add To Global Library Table" ), wxYES_NO );
GetLibraryItemsForListDialog( headers, itemsToDisplay );
if( dlg.ShowModal() != wxID_OK )
ret = nullptr;
}
wxString libraryName = Prj().GetRString( PROJECT::PCB_LIB_NICKNAME );
return ret;
}
EDA_LIST_DIALOG dlg( this, aDialogTitle, headers, itemsToDisplay, libraryName, false, aExtraCheckboxes );
dlg.SetListLabel( aListLabel );
wxArrayString libTableNames;
libTableNames.Add( _( "Global" ) );
libTableNames.Add( _( "Project" ) );
wxButton* newLibraryButton = new wxButton( &dlg, ID_MAKE_NEW_LIBRARY, _( "New Library..." ) );
dlg.m_ButtonsSizer->Prepend( 80, 20 );
dlg.m_ButtonsSizer->Prepend( newLibraryButton, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 10 );
wxSingleChoiceDialog dlg( this, _( "Choose the Library Table to add the library to:" ),
_( "Add To Library Table" ), libTableNames );
newLibraryButton->Bind( wxEVT_BUTTON,
[&dlg]( wxCommandEvent& )
{
dlg.EndModal( ID_MAKE_NEW_LIBRARY );
}, ID_MAKE_NEW_LIBRARY );
if( aOptional )
{
dlg.FindWindow( wxID_CANCEL )->SetLabel( _( "Skip" ) );
dlg.FindWindow( wxID_OK )->SetLabel( _( "Add" ) );
}
dlg.Layout();
dlg.GetSizer()->Fit( &dlg );
if( dlg.ShowModal() != wxID_OK )
return nullptr;
int ret = dlg.ShowModal();
switch( dlg.GetSelection() )
{
case 0: return &GFootprintTable;
case 1: return PROJECT_PCB::PcbFootprintLibs( &Prj() );
default: return nullptr;
switch( ret )
{
case wxID_CANCEL:
return wxEmptyString;
case wxID_OK:
libraryName = dlg.GetTextSelection();
Prj().SetRString( PROJECT::PCB_LIB_NICKNAME, libraryName );
dlg.GetExtraCheckboxValues();
return libraryName;
case ID_MAKE_NEW_LIBRARY:
{
wxFileName fn = CreateNewLibrary( _( "New Footprint Library" ),
Prj().GetRString( PROJECT::PCB_LIB_PATH ) );
Prj().SetRString( PROJECT::PCB_LIB_PATH, fn.GetPath() );
Prj().SetRString( PROJECT::PCB_LIB_NICKNAME, fn.GetName() );
break;
}
default:
break;
}
}
}
bool PCB_BASE_EDIT_FRAME::AddLibrary( const wxString& aFilename, FP_LIB_TABLE* aTable )
bool PCB_BASE_EDIT_FRAME::AddLibrary( const wxString& aDialogTitle, const wxString& aFilename,
FP_LIB_TABLE* aTable )
{
if( aTable == nullptr )
aTable = selectLibTable();
bool isGlobal = false;
FP_LIB_TABLE* libTable = PROJECT_PCB::PcbFootprintLibs( &Prj() );
FILEDLG_HOOK_NEW_LIBRARY tableChooser( isGlobal );
FILEDLG_HOOK_NEW_LIBRARY* fileDlgHook = &tableChooser;
if( aTable == nullptr )
return wxEmptyString;
bool isGlobal = ( aTable == &GFootprintTable );
if( aTable )
{
isGlobal = ( aTable == &GFootprintTable );
libTable = aTable;
fileDlgHook = nullptr;
}
wxFileName fn( aFilename );
if( aFilename.IsEmpty() )
{
if( !LibraryFileBrowser( true, fn, FILEEXT::KiCadFootprintLibPathWildcard(),
FILEEXT::KiCadFootprintLibPathExtension, true, isGlobal,
PATHS::GetDefaultUserFootprintsPath() ) )
if( !LibraryFileBrowser( aDialogTitle, true, fn, FILEEXT::KiCadFootprintLibPathWildcard(),
FILEEXT::KiCadFootprintLibPathExtension, true, fileDlgHook ) )
{
return false;
}
if( fileDlgHook )
{
isGlobal = fileDlgHook->GetUseGlobalTable();
libTable = isGlobal ? &GFootprintTable : PROJECT_PCB::PcbFootprintLibs( &Prj() );
}
}
wxString libPath = fn.GetFullPath();
@ -488,8 +522,7 @@ bool PCB_BASE_EDIT_FRAME::AddLibrary( const wxString& aFilename, FP_LIB_TABLE* a
// KiCad lib is our default guess. So it might not have the .pretty extension
// In this case, the extension is part of the library name
if( lib_type == PCB_IO_MGR::KICAD_SEXP
&& fn.GetExt() != FILEEXT::KiCadFootprintLibPathExtension )
if( lib_type == PCB_IO_MGR::KICAD_SEXP && fn.GetExt() != FILEEXT::KiCadFootprintLibPathExtension )
libName = fn.GetFullName();
// try to use path normalized to an environmental variable or project path
@ -498,12 +531,12 @@ bool PCB_BASE_EDIT_FRAME::AddLibrary( const wxString& aFilename, FP_LIB_TABLE* a
try
{
FP_LIB_TABLE_ROW* row = new FP_LIB_TABLE_ROW( libName, normalizedPath, type, wxEmptyString );
aTable->InsertRow( row );
libTable->InsertRow( row );
if( isGlobal )
GFootprintTable.Save( FP_LIB_TABLE::GetGlobalTableFileName() );
libTable->Save( FP_LIB_TABLE::GetGlobalTableFileName() );
else
PROJECT_PCB::PcbFootprintLibs( &Prj() )->Save( Prj().FootprintLibTblName() );
libTable->Save( Prj().FootprintLibTblName() );
}
catch( const IO_ERROR& ioe )
{
@ -600,130 +633,51 @@ void PCB_EDIT_FRAME::ExportFootprintsToLibrary( bool aStoreInNewLib, const wxStr
return;
}
auto resetReference =
[]( FOOTPRINT* aFootprint )
{
aFootprint->SetReference( "REF**" );
};
bool map = false;
PROJECT& prj = Prj();
wxString nickname = SelectLibrary( _( "Export Footprints" ), _( "Export footprints to library:" ),
{ { _( "Update board footprints to link to exported footprints" ), &map } } );
auto resetGroup =
[]( FOOTPRINT* aFootprint )
{
if( EDA_GROUP* parentGroup = aFootprint->GetParentGroup() )
parentGroup->RemoveItem( aFootprint );
};
if( !nickname ) // Aborted
return;
auto resetZones =
[]( FOOTPRINT* aFootprint )
{
for( ZONE* zone : aFootprint->Zones() )
zone->Move( -aFootprint->GetPosition() );
};
prj.SetRString( PROJECT::PCB_LIB_NICKNAME, nickname );
if( !aStoreInNewLib )
for( FOOTPRINT* footprint : GetBoard()->Footprints() )
{
// The footprints are saved in an existing .pretty library in the fp lib table
PROJECT& prj = Prj();
wxString last_nickname = prj.GetRString( PROJECT::PCB_LIB_NICKNAME );
wxString nickname = SelectLibrary( last_nickname );
if( !nickname ) // Aborted
return;
bool map = IsOK( this, wxString::Format( _( "Update footprints on board to refer to %s?" ),
nickname ) );
prj.SetRString( PROJECT::PCB_LIB_NICKNAME, nickname );
for( FOOTPRINT* footprint : GetBoard()->Footprints() )
try
{
try
FP_LIB_TABLE* tbl = PROJECT_PCB::PcbFootprintLibs( &prj );
if( !footprint->GetFPID().GetLibItemName().empty() ) // Handle old boards.
{
FP_LIB_TABLE* tbl = PROJECT_PCB::PcbFootprintLibs( &prj );
FOOTPRINT* fpCopy = static_cast<FOOTPRINT*>( footprint->Duplicate( IGNORE_PARENT_GROUP ) );
if( !footprint->GetFPID().GetLibItemName().empty() ) // Handle old boards.
{
FOOTPRINT* fpCopy = static_cast<FOOTPRINT*>( footprint->Duplicate( IGNORE_PARENT_GROUP ) );
// Reset reference designator, group membership, and zone offset before saving
// Reset reference designator and group membership before saving
resetReference( fpCopy );
resetGroup( fpCopy );
resetZones( fpCopy );
fpCopy->SetReference( "REF**" );
tbl->FootprintSave( nickname, fpCopy, true );
if( EDA_GROUP* parentGroup = fpCopy->GetParentGroup() )
parentGroup->RemoveItem( fpCopy );
delete fpCopy;
}
}
catch( const IO_ERROR& ioe )
{
DisplayError( this, ioe.What() );
}
for( ZONE* zone : fpCopy->Zones() )
zone->Move( -fpCopy->GetPosition() );
if( map )
{
LIB_ID id = footprint->GetFPID();
id.SetLibNickname( nickname );
footprint->SetFPID( id );
tbl->FootprintSave( nickname, fpCopy, true );
delete fpCopy;
}
}
}
else
{
// The footprints are saved in a new .pretty library.
// If this library already exists, all previous footprints will be deleted
wxString libPath = CreateNewLibrary( aLibName );
if( libPath.IsEmpty() ) // Aborted
return;
if( aLibPath )
*aLibPath = libPath;
wxString libNickname;
bool map = IsOK( this, _( "Update footprints on board to refer to new library?" ) );
if( map )
catch( const IO_ERROR& ioe )
{
const LIB_TABLE_ROW* row = PROJECT_PCB::PcbFootprintLibs( &Prj() )->FindRowByURI( libPath );
if( row )
libNickname = row->GetNickName();
DisplayError( this, ioe.What() );
}
PCB_IO_MGR::PCB_FILE_T piType = PCB_IO_MGR::KICAD_SEXP;
IO_RELEASER<PCB_IO> pi( PCB_IO_MGR::PluginFind( piType ) );
std::map<std::string, UTF8> options { { "skip_cache_validation", "1" } }; // Skip cache validation -- we just created it
for( FOOTPRINT* footprint : GetBoard()->Footprints() )
if( map )
{
try
{
if( !footprint->GetFPID().GetLibItemName().empty() ) // Handle old boards.
{
FOOTPRINT* fpCopy = static_cast<FOOTPRINT*>( footprint->Duplicate( IGNORE_PARENT_GROUP ) );
// Reset reference designator and group membership before saving
resetReference( fpCopy );
resetGroup( fpCopy );
resetZones( fpCopy );
pi->FootprintSave( libPath, fpCopy, &options );
delete fpCopy;
}
}
catch( const IO_ERROR& ioe )
{
DisplayError( this, ioe.What() );
}
if( map )
{
LIB_ID id = footprint->GetFPID();
id.SetLibNickname( libNickname );
footprint->SetFPID( id );
}
LIB_ID id = footprint->GetFPID();
id.SetLibNickname( nickname );
footprint->SetFPID( id );
}
}
}
@ -1000,9 +954,6 @@ bool FOOTPRINT_EDIT_FRAME::SaveFootprintToBoard( bool aAddNew )
}
static int ID_MAKE_NEW_LIBRARY = 4173;
class SAVE_AS_DIALOG : public EDA_LIST_DIALOG
{
public:
@ -1012,41 +963,12 @@ public:
EDA_LIST_DIALOG( aParent, _( "Save Footprint As" ), false ),
m_validator( std::move( aValidator ) )
{
COMMON_SETTINGS* cfg = Pgm().GetCommonSettings();
PROJECT_FILE& project = aParent->Prj().GetProjectFile();
FP_LIB_TABLE* tbl = PROJECT_PCB::PcbFootprintLibs( &aParent->Prj() );
std::vector<wxString> nicknames = tbl->GetLogicalLibs();
wxArrayString headers;
std::vector<wxArrayString> itemsToDisplay;
headers.Add( _( "Nickname" ) );
headers.Add( _( "Description" ) );
for( const wxString& nickname : nicknames )
{
if( alg::contains( project.m_PinnedFootprintLibs, nickname )
|| alg::contains( cfg->m_Session.pinned_fp_libs, nickname ) )
{
wxArrayString item;
item.Add( LIB_TREE_MODEL_ADAPTER::GetPinningSymbol() + nickname );
item.Add( tbl->GetDescription( nickname ) );
itemsToDisplay.push_back( item );
}
}
for( const wxString& nickname : nicknames )
{
if( !alg::contains( project.m_PinnedFootprintLibs, nickname )
&& !alg::contains( cfg->m_Session.pinned_fp_libs, nickname ) )
{
wxArrayString item;
item.Add( nickname );
item.Add( tbl->GetDescription( nickname ) );
itemsToDisplay.push_back( item );
}
}
aParent->GetLibraryItemsForListDialog( headers, itemsToDisplay );
initDialog( headers, itemsToDisplay, aLibraryPreselect );
SetListLabel( _( "Save in library:" ) );
@ -1162,8 +1084,7 @@ bool FOOTPRINT_EDIT_FRAME::SaveFootprintAs( FOOTPRINT* aFootprint )
newName,
newLib );
KIDIALOG errorDlg( this, msg, _( "Confirmation" ),
wxOK | wxCANCEL | wxICON_WARNING );
KIDIALOG errorDlg( this, msg, _( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
errorDlg.SetOKLabel( _( "Overwrite" ) );
return errorDlg.ShowModal() == wxID_OK;
@ -1186,8 +1107,12 @@ bool FOOTPRINT_EDIT_FRAME::SaveFootprintAs( FOOTPRINT* aFootprint )
}
else if( ret == ID_MAKE_NEW_LIBRARY )
{
wxFileName newLibrary( CreateNewLibrary() );
libraryName = newLibrary.GetName();
wxFileName fn = CreateNewLibrary( _( "New Footprint Library" ),
Prj().GetRString( PROJECT::PCB_LIB_PATH ) );
Prj().SetRString( PROJECT::PCB_LIB_PATH, fn.GetPath() );
Prj().SetRString( PROJECT::PCB_LIB_NICKNAME, fn.GetName() );
libraryName = fn.GetName();
}
}
@ -1351,18 +1276,16 @@ FOOTPRINT* PCB_BASE_FRAME::CreateNewFootprint( wxString aFootprintName, const wx
}
wxString PCB_BASE_FRAME::SelectLibrary( const wxString& aNicknameExisting )
void PCB_BASE_FRAME::GetLibraryItemsForListDialog( wxArrayString& aHeaders,
std::vector<wxArrayString>& aItemsToDisplay )
{
wxArrayString headers;
headers.Add( _( "Nickname" ) );
headers.Add( _( "Description" ) );
aHeaders.Add( _( "Library" ) );
aHeaders.Add( _( "Description" ) );
COMMON_SETTINGS* cfg = Pgm().GetCommonSettings();
PROJECT_FILE& project = Kiway().Prj().GetProjectFile();
FP_LIB_TABLE* fptbl = PROJECT_PCB::PcbFootprintLibs( &Prj() );
std::vector< wxArrayString > itemsToDisplay;
std::vector< wxString > nicknames = fptbl->GetLogicalLibs();
COMMON_SETTINGS* cfg = Pgm().GetCommonSettings();
PROJECT_FILE& project = Kiway().Prj().GetProjectFile();
FP_LIB_TABLE* fptbl = PROJECT_PCB::PcbFootprintLibs( &Prj() );
std::vector<wxString> nicknames = fptbl->GetLogicalLibs();
for( const wxString& nickname : nicknames )
{
@ -1373,7 +1296,7 @@ wxString PCB_BASE_FRAME::SelectLibrary( const wxString& aNicknameExisting )
item.Add( LIB_TREE_MODEL_ADAPTER::GetPinningSymbol() + nickname );
item.Add( fptbl->GetDescription( nickname ) );
itemsToDisplay.push_back( item );
aItemsToDisplay.push_back( item );
}
}
@ -1386,15 +1309,9 @@ wxString PCB_BASE_FRAME::SelectLibrary( const wxString& aNicknameExisting )
item.Add( nickname );
item.Add( fptbl->GetDescription( nickname ) );
itemsToDisplay.push_back( item );
aItemsToDisplay.push_back( item );
}
}
}
EDA_LIST_DIALOG dlg( this, _( "Select Library" ), headers, itemsToDisplay, aNicknameExisting,
false );
if( dlg.ShowModal() != wxID_OK )
return wxEmptyString;
return dlg.GetTextSelection();
}

2
pcbnew/load_select_footprint.cpp

@ -327,7 +327,7 @@ FOOTPRINT* FOOTPRINT_EDIT_FRAME::SelectFootprintFromBoard( BOARD* aPcb )
bool FOOTPRINT_EDIT_FRAME::SaveLibraryAs( const wxString& aLibraryPath )
{
const wxString& curLibPath = aLibraryPath;
wxString dstLibPath = CreateNewLibrary( wxEmptyString, aLibraryPath );
wxString dstLibPath = CreateNewLibrary( _( "Save Footprint Library As" ), aLibraryPath );
if( !dstLibPath )
return false; // user aborted in CreateNewLibrary()

3
pcbnew/menubar_pcb_editor.cpp

@ -133,8 +133,7 @@ void PCB_EDIT_FRAME::doReCreateMenuBar()
submenuExport->Add( *m_exportNetlistAction );
submenuExport->AppendSeparator();
submenuExport->Add( PCB_ACTIONS::exportFootprints );
submenuExport->Add( PCB_ACTIONS::exportFootprintsAs );
submenuExport->Add( PCB_ACTIONS::exportFootprints, ACTION_MENU::NORMAL, _( "Footprints..." ) );
fileMenu->Add( submenuExport );

40
pcbnew/pcb_base_edit_frame.h

@ -37,6 +37,7 @@ class PCB_TEXTBOX;
class PCB_TABLE;
class PCB_TEXT;
class PCB_SHAPE;
class FILEDLG_HOOK_NEW_LIBRARY;
/**
* Common, abstract interface for edit frames.
@ -61,15 +62,27 @@ public:
* If library exists, user is warned about that, and is given a chance
* to abort the new creation, and in that case existing library is first deleted.
*
* @param aProposedName is the initial path and filename shown in the file chooser dialog.
* @param aDialogTitle title for the file browser
* @param aInitialPath is the initial path and filename shown in the file chooser dialog.
* @return The newly created library path if library was successfully created, else
* wxEmptyString because user aborted or error.
*/
wxString CreateNewLibrary( const wxString& aLibName = wxEmptyString,
const wxString& aProposedName = wxEmptyString );
wxString CreateNewLibrary( const wxString& aDialogTitle, const wxString& aInitialPath = wxEmptyString );
wxString CreateNewProjectLibrary( const wxString& aLibName = wxEmptyString,
const wxString& aProposedName = wxEmptyString );
wxString CreateNewProjectLibrary( const wxString& aDialogTitle, const wxString& aLibName );
/**
* Put up a dialog and allows the user to pick a library, for unspecified use.
*
* @param aDialogTitle title for the dialog window
* @param aListLabel label for the list of libraries
* @param aExtraCheckboxes [optional] list of label/valuePointer pairs from which to construct extra
* checkboxes in the dialog. Values are written back to the pointers when
* the dialog is finished.
* @return the library or wxEmptyString on abort.
*/
wxString SelectLibrary( const wxString& aDialogTitle, const wxString& aListLabel,
const std::vector<std::pair<wxString, bool*>>& aExtraCheckboxes = {} );
/**
* Add an existing library to either the global or project library table.
@ -77,7 +90,8 @@ public:
* @param aFileName the library to add; a file open dialog will be displayed if empty.
* @return true if successfully added.
*/
bool AddLibrary( const wxString& aLibName = wxEmptyString, FP_LIB_TABLE* aTable = nullptr );
bool AddLibrary( const wxString& aDialogTitle, const wxString& aLibName = wxEmptyString,
FP_LIB_TABLE* aTable = nullptr );
/**
* Install the corresponding dialog editor for the given item.
@ -235,18 +249,10 @@ protected:
void configureToolbars() override;
/**
* Prompts a user to select global or project library tables
*
* @return Pointer to library table selected or nullptr if none selected/canceled
*/
FP_LIB_TABLE* selectLibTable( bool aOptional = false );
/**
* Create a new library in the given table (presumed to be either the global or project
* library table).
* Create a new library in the given table. (The user will be consulted if the table is null.)
*/
wxString createNewLibrary( const wxString& aLibName, const wxString& aProposedName,
FP_LIB_TABLE* aTable );
wxString createNewLibrary( const wxString& aDialogTitle, const wxString& aLibName,
const wxString& aInitialPath, FP_LIB_TABLE* aTable );
void handleActivateEvent( wxActivateEvent& aEvent ) override;

8
pcbnew/tools/board_editor_control.cpp

@ -282,13 +282,6 @@ int BOARD_EDITOR_CONTROL::ExportFootprints( const TOOL_EVENT& aEvent )
}
int BOARD_EDITOR_CONTROL::ExportFootprintsAs( const TOOL_EVENT& aEvent )
{
m_frame->ExportFootprintsToLibrary( true );
return 0;
}
int BOARD_EDITOR_CONTROL::PageSettings( const TOOL_EVENT& aEvent )
{
PICKED_ITEMS_LIST undoCmd;
@ -1798,7 +1791,6 @@ void BOARD_EDITOR_CONTROL::setTransitions()
Go( &BOARD_EDITOR_CONTROL::RescueAutosave, PCB_ACTIONS::rescueAutosave.MakeEvent() );
Go( &BOARD_EDITOR_CONTROL::OpenNonKicadBoard, PCB_ACTIONS::openNonKicadBoard.MakeEvent() );
Go( &BOARD_EDITOR_CONTROL::ExportFootprints, PCB_ACTIONS::exportFootprints.MakeEvent() );
Go( &BOARD_EDITOR_CONTROL::ExportFootprintsAs, PCB_ACTIONS::exportFootprintsAs.MakeEvent() );
Go( &BOARD_EDITOR_CONTROL::BoardSetup, PCB_ACTIONS::boardSetup.MakeEvent() );
Go( &BOARD_EDITOR_CONTROL::ImportNetlist, PCB_ACTIONS::importNetlist.MakeEvent() );
Go( &BOARD_EDITOR_CONTROL::ImportSpecctraSession, PCB_ACTIONS::importSpecctraSession.MakeEvent() );

1
pcbnew/tools/board_editor_control.h

@ -60,7 +60,6 @@ public:
int RescueAutosave( const TOOL_EVENT& aEvent );
int OpenNonKicadBoard( const TOOL_EVENT& aEvent );
int ExportFootprints( const TOOL_EVENT& aEvent );
int ExportFootprintsAs( const TOOL_EVENT& aEvent );
int PageSettings( const TOOL_EVENT& aEvent );
int Plot( const TOOL_EVENT& aEvent );

12
pcbnew/tools/pcb_actions.cpp

@ -1154,19 +1154,11 @@ TOOL_ACTION PCB_ACTIONS::openNonKicadBoard( TOOL_ACTION_ARGS()
TOOL_ACTION PCB_ACTIONS::exportFootprints( TOOL_ACTION_ARGS()
.Name( "pcbnew.EditorControl.exportFootprints" )
.Scope( AS_GLOBAL )
.FriendlyName( _( "Footprints to Library..." ) )
.Tooltip( _( "Add footprints used on board to an existing footprint library\n"
.FriendlyName( _( "Export Footprints..." ) )
.Tooltip( _( "Add footprints from board to a new or an existing footprint library\n"
"(does not remove other footprints from this library)" ) )
.Icon( BITMAPS::library_archive ) );
TOOL_ACTION PCB_ACTIONS::exportFootprintsAs( TOOL_ACTION_ARGS()
.Name( "pcbnew.EditorControl.exportFootprintsAs" )
.Scope( AS_GLOBAL )
.FriendlyName( _( "Footprints to New Library..." ) )
.Tooltip( _( "Create a new footprint library containing the footprints used on board\n"
"(if the library already exists it will be replaced)" ) )
.Icon( BITMAPS::library_archive_as ) );
TOOL_ACTION PCB_ACTIONS::boardSetup( TOOL_ACTION_ARGS()
.Name( "pcbnew.EditorControl.boardSetup" )
.Scope( AS_GLOBAL )

1
pcbnew/tools/pcb_actions.h

@ -406,7 +406,6 @@ public:
static TOOL_ACTION rescueAutosave;
static TOOL_ACTION openNonKicadBoard;
static TOOL_ACTION exportFootprints;
static TOOL_ACTION exportFootprintsAs;
static TOOL_ACTION boardSetup;
static TOOL_ACTION importNetlist;

8
pcbnew/tools/pcb_control.cpp

@ -53,6 +53,7 @@
#include <pcb_textbox.h>
#include <pcb_track.h>
#include <pcb_generator.h>
#include <project_pcb.h>
#include <wildcards_and_files_ext.h>
#include <zone.h>
#include <confirm.h>
@ -117,9 +118,9 @@ int PCB_CONTROL::AddLibrary( const TOOL_EVENT& aEvent )
if( m_frame->IsType( FRAME_FOOTPRINT_EDITOR ) || m_frame->IsType( FRAME_PCB_EDITOR ) )
{
if( aEvent.IsAction( &ACTIONS::newLibrary ) )
static_cast<PCB_BASE_EDIT_FRAME*>( m_frame )->CreateNewLibrary();
static_cast<PCB_BASE_EDIT_FRAME*>( m_frame )->CreateNewLibrary( _( "New Footprint Library" ) );
else if( aEvent.IsAction( &ACTIONS::addLibrary ) )
static_cast<PCB_BASE_EDIT_FRAME*>( m_frame )->AddLibrary();
static_cast<PCB_BASE_EDIT_FRAME*>( m_frame )->AddLibrary( _( "Add Footprint Library" ) );
}
return 0;
@ -149,7 +150,8 @@ int PCB_CONTROL::SaveFpToBoard( const TOOL_EVENT& aEvent )
int PCB_CONTROL::DdAddLibrary( const TOOL_EVENT& aEvent )
{
const wxString fn = *aEvent.Parameter<wxString*>();
static_cast<PCB_BASE_EDIT_FRAME*>( m_frame )->AddLibrary( fn );
static_cast<PCB_BASE_EDIT_FRAME*>( m_frame )->AddLibrary( _( "Add Footprint Library" ), fn,
PROJECT_PCB::PcbFootprintLibs( &m_frame->Prj() ) );
return 0;
}

Loading…
Cancel
Save