diff --git a/3d-viewer/3d_frame.cpp b/3d-viewer/3d_frame.cpp index 9410acc940..d509ebcb66 100644 --- a/3d-viewer/3d_frame.cpp +++ b/3d-viewer/3d_frame.cpp @@ -116,7 +116,7 @@ END_EVENT_TABLE() EDA_3D_FRAME::EDA_3D_FRAME( KIWAY* aKiway, PCB_BASE_FRAME* aParent, const wxString& aTitle, long style ) : KIWAY_PLAYER( aKiway, aParent, FRAME_PCB_DISPLAY3D, aTitle, - wxDefaultPosition, wxDefaultSize, style, wxT( "Frame3D" ) ) + wxDefaultPosition, wxDefaultSize, style, VIEWER3D_FRAMENAME ) { m_canvas = NULL; m_reloadRequest = false; @@ -227,6 +227,7 @@ EDA_3D_FRAME::~EDA_3D_FRAME() m_auimgr.UnInit(); } + void EDA_3D_FRAME::Exit3DFrame( wxCommandEvent& event ) { Close( true ); @@ -235,9 +236,6 @@ void EDA_3D_FRAME::Exit3DFrame( wxCommandEvent& event ) void EDA_3D_FRAME::OnCloseWindow( wxCloseEvent& Event ) { - if( Parent() ) - Parent()->m_Draw3DFrame = NULL; - Destroy(); } diff --git a/3d-viewer/3d_viewer.h b/3d-viewer/3d_viewer.h index 25c32d6a26..3412288d35 100644 --- a/3d-viewer/3d_viewer.h +++ b/3d-viewer/3d_viewer.h @@ -54,6 +54,8 @@ class wxColourData; #define KICAD_DEFAULT_3D_DRAWFRAME_STYLE (wxDEFAULT_FRAME_STYLE | wxWANTS_CHARS) +#define VIEWER3D_FRAMENAME wxT( "Viewer3DFrameName" ) + class EDA_3D_FRAME : public KIWAY_PLAYER { diff --git a/CMakeLists.txt b/CMakeLists.txt index 8f17a0690b..e54f90880f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -478,6 +478,9 @@ endif() # Find GLM library find_package( GLM 0.9.5.4 REQUIRED ) +# Find CURL library +find_package( CURL REQUIRED ) + # Find Cairo library if( NOT CAIRO_FOUND ) find_package( Cairo 1.8.1 QUIET ) diff --git a/README.txt b/README.txt index 5a7fe278f9..ab05f7562e 100644 --- a/README.txt +++ b/README.txt @@ -11,9 +11,9 @@ CMakeList.txt - CMAKE build tool script COPYRIGHT.txt - A copy of the GNU General Public License Version 2 CTestConfig.cmake - Support for CTest and CDash testing tools Doxyfile - Doxygen config file for Kicad -INSTALL.txt - The release (binairy) installation instructions +INSTALL.txt - The release (binary) installation instructions TODO.txt - Todo list -uncrustify.cfg - Uncrustify config file for uncrustify sorces formatting tool +uncrustify.cfg - Uncrustify config file for uncrustify sources formatting tool Subdirectories -------------- diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 27267186ef..9d8b71fc09 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -5,6 +5,7 @@ include_directories( ${CAIRO_INCLUDE_DIR} ${GLEW_INCLUDE_DIR} ${GLM_INCLUDE_DIR} + ${CURL_INCLUDE_DIRS} ../3d-viewer ../pcbnew ../polygon @@ -201,6 +202,7 @@ set( COMMON_SRCS dsnlexer.cpp eda_dde.cpp eda_doc.cpp + eda_pattern_match.cpp filter_reader.cpp # findkicadhelppath.cpp.notused deprecated, use searchhelpfilefullpath.cpp gestfich.cpp @@ -253,6 +255,9 @@ endif() set( COMMON_SRCS ${COMMON_SRCS} + kicad_curl/kicad_curl.cpp + kicad_curl/kicad_curl_easy.cpp + view/view.cpp view/view_item.cpp view/view_group.cpp @@ -278,7 +283,7 @@ set( COMMON_SRCS add_library( common STATIC ${COMMON_SRCS} ) add_dependencies( common lib-dependencies ) add_dependencies( common version_header ) -target_link_libraries( common ${Boost_LIBRARIES} ) +target_link_libraries( common ${Boost_LIBRARIES} ${CURL_LIBRARIES} ) set( PCB_COMMON_SRCS diff --git a/common/dialogs/dialog_get_component_base.cpp b/common/dialogs/dialog_get_component_base.cpp index 8e8810c5d0..527278736f 100644 --- a/common/dialogs/dialog_get_component_base.cpp +++ b/common/dialogs/dialog_get_component_base.cpp @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////// -// C++ code generated with wxFormBuilder (version Nov 5 2013) +// C++ code generated with wxFormBuilder (version Jun 17 2015) // http://www.wxformbuilder.org/ // // PLEASE DO "NOT" EDIT THIS FILE! @@ -14,7 +14,10 @@ DIALOG_GET_COMPONENT_BASE::DIALOG_GET_COMPONENT_BASE( wxWindow* parent, wxWindow this->SetSizeHints( wxDefaultSize, wxDefaultSize ); wxBoxSizer* bSizerMain; - bSizerMain = new wxBoxSizer( wxHORIZONTAL ); + bSizerMain = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizerUpper; + bSizerUpper = new wxBoxSizer( wxHORIZONTAL ); wxBoxSizer* bSizerLeft; bSizerLeft = new wxBoxSizer( wxVERTICAL ); @@ -34,24 +37,17 @@ DIALOG_GET_COMPONENT_BASE::DIALOG_GET_COMPONENT_BASE( wxWindow* parent, wxWindow m_historyList = new wxListBox( this, ID_SEL_BY_LISTBOX, wxDefaultPosition, wxDefaultSize, 0, NULL, 0 ); m_historyList->SetMinSize( wxSize( 200,100 ) ); - bSizerLeft->Add( m_historyList, 1, wxALL|wxEXPAND, 5 ); + bSizerLeft->Add( m_historyList, 1, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); - bSizerMain->Add( bSizerLeft, 1, wxEXPAND, 5 ); + bSizerUpper->Add( bSizerLeft, 1, wxEXPAND, 5 ); wxBoxSizer* bSizerRight; bSizerRight = new wxBoxSizer( wxVERTICAL ); - m_buttonOK = new wxButton( this, wxID_OK, _("OK"), wxDefaultPosition, wxDefaultSize, 0 ); - m_buttonOK->SetDefault(); - bSizerRight->Add( m_buttonOK, 0, wxALL|wxEXPAND, 5 ); - m_buttonKW = new wxButton( this, ID_ACCEPT_KEYWORD, _("Search by Keyword"), wxDefaultPosition, wxDefaultSize, 0 ); bSizerRight->Add( m_buttonKW, 0, wxALL|wxEXPAND, 5 ); - m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizerRight->Add( m_buttonCancel, 0, wxALL|wxEXPAND, 5 ); - m_buttonList = new wxButton( this, ID_LIST_ALL, _("List All"), wxDefaultPosition, wxDefaultSize, 0 ); bSizerRight->Add( m_buttonList, 0, wxALL|wxEXPAND, 5 ); @@ -59,32 +55,46 @@ DIALOG_GET_COMPONENT_BASE::DIALOG_GET_COMPONENT_BASE( wxWindow* parent, wxWindow bSizerRight->Add( m_buttonBrowse, 0, wxALL|wxEXPAND, 5 ); - bSizerMain->Add( bSizerRight, 0, wxALIGN_CENTER_VERTICAL, 5 ); + bSizerUpper->Add( bSizerRight, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + + bSizerMain->Add( bSizerUpper, 1, wxEXPAND, 5 ); + + m_staticline1 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizerMain->Add( m_staticline1, 0, wxEXPAND|wxTOP|wxRIGHT, 5 ); + + m_sdbSizer = new wxStdDialogButtonSizer(); + m_sdbSizerOK = new wxButton( this, wxID_OK ); + m_sdbSizer->AddButton( m_sdbSizerOK ); + m_sdbSizerCancel = new wxButton( this, wxID_CANCEL ); + m_sdbSizer->AddButton( m_sdbSizerCancel ); + m_sdbSizer->Realize(); + + bSizerMain->Add( m_sdbSizer, 0, wxEXPAND|wxALL, 5 ); this->SetSizer( bSizerMain ); this->Layout(); - bSizerMain->Fit( this ); this->Centre( wxBOTH ); // Connect Events m_historyList->Connect( wxEVT_COMMAND_LISTBOX_SELECTED, wxCommandEventHandler( DIALOG_GET_COMPONENT_BASE::Accept ), NULL, this ); - m_buttonOK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_GET_COMPONENT_BASE::Accept ), NULL, this ); m_buttonKW->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_GET_COMPONENT_BASE::Accept ), NULL, this ); - m_buttonCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_GET_COMPONENT_BASE::OnCancel ), NULL, this ); m_buttonList->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_GET_COMPONENT_BASE::Accept ), NULL, this ); m_buttonBrowse->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_GET_COMPONENT_BASE::GetExtraSelection ), NULL, this ); + m_sdbSizerCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_GET_COMPONENT_BASE::OnCancel ), NULL, this ); + m_sdbSizerOK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_GET_COMPONENT_BASE::Accept ), NULL, this ); } DIALOG_GET_COMPONENT_BASE::~DIALOG_GET_COMPONENT_BASE() { // Disconnect Events m_historyList->Disconnect( wxEVT_COMMAND_LISTBOX_SELECTED, wxCommandEventHandler( DIALOG_GET_COMPONENT_BASE::Accept ), NULL, this ); - m_buttonOK->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_GET_COMPONENT_BASE::Accept ), NULL, this ); m_buttonKW->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_GET_COMPONENT_BASE::Accept ), NULL, this ); - m_buttonCancel->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_GET_COMPONENT_BASE::OnCancel ), NULL, this ); m_buttonList->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_GET_COMPONENT_BASE::Accept ), NULL, this ); m_buttonBrowse->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_GET_COMPONENT_BASE::GetExtraSelection ), NULL, this ); + m_sdbSizerCancel->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_GET_COMPONENT_BASE::OnCancel ), NULL, this ); + m_sdbSizerOK->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_GET_COMPONENT_BASE::Accept ), NULL, this ); } diff --git a/common/dialogs/dialog_get_component_base.fbp b/common/dialogs/dialog_get_component_base.fbp index 10a950c93f..51733f03e4 100644 --- a/common/dialogs/dialog_get_component_base.fbp +++ b/common/dialogs/dialog_get_component_base.fbp @@ -1,6 +1,6 @@ - + C++ @@ -44,7 +44,7 @@ DIALOG_GET_COMPONENT_BASE - -1,-1 + 361,285 wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER DIALOG_SHIM; dialog_shim.h @@ -91,7 +91,7 @@ bSizerMain - wxHORIZONTAL + wxVERTICAL none 5 @@ -99,805 +99,747 @@ 1 - bSizerLeft - wxVERTICAL + bSizerUpper + wxHORIZONTAL none 5 - wxTOP|wxRIGHT|wxLEFT - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - Name: - - 0 - - - 0 - - 1 - m_staticTextName - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - - - - - -1 - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 - wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - - 0 - - 0 - - 0 - - 1 - m_textCmpNameCtrl - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 - wxTOP|wxRIGHT|wxLEFT - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - History list: - - 0 - - - 0 - - 1 - m_staticTextHistory - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - - - - - -1 - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 - wxALL|wxEXPAND + wxEXPAND 1 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - ID_SEL_BY_LISTBOX - - 0 - - - 0 - 200,100 - 1 - m_historyList - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - - - - - - - - Accept - - - - - - - - - - - - - - + + + bSizerLeft + wxVERTICAL + none + + 5 + wxTOP|wxRIGHT|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Name: + + 0 + + + 0 + + 1 + m_staticTextName + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + 0 + + 0 + + 1 + m_textCmpNameCtrl + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxTOP|wxRIGHT|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + History list: + + 0 + + + 0 + + 1 + m_staticTextHistory + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + ID_SEL_BY_LISTBOX + + 0 + + + 0 + 200,100 + 1 + m_historyList + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + + + + Accept + + + + + + + + + + + + + + + + + + + + 5 + wxALIGN_CENTER_VERTICAL + 0 + + + bSizerRight + wxVERTICAL + none + + 5 + wxALL|wxEXPAND + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + ID_ACCEPT_KEYWORD + Search by Keyword + + 0 + + + 0 + + 1 + m_buttonKW + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + Accept + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALL|wxEXPAND + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + ID_LIST_ALL + List All + + 0 + + + 0 + + 1 + m_buttonList + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + Accept + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALL|wxEXPAND + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + ID_EXTRA_TOOL + Select by Browser + + 0 + + + 0 + + 1 + m_buttonBrowse + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + GetExtraSelection + + + + + + + + + + + + + + + + + + + + + + + + + 5 - wxALIGN_CENTER_VERTICAL + wxEXPAND|wxTOP|wxRIGHT 0 - + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 - bSizerRight - wxVERTICAL - none - - 5 - wxALL|wxEXPAND - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_OK - OK - - 0 - - - 0 - - 1 - m_buttonOK - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - Accept - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 - wxALL|wxEXPAND - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - ID_ACCEPT_KEYWORD - Search by Keyword - - 0 - - - 0 - - 1 - m_buttonKW - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - Accept - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 - wxALL|wxEXPAND - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_CANCEL - Cancel - - 0 - - - 0 - - 1 - m_buttonCancel - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - OnCancel - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 - wxALL|wxEXPAND - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - ID_LIST_ALL - List All - - 0 - - - 0 - - 1 - m_buttonList - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - Accept - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 - wxALL|wxEXPAND - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - ID_EXTRA_TOOL - Select by Browser - - 0 - - - 0 - - 1 - m_buttonBrowse - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - GetExtraSelection - - - - - - - - - - - - - - - - - - - - - - - - - + 1 + m_staticline1 + 1 + + + protected + 1 + + Resizable + 1 + + wxLI_HORIZONTAL + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxEXPAND|wxALL + 0 + + 0 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + + m_sdbSizer + protected + + OnCancel + + + + Accept + + diff --git a/common/dialogs/dialog_get_component_base.h b/common/dialogs/dialog_get_component_base.h index a0a39d5b27..37cb943b24 100644 --- a/common/dialogs/dialog_get_component_base.h +++ b/common/dialogs/dialog_get_component_base.h @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////// -// C++ code generated with wxFormBuilder (version Nov 5 2013) +// C++ code generated with wxFormBuilder (version Jun 17 2015) // http://www.wxformbuilder.org/ // // PLEASE DO "NOT" EDIT THIS FILE! @@ -24,6 +24,7 @@ class DIALOG_SHIM; #include #include #include +#include #include /////////////////////////////////////////////////////////////////////////// @@ -45,21 +46,23 @@ class DIALOG_GET_COMPONENT_BASE : public DIALOG_SHIM wxTextCtrl* m_textCmpNameCtrl; wxStaticText* m_staticTextHistory; wxListBox* m_historyList; - wxButton* m_buttonOK; wxButton* m_buttonKW; - wxButton* m_buttonCancel; wxButton* m_buttonList; wxButton* m_buttonBrowse; + wxStaticLine* m_staticline1; + wxStdDialogButtonSizer* m_sdbSizer; + wxButton* m_sdbSizerOK; + wxButton* m_sdbSizerCancel; // Virtual event handlers, overide them in your derived class virtual void Accept( wxCommandEvent& event ) { event.Skip(); } - virtual void OnCancel( wxCommandEvent& event ) { event.Skip(); } virtual void GetExtraSelection( wxCommandEvent& event ) { event.Skip(); } + virtual void OnCancel( wxCommandEvent& event ) { event.Skip(); } public: - DIALOG_GET_COMPONENT_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); + DIALOG_GET_COMPONENT_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 361,285 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); ~DIALOG_GET_COMPONENT_BASE(); }; diff --git a/common/eda_pattern_match.cpp b/common/eda_pattern_match.cpp new file mode 100644 index 0000000000..cc4b8bf787 --- /dev/null +++ b/common/eda_pattern_match.cpp @@ -0,0 +1,137 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Chris Pavlina + * Copyright (C) 2015 KiCad Developers, see change_log.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 2 + * 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, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include +#include +#include + +bool EDA_PATTERN_MATCH_SUBSTR::SetPattern( const wxString& aPattern ) +{ + m_pattern = aPattern; + return true; +} + + +int EDA_PATTERN_MATCH_SUBSTR::Find( const wxString& aCandidate ) const +{ + int loc = aCandidate.Find( m_pattern ); + + return ( loc == wxNOT_FOUND ) ? EDA_PATTERN_NOT_FOUND : loc; +} + + +/** + * Context class to set wx loglevel for a block, and always restore it at the end. + */ +class WX_LOGLEVEL_CONTEXT +{ + wxLogLevel m_old_level; + +public: + WX_LOGLEVEL_CONTEXT( wxLogLevel level ) + { + m_old_level = wxLog::GetLogLevel(); + wxLog::SetLogLevel( level ); + } + + ~WX_LOGLEVEL_CONTEXT() + { + wxLog::SetLogLevel( m_old_level ); + } +}; + + +bool EDA_PATTERN_MATCH_REGEX::SetPattern( const wxString& aPattern ) +{ + m_pattern = aPattern; + + // Evil and undocumented: wxRegEx::Compile calls wxLogError on error, even + // though it promises to just return false. Silence the error. + WX_LOGLEVEL_CONTEXT ctx( wxLOG_FatalError ); + + return m_regex.Compile( aPattern, wxRE_ADVANCED ); +} + + +int EDA_PATTERN_MATCH_REGEX::Find( const wxString& aCandidate ) const +{ + if( m_regex.IsValid() ) + { + if( m_regex.Matches( aCandidate ) ) + { + size_t start, len; + m_regex.GetMatch( &start, &len, 0 ); + return ( start > INT_MAX ) ? INT_MAX : start; + } + else + { + return EDA_PATTERN_NOT_FOUND; + } + } + else + { + int loc = aCandidate.Find( m_pattern ); + return ( loc == wxNOT_FOUND ) ? EDA_PATTERN_NOT_FOUND : loc; + } +} + + +bool EDA_PATTERN_MATCH_WILDCARD::SetPattern( const wxString& aPattern ) +{ + // Compile the wildcard string to a regular expression + wxString regex; + regex.Alloc( 2 * aPattern.Length() ); // no need to keep resizing, we know the size roughly + + const wxString to_replace = wxT( ".*+?^${}()|[]/\\" ); + + for( wxString::const_iterator it = aPattern.begin(); it < aPattern.end(); ++it ) + { + wxUniChar c = *it; + if( c == '?' ) + { + regex += wxT( "." ); + } + else if( c == '*' ) + { + regex += wxT( ".*" ); + } + else if( to_replace.Find( c ) != wxNOT_FOUND ) + { + regex += "\\"; + regex += c; + } + else + { + regex += c; + } + } + + return EDA_PATTERN_MATCH_REGEX::SetPattern( regex ); +} + + +int EDA_PATTERN_MATCH_WILDCARD::Find( const wxString& aCandidate ) const +{ + return EDA_PATTERN_MATCH_REGEX::Find( aCandidate ); +} diff --git a/common/kicad_curl/kicad_curl.cpp b/common/kicad_curl/kicad_curl.cpp new file mode 100644 index 0000000000..7424eec870 --- /dev/null +++ b/common/kicad_curl/kicad_curl.cpp @@ -0,0 +1,54 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Mark Roszko + * Copyright (C) 2015 KiCad Developers, see CHANGELOG.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, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include + +bool KICAD_CURL::Init() +{ + if ( curl_global_init( CURL_GLOBAL_ALL ) != CURLE_OK ) + { + return false; + } + else + { + m_initialized = true; + return true; + } +} + + +void KICAD_CURL::Cleanup() +{ + if( m_initialized ) + curl_global_cleanup(); +} + + +std::string KICAD_CURL::GetVersion() +{ + return std::string( curl_version() ); +} + + +bool KICAD_CURL::m_initialized = false; \ No newline at end of file diff --git a/common/kicad_curl/kicad_curl_easy.cpp b/common/kicad_curl/kicad_curl_easy.cpp new file mode 100644 index 0000000000..71a410d0d0 --- /dev/null +++ b/common/kicad_curl/kicad_curl_easy.cpp @@ -0,0 +1,163 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Mark Roszko + * Copyright (C) 2015 KiCad Developers, see CHANGELOG.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, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include + +#include +#include +#include +#include +#include + +static size_t write_callback (void *contents, size_t size, size_t nmemb, void *userp); + + +KICAD_CURL_EASY::KICAD_CURL_EASY() + : m_headers( NULL ) +{ + m_CURL = curl_easy_init(); + + if( m_CURL == NULL ) + { + THROW_IO_ERROR( "Unable to initialize CURL session" ); + } + + m_Buffer.payload = (char*)malloc( 1 ); + m_Buffer.size = 0; + + curl_easy_setopt( m_CURL, CURLOPT_WRITEFUNCTION, write_callback ); + curl_easy_setopt( m_CURL, CURLOPT_WRITEDATA, (void *)&m_Buffer ); +} + + +KICAD_CURL_EASY::~KICAD_CURL_EASY() +{ + free(m_Buffer.payload); + curl_easy_cleanup(m_CURL); +} + + +bool KICAD_CURL_EASY::SetURL( const std::string& aURL ) +{ + if( SetOption( CURLOPT_URL, aURL.c_str() ) == CURLE_OK ) + { + return true; + } + return false; +} + + +bool KICAD_CURL_EASY::SetUserAgent( const std::string& aAgent ) +{ + if( SetOption( CURLOPT_USERAGENT, aAgent.c_str() ) == CURLE_OK ) + { + return true; + } + return false; +} + + +bool KICAD_CURL_EASY::SetFollowRedirects( bool aFollow ) +{ + if( SetOption( CURLOPT_FOLLOWLOCATION , (aFollow ? 1 : 0) ) == CURLE_OK ) + { + return true; + } + return false; +} + + +void KICAD_CURL_EASY::SetHeader( const std::string& aName, const std::string& aValue ) +{ + std::string header = aName + ':' + aValue; + m_headers = curl_slist_append( m_headers, header.c_str() ); +} + + +std::string KICAD_CURL_EASY::GetErrorText(CURLcode code) +{ + return curl_easy_strerror(code); +} + + +static size_t write_callback( void *contents, size_t size, size_t nmemb, void *userp ) +{ + /* calculate buffer size */ + size_t realsize = size * nmemb; + + /* cast pointer to fetch struct */ + struct KICAD_EASY_CURL_BUFFER *p = ( struct KICAD_EASY_CURL_BUFFER * ) userp; + + /* expand buffer */ + p->payload = (char *) realloc( p->payload, p->size + realsize + 1 ); + + /* check buffer */ + if ( p->payload == NULL ) + { + wxLogError( wxT( "Failed to expand buffer in curl_callback" ) ); + + /* free buffer */ + free( p->payload ); + + return -1; + } + + /* copy contents to buffer */ + memcpy( &(p->payload[p->size]), contents, realsize ); + + /* set new buffer size */ + p->size += realsize; + + /* ensure null termination */ + p->payload[p->size] = 0; + + /* return size */ + return realsize; +} + + +void KICAD_CURL_EASY::Perform() +{ + if( m_headers != NULL ) + { + curl_easy_setopt( m_CURL, CURLOPT_HTTPHEADER, m_headers ); + } + + if( m_Buffer.size > 0 ) + { + free( m_Buffer.payload ); + m_Buffer.payload = (char*)malloc( 1 ); + m_Buffer.size = 0; + } + + CURLcode res = curl_easy_perform( m_CURL ); + if( res != CURLE_OK ) + { + wxString msg = wxString::Format( + _( "CURL Request Failed: %s" ), + GetErrorText( res ) ); + + THROW_IO_ERROR( msg ); + } +} \ No newline at end of file diff --git a/common/kiway.cpp b/common/kiway.cpp index 4d6e6fa2a9..7919b9c888 100644 --- a/common/kiway.cpp +++ b/common/kiway.cpp @@ -212,7 +212,7 @@ KIFACE* KIWAY::KiFACE( FACE_T aFaceId, bool doLoad ) if( ! wxFileExists( dname ) ) msg << wxT( "It is missing.\n" ); else - msg << wxT( "Perhaps a wxWidgets shared (.dll or .so) file is missing.\n" ); + msg << wxT( "Perhaps a shared library (.dll or .so) file is missing.\n" ); msg << wxT( "From command line: argv[0]:\n'" ); msg << wxStandardPaths::Get().GetExecutablePath() << wxT( "'\n" ); diff --git a/common/kiway_player.cpp b/common/kiway_player.cpp index 14deee0efa..a268e6bfd2 100644 --- a/common/kiway_player.cpp +++ b/common/kiway_player.cpp @@ -119,7 +119,6 @@ bool KIWAY_PLAYER::ShowModal( wxString* aResult, wxWindow* aResultantFocusWindow if( wlist[ii]->IsTopLevel() && wlist[ii]->IsEnabled() ) enabledTopLevelWindows.push_back( wlist[ii] ); - // exception safe way to disable all top level windows except the modal one, // re-enables only those that were disabled on exit wxWindowDisabler toggle( this ); diff --git a/common/pgm_base.cpp b/common/pgm_base.cpp index 039a8572c4..6606ee1b0a 100644 --- a/common/pgm_base.cpp +++ b/common/pgm_base.cpp @@ -30,6 +30,7 @@ * (locale handling) */ +#include /* Include before any wx file */ #include #include #include @@ -282,6 +283,7 @@ PGM_BASE::PGM_BASE() PGM_BASE::~PGM_BASE() { destroy(); + KICAD_CURL::Cleanup(); } @@ -493,6 +495,13 @@ bool PGM_BASE::initPgm() wxSystemOptions::SetOption( wxOSX_FILEDIALOG_ALWAYS_SHOW_TYPES, 1 ); #endif + // Initialize CURL + wxLogDebug( wxT( "Using %s" ), KICAD_CURL::GetVersion() ); + if( !KICAD_CURL::Init() ) + { + wxLogDebug( wxT( "Error initializing libcurl" ) ); + } + return true; } diff --git a/cvpcb/class_DisplayFootprintsFrame.cpp b/cvpcb/class_DisplayFootprintsFrame.cpp index 0b3a76a57c..dff95aee86 100644 --- a/cvpcb/class_DisplayFootprintsFrame.cpp +++ b/cvpcb/class_DisplayFootprintsFrame.cpp @@ -149,8 +149,10 @@ DISPLAY_FOOTPRINTS_FRAME::~DISPLAY_FOOTPRINTS_FRAME() void DISPLAY_FOOTPRINTS_FRAME::OnCloseWindow( wxCloseEvent& event ) { - if( m_Draw3DFrame ) - m_Draw3DFrame->Close( true ); + EDA_3D_FRAME* draw3DFrame = Get3DViewerFrame(); + + if( draw3DFrame ) + draw3DFrame->Close( true ); Destroy(); } @@ -382,25 +384,27 @@ bool DISPLAY_FOOTPRINTS_FRAME::GeneralControl( wxDC* aDC, const wxPoint& aPositi void DISPLAY_FOOTPRINTS_FRAME::Show3D_Frame( wxCommandEvent& event ) { - if( m_Draw3DFrame ) + EDA_3D_FRAME* draw3DFrame = Get3DViewerFrame(); + + if( draw3DFrame ) { // Raising the window does not show the window on Windows if iconized. // This should work on any platform. - if( m_Draw3DFrame->IsIconized() ) - m_Draw3DFrame->Iconize( false ); + if( draw3DFrame->IsIconized() ) + draw3DFrame->Iconize( false ); - m_Draw3DFrame->Raise(); + draw3DFrame->Raise(); // Raising the window does not set the focus on Linux. This should work on any platform. - if( wxWindow::FindFocus() != m_Draw3DFrame ) - m_Draw3DFrame->SetFocus(); + if( wxWindow::FindFocus() != draw3DFrame ) + draw3DFrame->SetFocus(); return; } - m_Draw3DFrame = new EDA_3D_FRAME( &Kiway(), this, _( "3D Viewer" ) ); - m_Draw3DFrame->Raise(); // Needed with some Window Managers - m_Draw3DFrame->Show( true ); + draw3DFrame = new EDA_3D_FRAME( &Kiway(), this, _( "3D Viewer" ) ); + draw3DFrame->Raise(); // Needed with some Window Managers + draw3DFrame->Show( true ); } @@ -489,7 +493,8 @@ void DISPLAY_FOOTPRINTS_FRAME::InitDisplay() msg.Printf( _( "Footprint: %s" ), GetChars( footprintName ) ); SetTitle( msg ); - const FOOTPRINT_INFO* module_info = parentframe->m_footprints.GetModuleInfo( footprintName ); + const FOOTPRINT_INFO* module_info = + parentframe->m_footprints.GetModuleInfo( footprintName ); const wxChar* libname; @@ -530,8 +535,10 @@ void DISPLAY_FOOTPRINTS_FRAME::InitDisplay() GetCanvas()->Refresh(); - if( m_Draw3DFrame ) - m_Draw3DFrame->NewDisplay(); + EDA_3D_FRAME* draw3DFrame = Get3DViewerFrame(); + + if( draw3DFrame ) + draw3DFrame->NewDisplay(); } diff --git a/cvpcb/cvframe.cpp b/cvpcb/cvframe.cpp index 1c612f0c49..a3deab9c17 100644 --- a/cvpcb/cvframe.cpp +++ b/cvpcb/cvframe.cpp @@ -910,7 +910,8 @@ COMPONENT* CVPCB_MAINFRAME::GetSelectedComponent() DISPLAY_FOOTPRINTS_FRAME* CVPCB_MAINFRAME::GetFpViewerFrame() { // returns the Footprint Viewer frame, if exists, or NULL - return (DISPLAY_FOOTPRINTS_FRAME*) wxWindow::FindWindowByName( FOOTPRINTVIEWER_FRAME_NAME ); + return dynamic_cast + ( wxWindow::FindWindowByName( FOOTPRINTVIEWER_FRAME_NAME ) ); } diff --git a/eeschema/class_drc_erc_item.cpp b/eeschema/class_drc_erc_item.cpp index 9071dc89d4..5b013e7858 100644 --- a/eeschema/class_drc_erc_item.cpp +++ b/eeschema/class_drc_erc_item.cpp @@ -54,6 +54,10 @@ wxString DRC_ITEM::GetErrorText() const return wxString( _("A no connect symbol is connected to more than 1 pin")); case ERCE_GLOBLABEL: return wxString( _("Global label not connected to any other global label") ); + case ERCE_SIMILAR_LABELS: + return wxString( _("Labels are similar (lower/upper case difference only)") ); + case ERCE_SIMILAR_GLBL_LABELS: + return wxString( _("Global labels are similar (lower/upper case difference only)") ); default: return wxString( wxT("Unkown.") ); diff --git a/eeschema/class_libentry.cpp b/eeschema/class_libentry.cpp index 755dcd81d3..8941a05d70 100644 --- a/eeschema/class_libentry.cpp +++ b/eeschema/class_libentry.cpp @@ -886,7 +886,7 @@ bool LIB_PART::Load( LINE_READER& aLineReader, wxString& aErrorMsg ) { p = strtok( line, " \t\n" ); - if( stricmp( p, "ENDDEF" ) == 0 ) + if( p && stricmp( p, "ENDDEF" ) == 0 ) break; } @@ -948,6 +948,9 @@ bool LIB_PART::Load( LINE_READER& aLineReader, wxString& aErrorMsg ) if( *line == '#' ) // a comment continue; + if( p == NULL ) // empty line + continue; + if( line[0] == 'T' && line[1] == 'i' ) result = LoadDateAndTime( aLineReader ); else if( *line == 'F' ) @@ -1036,7 +1039,12 @@ bool LIB_PART::LoadDrawEntries( LINE_READER& aLineReader, wxString& aErrorMsg ) break; case '#': // Comment - continue; + continue; + + case '\n': + case '\r': + case 0: // empty line + continue; default: aErrorMsg.Printf( wxT( "undefined DRAW command %c" ), line[0] ); diff --git a/eeschema/class_netlist_object.h b/eeschema/class_netlist_object.h index f97fe77de4..68dc2b80fb 100644 --- a/eeschema/class_netlist_object.h +++ b/eeschema/class_netlist_object.h @@ -369,6 +369,32 @@ public: */ void SortListbySheet(); + /** + * Counts number of pins connected on the same net. + * Used to count all pins connected to a no connect symbol + * @return the pin count of the net starting at aNetStart + * @param aNetStart = index in list of net objects of the first item + */ + int CountPinsInNet( unsigned aNetStart ); + + /** + * Function TestforNonOrphanLabel + * Sheet labels are expected to be connected to a hierarchical label. + * Hierarchical labels are expected to be connected to a sheet label. + * Global labels are expected to be not orphan (connected to at least one other global label. + * this function tests the connection to an other suitable label + */ + void TestforNonOrphanLabel( unsigned aNetItemRef, unsigned aStartNet ); + + /** + * Function TestforSimilarLabels + * detects labels which are different when using case sensitive comparisons + * but are equal when using case insensitive comparisons + * It can be due to a mistake from designer, so this kind of labels + * is reported by TestforSimilarLabels + */ + void TestforSimilarLabels(); + #if defined(DEBUG) void DumpNetTable() @@ -403,7 +429,7 @@ private: return Objet1->GetNet() < Objet2->GetNet(); } - /* Comparison routine to sort items by Sheet Number + /* Comparison routine to sort items by Sheet path */ static bool sortItemsBySheet( const NETLIST_OBJECT* Objet1, const NETLIST_OBJECT* Objet2 ) { diff --git a/eeschema/component_tree_search_container.cpp b/eeschema/component_tree_search_container.cpp index c3061f95e9..633af5494c 100644 --- a/eeschema/component_tree_search_container.cpp +++ b/eeschema/component_tree_search_container.cpp @@ -35,6 +35,8 @@ #include #include +#include + // Each node gets this lowest score initially, without any matches applied. Matches // will then increase this score depending on match quality. // This way, an empty search string will result in all components being displayed as they @@ -113,6 +115,7 @@ COMPONENT_TREE_SEARCH_CONTAINER::~COMPONENT_TREE_SEARCH_CONTAINER() { BOOST_FOREACH( TREE_NODE* node, m_nodes ) delete node; + m_nodes.clear(); } @@ -225,12 +228,15 @@ LIB_ALIAS* COMPONENT_TREE_SEARCH_CONTAINER::GetSelectedAlias( int* aUnit ) BOOST_FOREACH( TREE_NODE* node, m_nodes ) { - if( node->MatchScore > 0 && node->TreeId == select_id ) { + if( node->MatchScore > 0 && node->TreeId == select_id ) + { if( aUnit && node->Unit > 0 ) *aUnit = node->Unit; + return node->Alias; } } + return NULL; } @@ -249,6 +255,72 @@ static int matchPosScore(int aPosition, int aMaximum) } +namespace +{ +class EDA_COMBINED_MATCHER +{ +public: + EDA_COMBINED_MATCHER( const wxString &aPattern ) + { + // Whatever syntax users prefer, it shall be matched. + AddMatcher( aPattern, new EDA_PATTERN_MATCH_REGEX() ); + AddMatcher( aPattern, new EDA_PATTERN_MATCH_WILDCARD() ); + // If any of the above matchers couldn't be created because the pattern + // syntax does not match, the substring will try its best. + AddMatcher( aPattern, new EDA_PATTERN_MATCH_SUBSTR() ); + } + + ~EDA_COMBINED_MATCHER() + { + BOOST_FOREACH( const EDA_PATTERN_MATCH* matcher, m_matchers ) + delete matcher; + } + + /* + * Look in all existing matchers, return the earliest match of any of + * the existing. Returns EDA_PATTERN_NOT_FOUND if no luck. + */ + int Find( const wxString &aTerm, int *aMatchersTriggered ) + { + int result = EDA_PATTERN_NOT_FOUND; + + BOOST_FOREACH( const EDA_PATTERN_MATCH* matcher, m_matchers ) + { + int local_find = matcher->Find( aTerm ); + + if ( local_find != EDA_PATTERN_NOT_FOUND ) + { + *aMatchersTriggered += 1; + + if ( local_find < result ) + { + result = local_find; + } + } + } + + return result; + } + +private: + // Add matcher if it can compile the pattern. + void AddMatcher( const wxString &aPattern, EDA_PATTERN_MATCH *aMatcher ) + { + if ( aMatcher->SetPattern( aPattern ) ) + { + m_matchers.push_back( aMatcher ); + } + else + { + delete aMatcher; + } + } + + std::vector m_matchers; +}; +} + + void COMPONENT_TREE_SEARCH_CONTAINER::UpdateSearchTerm( const wxString& aSearch ) { if( m_tree == NULL ) @@ -286,6 +358,7 @@ void COMPONENT_TREE_SEARCH_CONTAINER::UpdateSearchTerm( const wxString& aSearch while ( tokenizer.HasMoreTokens() ) { const wxString term = tokenizer.GetNextToken().Lower(); + EDA_COMBINED_MATCHER matcher( term ); BOOST_FOREACH( TREE_NODE* node, m_nodes ) { @@ -299,17 +372,18 @@ void COMPONENT_TREE_SEARCH_CONTAINER::UpdateSearchTerm( const wxString& aSearch // least two characters long. That avoids spurious, low quality // matches. Most abbreviations are at three characters long. int found_pos; + int matcher_fired = 0; if( term == node->MatchName ) node->MatchScore += 1000; // exact match. High score :) - else if( (found_pos = node->MatchName.Find( term ) ) != wxNOT_FOUND ) + else if( (found_pos = matcher.Find( node->MatchName, &matcher_fired ) ) != EDA_PATTERN_NOT_FOUND ) { // Substring match. The earlier in the string the better. score += 20..40 node->MatchScore += matchPosScore( found_pos, 20 ) + 20; } - else if( node->Parent->MatchName.Find( term ) != wxNOT_FOUND ) + else if( matcher.Find( node->Parent->MatchName, &matcher_fired ) != EDA_PATTERN_NOT_FOUND ) node->MatchScore += 19; // parent name matches. score += 19 - else if( ( found_pos = node->SearchText.Find( term ) ) != wxNOT_FOUND ) + else if( ( found_pos = matcher.Find( node->SearchText, &matcher_fired ) ) != EDA_PATTERN_NOT_FOUND ) { // If we have a very short search term (like one or two letters), we don't want // to accumulate scores if they just happen to be in keywords or description as @@ -322,6 +396,8 @@ void COMPONENT_TREE_SEARCH_CONTAINER::UpdateSearchTerm( const wxString& aSearch } else node->MatchScore = 0; // No match. That's it for this item. + + node->MatchScore += 2 * matcher_fired; } } diff --git a/eeschema/dialogs/dialog_erc.cpp b/eeschema/dialogs/dialog_erc.cpp index c6792eae58..87acb30d5f 100644 --- a/eeschema/dialogs/dialog_erc.cpp +++ b/eeschema/dialogs/dialog_erc.cpp @@ -1,7 +1,7 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2012 Jean-Pierre Charras, jp.charras at wanadoo.fr + * Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr * Copyright (C) 2012 Wayne Stambaugh * Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors. * @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -48,10 +49,19 @@ #include #include +extern int DiagErc[PIN_NMAX][PIN_NMAX]; +extern int DefaultDiagErc[PIN_NMAX][PIN_NMAX]; -bool DIALOG_ERC::m_writeErcFile = false; +bool DIALOG_ERC::m_writeErcFile = false; // saved only for the current session +bool DIALOG_ERC::m_TestSimilarLabels = true; // Save in project config +bool DIALOG_ERC::m_diagErcTableInit = false; // saved only for the current session +bool DIALOG_ERC::m_tstUniqueGlobalLabels = true; // saved only for the current session + +// Control identifiers for events +#define ID_MATRIX_0 1800 + BEGIN_EVENT_TABLE( DIALOG_ERC, DIALOG_ERC_BASE ) EVT_COMMAND_RANGE( ID_MATRIX_0, ID_MATRIX_0 + ( PIN_NMAX * PIN_NMAX ) - 1, wxEVT_COMMAND_BUTTON_CLICKED, DIALOG_ERC::ChangeErrorLevel ) @@ -72,6 +82,8 @@ DIALOG_ERC::DIALOG_ERC( SCH_EDIT_FRAME* parent ) : DIALOG_ERC::~DIALOG_ERC() { + m_TestSimilarLabels = m_cbTestSimilarLabels->GetValue(); + m_tstUniqueGlobalLabels = m_cbTestUniqueGlbLabels->GetValue(); } @@ -86,6 +98,8 @@ void DIALOG_ERC::Init() } m_WriteResultOpt->SetValue( m_writeErcFile ); + m_cbTestSimilarLabels->SetValue( m_TestSimilarLabels ); + m_cbTestUniqueGlbLabels->SetValue( m_tstUniqueGlobalLabels ); SCH_SCREENS screens; updateMarkerCounts( &screens ); @@ -232,7 +246,7 @@ void DIALOG_ERC::OnLeftClickMarkersList( wxHtmlLinkEvent& event ) void DIALOG_ERC::OnLeftDblClickMarkersList( wxMouseEvent& event ) { - // Remember: OnLeftClickMarkersList was called just berfore + // Remember: OnLeftClickMarkersList was called just before // and therefore m_lastMarkerFound was initialized. // (NULL if not found) if( m_lastMarkerFound ) @@ -257,10 +271,10 @@ void DIALOG_ERC::ReBuildMatrixPanel() wxSize bitmap_size = dummy->GetSize(); delete dummy; - if( !DiagErcTableInit ) + if( !m_diagErcTableInit ) { memcpy( DiagErc, DefaultDiagErc, sizeof(DefaultDiagErc) ); - DiagErcTableInit = true; + m_diagErcTableInit = true; } wxPoint pos; @@ -389,6 +403,10 @@ void DIALOG_ERC::ResetDefaultERCDiag( wxCommandEvent& event ) { memcpy( DiagErc, DefaultDiagErc, sizeof( DiagErc ) ); ReBuildMatrixPanel(); + m_TestSimilarLabels = true; + m_cbTestSimilarLabels->SetValue( m_TestSimilarLabels ); + m_tstUniqueGlobalLabels = true; + m_cbTestUniqueGlbLabels->SetValue( m_tstUniqueGlobalLabels ); } @@ -432,13 +450,9 @@ void DIALOG_ERC::TestErc( wxArrayString* aMessagesList ) { wxFileName fn; - if( !DiagErcTableInit ) - { - memcpy( DiagErc, DefaultDiagErc, sizeof( DefaultDiagErc ) ); - DiagErcTableInit = true; - } - m_writeErcFile = m_WriteResultOpt->GetValue(); + m_TestSimilarLabels = m_cbTestSimilarLabels->GetValue(); + m_tstUniqueGlobalLabels = m_cbTestUniqueGlbLabels->GetValue(); // Build the whole sheet list in hierarchy (sheet, not screen) SCH_SHEET_LIST sheets; @@ -511,12 +525,14 @@ void DIALOG_ERC::TestErc( wxArrayString* aMessagesList ) case NET_HIERBUSLABELMEMBER: case NET_SHEETLABEL: case NET_SHEETBUSLABELMEMBER: - case NET_GLOBLABEL: - // ERC problems when pin sheets do not match hierarchical labels. // Each pin sheet must match a hierarchical label // Each hierarchical label must match a pin sheet - TestLabel( objectsConnectedList.get(), net, nextNet ); + objectsConnectedList->TestforNonOrphanLabel( net, nextNet ); + break; + case NET_GLOBLABEL: + if( m_tstUniqueGlobalLabels ) + objectsConnectedList->TestforNonOrphanLabel( net, nextNet ); break; case NET_NOCONNECT: @@ -524,7 +540,7 @@ void DIALOG_ERC::TestErc( wxArrayString* aMessagesList ) // ERC problems when a noconnect symbol is connected to more than one pin. MinConn = NET_NC; - if( CountPinsInNet( objectsConnectedList.get(), nextNet ) > 1 ) + if( objectsConnectedList->CountPinsInNet( nextNet ) > 1 ) Diagnose( objectsConnectedList->GetItem( net ), NULL, MinConn, UNC ); break; @@ -539,6 +555,11 @@ void DIALOG_ERC::TestErc( wxArrayString* aMessagesList ) lastNet = net; } + // Test similar labels (i;e. labels which are identical when + // using case insensitive comparisons) + if( m_TestSimilarLabels ) + objectsConnectedList->TestforSimilarLabels(); + // Displays global results: updateMarkerCounts( &screens ); diff --git a/eeschema/dialogs/dialog_erc.h b/eeschema/dialogs/dialog_erc.h index e086166cf1..d7d9ff869f 100644 --- a/eeschema/dialogs/dialog_erc.h +++ b/eeschema/dialogs/dialog_erc.h @@ -27,22 +27,12 @@ #include #include - +#include // For PIN_NMAX definition #include #include "dialog_erc_listbox.h" -/* Variable locales */ -extern int DiagErc[PIN_NMAX][PIN_NMAX]; -extern bool DiagErcTableInit; // go to true after DiagErc init -extern int DefaultDiagErc[PIN_NMAX][PIN_NMAX]; - -/* Control identifiers */ -#define ID_MATRIX_0 1800 - -/*! - * DIALOG_ERC class declaration - */ +// DIALOG_ERC class declaration class DIALOG_ERC : public DIALOG_ERC_BASE { @@ -54,6 +44,11 @@ private: bool m_initialized; const SCH_MARKER* m_lastMarkerFound; static bool m_writeErcFile; + static bool m_diagErcTableInit; // go to true after DiagErc init + static bool m_tstUniqueGlobalLabels; + +public: + static bool m_TestSimilarLabels; public: DIALOG_ERC( SCH_EDIT_FRAME* parent ); diff --git a/eeschema/dialogs/dialog_erc_base.cpp b/eeschema/dialogs/dialog_erc_base.cpp index c1ef861b2c..29cb5ab41c 100644 --- a/eeschema/dialogs/dialog_erc_base.cpp +++ b/eeschema/dialogs/dialog_erc_base.cpp @@ -56,6 +56,9 @@ DIALOG_ERC_BASE::DIALOG_ERC_BASE( wxWindow* parent, wxWindowID id, const wxStrin sdiagSizer->Add( gSizeDiag, 0, wxEXPAND, 5 ); + m_staticline1 = new wxStaticLine( sdiagSizer->GetStaticBox(), wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + sdiagSizer->Add( m_staticline1, 0, wxEXPAND|wxTOP|wxBOTTOM, 5 ); + m_WriteResultOpt = new wxCheckBox( sdiagSizer->GetStaticBox(), wxID_ANY, _("Create ERC file report"), wxDefaultPosition, wxDefaultSize, 0 ); sdiagSizer->Add( m_WriteResultOpt, 0, wxTOP|wxBOTTOM|wxRIGHT, 5 ); @@ -83,7 +86,7 @@ DIALOG_ERC_BASE::DIALOG_ERC_BASE( wxWindow* parent, wxWindowID id, const wxStrin bercSizer->Add( m_textMarkers, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); m_MarkersList = new ERC_HTML_LISTFRAME( m_PanelERC, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHW_SCROLLBAR_AUTO|wxSUNKEN_BORDER ); - bercSizer->Add( m_MarkersList, 1, wxALL|wxEXPAND, 5 ); + bercSizer->Add( m_MarkersList, 1, wxEXPAND|wxALL, 5 ); wxBoxSizer* bbuttonsSizer; bbuttonsSizer = new wxBoxSizer( wxHORIZONTAL ); @@ -113,9 +116,30 @@ DIALOG_ERC_BASE::DIALOG_ERC_BASE( wxWindow* parent, wxWindowID id, const wxStrin m_ResetOptButton = new wxButton( m_PanelERCOptions, ID_RESET_MATRIX, _("Initialize to Default"), wxDefaultPosition, wxDefaultSize, 0 ); m_panelMatrixSizer->Add( m_ResetOptButton, 0, wxALIGN_RIGHT|wxTOP|wxRIGHT|wxLEFT, 5 ); + m_staticText8 = new wxStaticText( m_PanelERCOptions, wxID_ANY, _("Pin to pin connections"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE ); + m_staticText8->Wrap( -1 ); + m_panelMatrixSizer->Add( m_staticText8, 0, wxRIGHT|wxLEFT|wxEXPAND, 5 ); + m_matrixPanel = new wxPanel( m_PanelERCOptions, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); m_panelMatrixSizer->Add( m_matrixPanel, 1, wxEXPAND | wxALL, 5 ); + m_staticline2 = new wxStaticLine( m_PanelERCOptions, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + m_panelMatrixSizer->Add( m_staticline2, 0, wxEXPAND|wxTOP|wxBOTTOM, 5 ); + + m_staticText9 = new wxStaticText( m_PanelERCOptions, wxID_ANY, _("Label to label connections"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE ); + m_staticText9->Wrap( -1 ); + m_panelMatrixSizer->Add( m_staticText9, 0, wxBOTTOM|wxRIGHT|wxLEFT|wxEXPAND, 5 ); + + m_cbTestSimilarLabels = new wxCheckBox( m_PanelERCOptions, wxID_ANY, _("Test similar labels"), wxDefaultPosition, wxDefaultSize, 0 ); + m_cbTestSimilarLabels->SetToolTip( _("Similar labels are labels (inside a sheet) which differs only by upper/lower case") ); + + m_panelMatrixSizer->Add( m_cbTestSimilarLabels, 0, wxALL, 5 ); + + m_cbTestUniqueGlbLabels = new wxCheckBox( m_PanelERCOptions, wxID_ANY, _("Test unique global labels"), wxDefaultPosition, wxDefaultSize, 0 ); + m_cbTestUniqueGlbLabels->SetToolTip( _("Global labels are used to connect signals across the full hierarchy.\nThey are expected to be at least two labels with the same name.") ); + + m_panelMatrixSizer->Add( m_cbTestUniqueGlbLabels, 0, wxALL, 5 ); + m_PanelERCOptions->SetSizer( m_panelMatrixSizer ); m_PanelERCOptions->Layout(); diff --git a/eeschema/dialogs/dialog_erc_base.fbp b/eeschema/dialogs/dialog_erc_base.fbp index aa6589a1e8..06d1db56a7 100644 --- a/eeschema/dialogs/dialog_erc_base.fbp +++ b/eeschema/dialogs/dialog_erc_base.fbp @@ -44,7 +44,7 @@ DIALOG_ERC_BASE - 519,457 + 519,464 wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER DIALOG_SHIM; dialog_shim.h Electrical Rules Checker @@ -815,6 +815,87 @@ + + 5 + wxEXPAND|wxTOP|wxBOTTOM + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + + 1 + m_staticline1 + 1 + + + protected + 1 + + Resizable + 1 + + wxLI_HORIZONTAL + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 wxTOP|wxBOTTOM|wxRIGHT @@ -1177,7 +1258,7 @@ 5 - wxALL|wxEXPAND + wxEXPAND|wxALL 1 1 @@ -1708,6 +1789,89 @@ + + 5 + wxRIGHT|wxLEFT|wxEXPAND + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Pin to pin connections + + 0 + + + 0 + + 1 + m_staticText8 + 1 + + + protected + 1 + + Resizable + 1 + + wxALIGN_CENTRE + + 0 + + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + + + 5 wxEXPAND | wxALL @@ -1788,6 +1952,346 @@ + + 5 + wxEXPAND|wxTOP|wxBOTTOM + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + + 1 + m_staticline2 + 1 + + + protected + 1 + + Resizable + 1 + + wxLI_HORIZONTAL + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxBOTTOM|wxRIGHT|wxLEFT|wxEXPAND + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Label to label connections + + 0 + + + 0 + + 1 + m_staticText9 + 1 + + + protected + 1 + + Resizable + 1 + + wxALIGN_CENTRE + + 0 + + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Test similar labels + + 0 + + + 0 + + 1 + m_cbTestSimilarLabels + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + Similar labels are labels (inside a sheet) which differs only by upper/lower case + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Test unique global labels + + 0 + + + 0 + + 1 + m_cbTestUniqueGlbLabels + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + Global labels are used to connect signals across the full hierarchy. They are expected to be at least two labels with the same name. + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/eeschema/dialogs/dialog_erc_base.h b/eeschema/dialogs/dialog_erc_base.h index 007f9462af..1d1f67aeb3 100644 --- a/eeschema/dialogs/dialog_erc_base.h +++ b/eeschema/dialogs/dialog_erc_base.h @@ -23,6 +23,7 @@ class ERC_HTML_LISTFRAME; #include #include #include +#include #include #include #include @@ -56,6 +57,7 @@ class DIALOG_ERC_BASE : public DIALOG_SHIM wxTextCtrl* m_LastWarningCount; wxStaticText* m_LastErrCountText; wxTextCtrl* m_LastErrCount; + wxStaticLine* m_staticline1; wxCheckBox* m_WriteResultOpt; wxStaticText* m_titleMessages; wxTextCtrl* m_MessagesList; @@ -66,7 +68,12 @@ class DIALOG_ERC_BASE : public DIALOG_SHIM wxButton* m_buttonClose; wxPanel* m_PanelERCOptions; wxButton* m_ResetOptButton; + wxStaticText* m_staticText8; wxPanel* m_matrixPanel; + wxStaticLine* m_staticline2; + wxStaticText* m_staticText9; + wxCheckBox* m_cbTestSimilarLabels; + wxCheckBox* m_cbTestUniqueGlbLabels; // Virtual event handlers, overide them in your derived class virtual void OnCloseErcDialog( wxCloseEvent& event ) { event.Skip(); } @@ -80,7 +87,7 @@ class DIALOG_ERC_BASE : public DIALOG_SHIM public: - DIALOG_ERC_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Electrical Rules Checker"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 519,457 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); + DIALOG_ERC_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Electrical Rules Checker"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 519,464 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); ~DIALOG_ERC_BASE(); }; diff --git a/eeschema/dialogs/dialog_plot_schematic_base.cpp b/eeschema/dialogs/dialog_plot_schematic_base.cpp index fb2d510945..dab46317d2 100644 --- a/eeschema/dialogs/dialog_plot_schematic_base.cpp +++ b/eeschema/dialogs/dialog_plot_schematic_base.cpp @@ -18,33 +18,33 @@ DIALOG_PLOT_SCHEMATIC_BASE::DIALOG_PLOT_SCHEMATIC_BASE( wxWindow* parent, wxWind wxBoxSizer* bMainSizer; bMainSizer = new wxBoxSizer( wxVERTICAL ); - wxBoxSizer* bSizer6; - bSizer6 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizerDir; + bSizerDir = new wxBoxSizer( wxHORIZONTAL ); m_staticTextOutputDirectory = new wxStaticText( this, wxID_ANY, _("Output directory:"), wxDefaultPosition, wxDefaultSize, 0 ); m_staticTextOutputDirectory->Wrap( -1 ); - bSizer6->Add( m_staticTextOutputDirectory, 0, wxALL, 5 ); - - wxBoxSizer* bSizer5; - bSizer5 = new wxBoxSizer( wxHORIZONTAL ); + bSizerDir->Add( m_staticTextOutputDirectory, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); m_outputDirectoryName = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); m_outputDirectoryName->SetMaxLength( 0 ); m_outputDirectoryName->SetToolTip( _("Target directory for plot files. Can be absolute or relative to the schematic main file location.") ); - bSizer5->Add( m_outputDirectoryName, 1, wxEXPAND|wxLEFT|wxRIGHT, 5 ); + bSizerDir->Add( m_outputDirectoryName, 1, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); m_browseButton = new wxButton( this, wxID_ANY, _("Browse..."), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer5->Add( m_browseButton, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 5 ); + bSizerDir->Add( m_browseButton, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - bSizer6->Add( bSizer5, 1, wxEXPAND, 5 ); - - - bMainSizer->Add( bSizer6, 0, wxEXPAND|wxLEFT|wxTOP, 5 ); + bMainSizer->Add( bSizerDir, 0, wxBOTTOM|wxEXPAND, 10 ); m_optionsSizer = new wxBoxSizer( wxHORIZONTAL ); + wxString m_plotFormatOptChoices[] = { _("Postscript"), _("PDF"), _("SVG"), _("DXF"), _("HPGL") }; + int m_plotFormatOptNChoices = sizeof( m_plotFormatOptChoices ) / sizeof( wxString ); + m_plotFormatOpt = new wxRadioBox( this, wxID_ANY, _("Format"), wxDefaultPosition, wxDefaultSize, m_plotFormatOptNChoices, m_plotFormatOptChoices, 1, wxRA_SPECIFY_COLS ); + m_plotFormatOpt->SetSelection( 1 ); + m_optionsSizer->Add( m_plotFormatOpt, 0, wxEXPAND|wxRIGHT|wxLEFT, 5 ); + m_paperOptionsSizer = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Paper Options") ), wxVERTICAL ); wxString m_PaperSizeOptionChoices[] = { _("Schematic size"), _("Force size A4"), _("Force size A") }; @@ -85,12 +85,6 @@ DIALOG_PLOT_SCHEMATIC_BASE::DIALOG_PLOT_SCHEMATIC_BASE( wxWindow* parent, wxWind m_optionsSizer->Add( m_paperOptionsSizer, 0, wxEXPAND, 5 ); - wxString m_plotFormatOptChoices[] = { _("Postscript"), _("PDF"), _("SVG"), _("DXF"), _("HPGL") }; - int m_plotFormatOptNChoices = sizeof( m_plotFormatOptChoices ) / sizeof( wxString ); - m_plotFormatOpt = new wxRadioBox( this, wxID_ANY, _("Format"), wxDefaultPosition, wxDefaultSize, m_plotFormatOptNChoices, m_plotFormatOptChoices, 1, wxRA_SPECIFY_COLS ); - m_plotFormatOpt->SetSelection( 1 ); - m_optionsSizer->Add( m_plotFormatOpt, 0, wxEXPAND|wxLEFT, 5 ); - wxStaticBoxSizer* sbSizerPlotFormat; sbSizerPlotFormat = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("General Options") ), wxVERTICAL ); @@ -140,16 +134,16 @@ DIALOG_PLOT_SCHEMATIC_BASE::DIALOG_PLOT_SCHEMATIC_BASE( wxWindow* parent, wxWind bMainSizer->Add( m_optionsSizer, 0, wxEXPAND|wxLEFT|wxRIGHT|wxTOP, 5 ); - wxBoxSizer* bSizer4; - bSizer4 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizerMsgPanel; + bSizerMsgPanel = new wxBoxSizer( wxVERTICAL ); m_MessagesBox = new WX_HTML_REPORT_PANEL( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); m_MessagesBox->SetMinSize( wxSize( 300,150 ) ); - bSizer4->Add( m_MessagesBox, 1, wxEXPAND | wxALL, 5 ); + bSizerMsgPanel->Add( m_MessagesBox, 1, wxEXPAND | wxALL, 5 ); - bMainSizer->Add( bSizer4, 1, wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT, 5 ); + bMainSizer->Add( bSizerMsgPanel, 1, wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT, 5 ); this->SetSizer( bMainSizer ); @@ -159,8 +153,8 @@ DIALOG_PLOT_SCHEMATIC_BASE::DIALOG_PLOT_SCHEMATIC_BASE( wxWindow* parent, wxWind // Connect Events this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DIALOG_PLOT_SCHEMATIC_BASE::OnCloseWindow ) ); m_browseButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PLOT_SCHEMATIC_BASE::OnOutputDirectoryBrowseClicked ), NULL, this ); - m_HPGLPaperSizeOption->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_PLOT_SCHEMATIC_BASE::OnHPGLPageSelected ), NULL, this ); m_plotFormatOpt->Connect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( DIALOG_PLOT_SCHEMATIC_BASE::OnPlotFormatSelection ), NULL, this ); + m_HPGLPaperSizeOption->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_PLOT_SCHEMATIC_BASE::OnHPGLPageSelected ), NULL, this ); m_buttonPlotCurrent->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PLOT_SCHEMATIC_BASE::OnButtonPlotCurrentClick ), NULL, this ); m_buttonPlotAll->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PLOT_SCHEMATIC_BASE::OnButtonPlotAllClick ), NULL, this ); m_buttonQuit->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PLOT_SCHEMATIC_BASE::OnButtonCancelClick ), NULL, this ); @@ -171,8 +165,8 @@ DIALOG_PLOT_SCHEMATIC_BASE::~DIALOG_PLOT_SCHEMATIC_BASE() // Disconnect Events this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DIALOG_PLOT_SCHEMATIC_BASE::OnCloseWindow ) ); m_browseButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PLOT_SCHEMATIC_BASE::OnOutputDirectoryBrowseClicked ), NULL, this ); - m_HPGLPaperSizeOption->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_PLOT_SCHEMATIC_BASE::OnHPGLPageSelected ), NULL, this ); m_plotFormatOpt->Disconnect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( DIALOG_PLOT_SCHEMATIC_BASE::OnPlotFormatSelection ), NULL, this ); + m_HPGLPaperSizeOption->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_PLOT_SCHEMATIC_BASE::OnHPGLPageSelected ), NULL, this ); m_buttonPlotCurrent->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PLOT_SCHEMATIC_BASE::OnButtonPlotCurrentClick ), NULL, this ); m_buttonPlotAll->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PLOT_SCHEMATIC_BASE::OnButtonPlotAllClick ), NULL, this ); m_buttonQuit->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PLOT_SCHEMATIC_BASE::OnButtonCancelClick ), NULL, this ); diff --git a/eeschema/dialogs/dialog_plot_schematic_base.fbp b/eeschema/dialogs/dialog_plot_schematic_base.fbp index 8777457ad6..caf7fe31f3 100644 --- a/eeschema/dialogs/dialog_plot_schematic_base.fbp +++ b/eeschema/dialogs/dialog_plot_schematic_base.fbp @@ -94,17 +94,17 @@ wxVERTICAL none - 5 - wxEXPAND|wxLEFT|wxTOP + 10 + wxBOTTOM|wxEXPAND 0 - bSizer6 - wxVERTICAL + bSizerDir + wxHORIZONTAL none 5 - wxALL + wxALL|wxALIGN_CENTER_VERTICAL 0 1 @@ -187,192 +187,181 @@ 5 - wxEXPAND + wxALL|wxALIGN_CENTER_VERTICAL 1 - + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + 0 + + 0 - bSizer5 - wxHORIZONTAL - none - - 5 - wxEXPAND|wxLEFT|wxRIGHT - 1 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - - 0 - - 0 - - 0 - - 1 - m_outputDirectoryName - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - Target directory for plot files. Can be absolute or relative to the schematic main file location. - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 - wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - Browse... - - 0 - - - 0 - - 1 - m_browseButton - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - OnOutputDirectoryBrowseClicked - - - - - - - - - - - - - - - - - - - - - - - - - + 1 + m_outputDirectoryName + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + Target directory for plot files. Can be absolute or relative to the schematic main file location. + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALL|wxALIGN_CENTER_VERTICAL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Browse... + + 0 + + + 0 + + 1 + m_browseButton + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + OnOutputDirectoryBrowseClicked + + + + + + + + + + + + + + + + + + + + + + + @@ -386,6 +375,96 @@ m_optionsSizer wxHORIZONTAL protected + + 5 + wxEXPAND|wxRIGHT|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + "Postscript" "PDF" "SVG" "DXF" "HPGL" + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Format + 1 + + 0 + + + 0 + + 1 + m_plotFormatOpt + 1 + + + protected + 1 + + Resizable + 1 + 1 + + wxRA_SPECIFY_COLS + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + + + + + + + + + + + OnPlotFormatSelection + + + + + + + + 5 wxEXPAND @@ -939,96 +1018,6 @@ - - 5 - wxEXPAND|wxLEFT - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - "Postscript" "PDF" "SVG" "DXF" "HPGL" - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - Format - 1 - - 0 - - - 0 - - 1 - m_plotFormatOpt - 1 - - - protected - 1 - - Resizable - 1 - 1 - - wxRA_SPECIFY_COLS - - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - - - - - - - - - - - - - - - OnPlotFormatSelection - - - - - - - - 5 wxEXPAND|wxLEFT @@ -1678,7 +1667,7 @@ 1 - bSizer4 + bSizerMsgPanel wxVERTICAL none diff --git a/eeschema/dialogs/dialog_plot_schematic_base.h b/eeschema/dialogs/dialog_plot_schematic_base.h index f5a406bfd0..07127557ae 100644 --- a/eeschema/dialogs/dialog_plot_schematic_base.h +++ b/eeschema/dialogs/dialog_plot_schematic_base.h @@ -51,6 +51,7 @@ class DIALOG_PLOT_SCHEMATIC_BASE : public DIALOG_SHIM wxTextCtrl* m_outputDirectoryName; wxButton* m_browseButton; wxBoxSizer* m_optionsSizer; + wxRadioBox* m_plotFormatOpt; wxStaticBoxSizer* m_paperOptionsSizer; wxRadioBox* m_PaperSizeOption; wxStaticBoxSizer* m_paperHPGLSizer; @@ -59,7 +60,6 @@ class DIALOG_PLOT_SCHEMATIC_BASE : public DIALOG_SHIM wxRadioBox* m_plotOriginOpt; wxStaticText* m_penHPLGWidthTitle; wxTextCtrl* m_penHPGLWidthCtrl; - wxRadioBox* m_plotFormatOpt; wxStaticText* m_defaultLineWidthTitle; wxTextCtrl* m_DefaultLineSizeCtrl; wxRadioBox* m_ModeColorOption; @@ -73,8 +73,8 @@ class DIALOG_PLOT_SCHEMATIC_BASE : public DIALOG_SHIM // Virtual event handlers, overide them in your derived class virtual void OnCloseWindow( wxCloseEvent& event ) { event.Skip(); } virtual void OnOutputDirectoryBrowseClicked( wxCommandEvent& event ) { event.Skip(); } - virtual void OnHPGLPageSelected( wxCommandEvent& event ) { event.Skip(); } virtual void OnPlotFormatSelection( wxCommandEvent& event ) { event.Skip(); } + virtual void OnHPGLPageSelected( wxCommandEvent& event ) { event.Skip(); } virtual void OnButtonPlotCurrentClick( wxCommandEvent& event ) { event.Skip(); } virtual void OnButtonPlotAllClick( wxCommandEvent& event ) { event.Skip(); } virtual void OnButtonCancelClick( wxCommandEvent& event ) { event.Skip(); } diff --git a/eeschema/eeschema_config.cpp b/eeschema/eeschema_config.cpp index 1b585dbf1e..804045e45c 100644 --- a/eeschema/eeschema_config.cpp +++ b/eeschema/eeschema_config.cpp @@ -51,6 +51,7 @@ #include #include #include +#include #include @@ -438,16 +439,18 @@ PARAM_CFG_ARRAY& SCH_EDIT_FRAME::GetProjectFileParametersList() */ m_projectFileParams.push_back( new PARAM_CFG_WXSTRING( wxT( "NetFmtName" ), - &m_netListFormat) ); + &m_netListFormat) ); m_projectFileParams.push_back( new PARAM_CFG_BOOL( wxT( "SpiceForceRefPrefix" ), - &m_spiceNetlistAddReferencePrefix, false ) ); + &m_spiceNetlistAddReferencePrefix, false ) ); m_projectFileParams.push_back( new PARAM_CFG_BOOL( wxT( "SpiceUseNetNumbers" ), - &m_spiceNetlistUseNetcodeAsNetname, false ) ); + &m_spiceNetlistUseNetcodeAsNetname, false ) ); m_projectFileParams.push_back( new PARAM_CFG_INT( wxT( "LabSize" ), - &s_defaultTextSize, - DEFAULT_SIZE_TEXT, 5, - 1000 ) ); + &s_defaultTextSize, + DEFAULT_SIZE_TEXT, 5, 1000 ) ); + + m_projectFileParams.push_back( new PARAM_CFG_BOOL( wxT( "ERC_TestSimilarLabels" ), + &DIALOG_ERC::m_TestSimilarLabels, true ) ); return m_projectFileParams; } diff --git a/eeschema/erc.cpp b/eeschema/erc.cpp index 099249cf60..1105566086 100644 --- a/eeschema/erc.cpp +++ b/eeschema/erc.cpp @@ -119,9 +119,9 @@ const wxString CommentERC_V[] = /* Look up table which gives the diag for a pair of connected pins * Can be modified by ERC options. * at start up: must be loaded by DefaultDiagErc + * Can be modified in dialog ERC */ int DiagErc[PIN_NMAX][PIN_NMAX]; -bool DiagErcTableInit; // go to true after DiagErc init /** * Default Look up table which gives the ERC error level for a pair of connected pins @@ -196,6 +196,8 @@ int TestDuplicateSheetNames( bool aCreateMarker ) continue; // We have found a second sheet: compare names + // we are using case insensitive comparison to avoid mistakes between + // similar names like Mysheet and mysheet if( ( (SCH_SHEET*) item )->GetName().CmpNoCase( ( ( SCH_SHEET* ) test_item )->GetName() ) == 0 ) { @@ -502,20 +504,19 @@ void TestOthersItems( NETLIST_OBJECT_LIST* aList, } } - -int CountPinsInNet( NETLIST_OBJECT_LIST* aList, unsigned aNetStart ) +int NETLIST_OBJECT_LIST::CountPinsInNet( unsigned aNetStart ) { int count = 0; - int curr_net = aList->GetItemNet( aNetStart ); + int curr_net = GetItemNet( aNetStart ); /* Test pins connected to NetItemRef */ - for( unsigned item = aNetStart; item < aList->size(); item++ ) + for( unsigned item = aNetStart; item < size(); item++ ) { // We examine only a given net. We stop the search if the net changes - if( curr_net != aList->GetItemNet( item ) ) // End of net + if( curr_net != GetItemNet( item ) ) // End of net break; - if( aList->GetItemType( item ) == NET_PIN ) + if( GetItemType( item ) == NET_PIN ) count++; } @@ -571,7 +572,7 @@ bool WriteDiagnosticERC( const wxString& aFullFileName ) msg << wxString::Format( _( "\n ** ERC messages: %d Errors %d Warnings %d\n" ), total_count, err_count, warn_count ); - // Currently: write report unsing UTF8 (as usual in Kicad). + // Currently: write report using UTF8 (as usual in Kicad). // TODO: see if we can use the current encoding page (mainly for Windows users), // Or other format (HTML?) file.Write( msg ); @@ -582,7 +583,7 @@ bool WriteDiagnosticERC( const wxString& aFullFileName ) } -void TestLabel( NETLIST_OBJECT_LIST* aList, unsigned aNetItemRef, unsigned aStartNet ) +void NETLIST_OBJECT_LIST::TestforNonOrphanLabel( unsigned aNetItemRef, unsigned aStartNet ) { unsigned netItemTst = aStartNet; int erc = 1; @@ -594,24 +595,246 @@ void TestLabel( NETLIST_OBJECT_LIST* aList, unsigned aNetItemRef, unsigned aStar continue; /* Is always in the same net? */ - if( ( netItemTst == aList->size() ) - || ( aList->GetItemNet( aNetItemRef ) != aList->GetItemNet( netItemTst ) ) ) + if( ( netItemTst == size() ) + || ( GetItemNet( aNetItemRef ) != GetItemNet( netItemTst ) ) ) { /* End Netcode found. */ if( erc ) { /* Glabel or SheetLabel orphaned. */ - Diagnose( aList->GetItem( aNetItemRef ), NULL, -1, WAR ); + Diagnose( GetItem( aNetItemRef ), NULL, -1, WAR ); } return; } - if( aList->GetItem( aNetItemRef )->IsLabelConnected( aList->GetItem( netItemTst ) ) ) + if( GetItem( aNetItemRef )->IsLabelConnected( GetItem( netItemTst ) ) ) erc = 0; //same thing, different order. - if( aList->GetItem( netItemTst )->IsLabelConnected( aList->GetItem( aNetItemRef ) ) ) + if( GetItem( netItemTst )->IsLabelConnected( GetItem( aNetItemRef ) ) ) erc = 0; } } + + +// this code try to detect similar labels, i.e. labels which are identical +// when they are compared using case insensitive coparisons. + + +// A helper struct to compare NETLIST_OBJECT items by sheetpath and label texts +// for a std::set container +// the full text is "sheetpath+label" for local labels and "label" for global labels +struct compare_labels +{ + bool operator() ( const NETLIST_OBJECT* lab1, const NETLIST_OBJECT* lab2 ) + { + wxString str1 = lab1->m_SheetPath.Path() + lab1->m_Label; + wxString str2 = lab2->m_SheetPath.Path() + lab2->m_Label; + + return str1.Cmp( str2 ) < 0; + } +}; + +struct compare_label_names +{ + bool operator() ( const NETLIST_OBJECT* lab1, const NETLIST_OBJECT* lab2 ) + { + return lab1->m_Label.Cmp( lab2->m_Label ) < 0; + } +}; + +struct compare_paths +{ + bool operator() ( const NETLIST_OBJECT* lab1, const NETLIST_OBJECT* lab2 ) + { + return lab1->m_SheetPath.Path().Cmp( lab2->m_SheetPath.Path() ) < 0; + } +}; + +// Helper functions to build the warning messages about Similar Labels: +static int countIndenticalLabels( std::vector& aList, NETLIST_OBJECT* aLabel ); +static void SimilarLabelsDiagnose( NETLIST_OBJECT* aItemA, NETLIST_OBJECT* aItemB ); + + +void NETLIST_OBJECT_LIST::TestforSimilarLabels() +{ + // Similar labels which are different when using case sensitive comparisons + // but are equal when using case insensitive comparisons + + // list of all labels (used the better item to build diag messages) + std::vector fullLabelList; + // list of all labels , each label appears only once (used to to detect similar labels) + std::set uniqueLabelList; + wxString msg; + + // Build a list of differents labels. If inside a given sheet there are + // more than one given label, only one label is stored. + // not also the sheet labels are not taken in account for 2 reasons: + // * they are in the root sheet but they are seen only from the child sheet + // * any mismatch between child sheet hierarchical labels and the sheet label + // already detected by ERC + for( unsigned netItem = 0; netItem < size(); ++netItem ) + { + switch( GetItemType( netItem ) ) + { + case NET_LABEL: + case NET_BUSLABELMEMBER: + case NET_PINLABEL: + case NET_GLOBBUSLABELMEMBER: + case NET_HIERLABEL: + case NET_HIERBUSLABELMEMBER: + case NET_GLOBLABEL: + // add this label in lists + uniqueLabelList.insert( GetItem( netItem ) ); + fullLabelList.push_back( GetItem( netItem ) ); + break; + + case NET_SHEETLABEL: + case NET_SHEETBUSLABELMEMBER: + default: + break; + } + } + + // build global labels and compare + std::set loc_labelList; + std::set::const_iterator it; + + for( it = uniqueLabelList.begin(); it != uniqueLabelList.end(); ++it ) + { + if( (*it)->IsLabelGlobal() ) + loc_labelList.insert( *it ); + } + + // compare global labels (same label names appears only once in list) + for( it = loc_labelList.begin(); it != loc_labelList.end(); ++it ) + { + std::set::const_iterator it_aux = it; + + for( ++it_aux; it_aux != loc_labelList.end(); ++it_aux ) + { + if( (*it)->m_Label.CmpNoCase( (*it_aux)->m_Label ) == 0 ) + { + // Create new marker for ERC. + int cntA = countIndenticalLabels( fullLabelList, *it ); + int cntB = countIndenticalLabels( fullLabelList, *it_aux ); + + if( cntA <= cntB ) + SimilarLabelsDiagnose( (*it), (*it_aux) ); + else + SimilarLabelsDiagnose( (*it_aux), (*it) ); + } + } + } + + // Build paths list + std::set pathsList; + + for( it = uniqueLabelList.begin(); it != uniqueLabelList.end(); ++it ) + pathsList.insert( *it ); + + // Examine each label inside a sheet path: + for( it = pathsList.begin(); it != pathsList.end(); ++it ) + { + loc_labelList.clear(); + + std::set::const_iterator it_aux = uniqueLabelList.begin(); + + for( ; it_aux != uniqueLabelList.end(); ++it_aux ) + { + if( (*it)->m_SheetPath.Path() == (*it_aux)->m_SheetPath.Path() ) + loc_labelList.insert( *it_aux ); + } + + // at this point, loc_labelList contains labels of the current sheet path. + // Detect similar labels (same label names appears only once in list) + std::set::const_iterator ref_it; + + for( ref_it = loc_labelList.begin(); ref_it != loc_labelList.end(); ++ref_it ) + { + NETLIST_OBJECT* ref_item = *ref_it; + it_aux = ref_it; + + for( ++it_aux; it_aux != loc_labelList.end(); ++it_aux ) + { + // global label versus global label was already examined. + // here, at least one label must be local + if( ref_item->IsLabelGlobal() && (*it_aux)->IsLabelGlobal() ) + continue; + + if( ref_item->m_Label.CmpNoCase( (*it_aux)->m_Label ) == 0 ) + { + // Create new marker for ERC. + int cntA = countIndenticalLabels( fullLabelList, ref_item ); + int cntB = countIndenticalLabels( fullLabelList, *it_aux ); + + if( cntA <= cntB ) + SimilarLabelsDiagnose( ref_item, (*it_aux) ); + else + SimilarLabelsDiagnose( (*it_aux), ref_item ); + } + } + } + } +} + +// Helper function: count the number of labels identical to aLabel +// for global label: global labels in the full project +// for local label: all labels in the current sheet +static int countIndenticalLabels( std::vector& aList, NETLIST_OBJECT* aLabel ) +{ + int count = 0; + + if( aLabel->IsLabelGlobal() ) + { + for( unsigned netItem = 0; netItem < aList.size(); ++netItem ) + { + NETLIST_OBJECT* item = aList[netItem]; + + if( item->IsLabelGlobal() && item->m_Label == aLabel->m_Label ) + count++; + } + } + else + { + for( unsigned netItem = 0; netItem < aList.size(); ++netItem ) + { + NETLIST_OBJECT* item = aList[netItem]; + + if( item->m_Label == aLabel->m_Label && + item->m_SheetPath.Path() == aLabel->m_SheetPath.Path() ) + count++; + } + } + + return count; +} + +// Helper function: creates a marker for similar labels ERC warning +static void SimilarLabelsDiagnose( NETLIST_OBJECT* aItemA, NETLIST_OBJECT* aItemB ) +{ + // Create new marker for ERC. + SCH_MARKER* marker = new SCH_MARKER(); + + marker->SetTimeStamp( GetNewTimeStamp() ); + marker->SetMarkerType( MARKER_BASE::MARKER_ERC ); + marker->SetErrorLevel( MARKER_BASE::MARKER_SEVERITY_WARNING ); + SCH_SCREEN* screen = aItemA->m_SheetPath.LastScreen(); + screen->Append( marker ); + + wxString fmt = aItemA->IsLabelGlobal() ? + _( "Global label '%s' (sheet '%s') looks like:" ) : + _( "Local label '%s' (sheet '%s') looks like:" ); + wxString msg; + + msg.Printf( fmt, GetChars( aItemA->m_Label ), GetChars( aItemA->m_SheetPath.PathHumanReadable() ) ); + marker->SetData( aItemA->IsLabelGlobal() && aItemB->IsLabelGlobal() ? + ERCE_SIMILAR_GLBL_LABELS : ERCE_SIMILAR_LABELS, + aItemA->m_Start, msg, aItemA->m_Start ); + + fmt = aItemB->IsLabelGlobal() ? _( "Global label '%s' (sheet '%s')" ) : + _( "Local label '%s' (sheet '%s')" ); + msg.Printf( fmt, GetChars( aItemB->m_Label ), GetChars( aItemB->m_SheetPath.PathHumanReadable() ) ); + marker->SetAuxiliaryData( msg, aItemB->m_Start ); +} diff --git a/eeschema/erc.h b/eeschema/erc.h index 708fb6a4d0..76cec12b98 100644 --- a/eeschema/erc.h +++ b/eeschema/erc.h @@ -31,7 +31,7 @@ #define _ERC_H -class EDA_DRAW_PANEL; +//class EDA_DRAW_PANEL; class NETLIST_OBJECT; class NETLIST_OBJECT_LIST; @@ -58,6 +58,8 @@ extern const wxString CommentERC_V[]; #define ERCE_HIERACHICAL_LABEL 6 // mismatch between hierarchical labels and pins sheets #define ERCE_NOCONNECT_CONNECTED 7 // a no connect symbol is connected to more than 1 pin #define ERCE_GLOBLABEL 8 // global label not connected to any other global label +#define ERCE_SIMILAR_LABELS 9 // 2 labels are equal fir case insensitive comparisons +#define ERCE_SIMILAR_GLBL_LABELS 10 // 2 labels are equal fir case insensitive comparisons /* Minimal connection table */ #define NPI 4 // Net with Pin isolated, this pin has type Not Connected and must be left N.C. @@ -73,14 +75,14 @@ extern const wxString CommentERC_V[]; * * @param aFullFileName A wxString object containing the file name and path. */ -extern bool WriteDiagnosticERC( const wxString& aFullFileName ); +bool WriteDiagnosticERC( const wxString& aFullFileName ); /** * Performs ERC testing and creates an ERC marker to show the ERC problem for aNetItemRef * or between aNetItemRef and aNetItemTst. * if MinConn < 0: this is an error on labels */ -extern void Diagnose( NETLIST_OBJECT* NetItemRef, NETLIST_OBJECT* NetItemTst, +void Diagnose( NETLIST_OBJECT* NetItemRef, NETLIST_OBJECT* NetItemTst, int MinConnexion, int Diag ); /** @@ -92,27 +94,10 @@ extern void Diagnose( NETLIST_OBJECT* NetItemRef, NETLIST_OBJECT* NetItemTst, * @param aMinConnexion = a pointer to a variable to store the minimal connection * found( NOD, DRV, NPI, NET_NC) */ -extern void TestOthersItems( NETLIST_OBJECT_LIST* aList, +void TestOthersItems( NETLIST_OBJECT_LIST* aList, unsigned aNetItemRef, unsigned aNetStart, int* aMinConnexion ); -/** - * Counts number of pins connected on the same net. - * Used to find all pins conected to a no connect symbol - * @return the pin count of the net starting at aNetStart - * @param aNetStart = index in list of net objects of the first item - * @param aList = a reference to the list of connected objects - */ -int CountPinsInNet( NETLIST_OBJECT_LIST* aList, unsigned aNetStart ); - - -/** - * Function TestLabel - * performs an ERC on a sheet labels to verify that it is connected to a corresponding - * sub sheet global label. - */ -extern void TestLabel( NETLIST_OBJECT_LIST* aList, unsigned aNetItemRef, unsigned aStartNet ); - /** * Function TestDuplicateSheetNames( ) * inside a given sheet, one cannot have sheets with duplicate names (file @@ -121,7 +106,7 @@ extern void TestLabel( NETLIST_OBJECT_LIST* aList, unsigned aNetItemRef, unsigne * @param aCreateMarker: true = create error markers in schematic, * false = calculate error count only */ -extern int TestDuplicateSheetNames( bool aCreateMarker ); +int TestDuplicateSheetNames( bool aCreateMarker ); #endif // _ERC_H diff --git a/eeschema/netlist.cpp b/eeschema/netlist.cpp index c7a3aada51..ebc324570a 100644 --- a/eeschema/netlist.cpp +++ b/eeschema/netlist.cpp @@ -52,19 +52,12 @@ /** @brief Kicad can use case sensitive or case insensitive comparisons for labels * Currently, it uses case insensitive. - * Can be changed by defining LABEL_CASE_SENSITIVE (uncomment next line). + * Can be changed by comment/uncomment next lines. */ -//#define LABEL_CASE_SENSITIVE -/// Compiler controlled string compare function, either case independent or not: inline int CmpLabel_KEEPCASE( const wxString& aString1, const wxString& aString2 ) { -#ifdef LABEL_CASE_SENSITIVE - // case specificity, the normal behavior: - return aString1.Cmp( aString2 ); -#else - // case independence (only for guys who want that: not recommended) - return aString1.CmpNoCase( aString2 ); -#endif + return aString1.Cmp( aString2 ); // case sensitive + //return aString1.CmpNoCase( aString2 ); // case insensitive } diff --git a/eeschema/sch_sheet.cpp b/eeschema/sch_sheet.cpp index 4fae9d50a5..fc9d1e8809 100644 --- a/eeschema/sch_sheet.cpp +++ b/eeschema/sch_sheet.cpp @@ -1253,6 +1253,31 @@ bool SCH_SHEET::IsModified() const } +bool SCH_SHEET::IsAutoSaveRequired() +{ + if( m_screen->IsModify() ) + return true; + + bool retv = false; + SCH_ITEM* item = m_screen->GetDrawItems(); + + while( item && !retv ) + { + if( item->Type() == SCH_SHEET_T ) + { + SCH_SHEET* sheet = static_cast( item ); + + if( sheet->m_screen ) + retv = sheet->m_screen->IsSave(); + } + + item = item->Next(); + } + + return retv; +} + + void SCH_SHEET::ClearModifyStatus() { m_screen->ClrModify(); diff --git a/eeschema/sch_sheet.h b/eeschema/sch_sheet.h index 7ae3bb0a73..2d284cf118 100644 --- a/eeschema/sch_sheet.h +++ b/eeschema/sch_sheet.h @@ -649,6 +649,13 @@ public: */ void ClearModifyStatus(); + /** + * Function IsAutoSaveRequired + * checks the entire hierarchy for any modifications that require auto save. + * @return True if the hierarchy is modified otherwise false. + */ + bool IsAutoSaveRequired(); + #if defined(DEBUG) void Show( int nestLevel, std::ostream& os ) const; // override #endif diff --git a/eeschema/sch_sheet_path.cpp b/eeschema/sch_sheet_path.cpp index fec3ef6815..3b720c624a 100644 --- a/eeschema/sch_sheet_path.cpp +++ b/eeschema/sch_sheet_path.cpp @@ -684,18 +684,6 @@ void SCH_SHEET_LIST::BuildSheetList( SCH_SHEET* aSheet ) } -bool SCH_SHEET_LIST::IsAutoSaveRequired() -{ - for( SCH_SHEET_PATH* sheet = GetFirst(); sheet; sheet = GetNext() ) - { - if( sheet->LastScreen() && sheet->LastScreen()->IsSave() ) - return true; - } - - return false; -} - - void SCH_SHEET_LIST::AnnotatePowerSymbols( PART_LIBS* aLibs ) { int ref = 1; diff --git a/eeschema/sch_sheet_path.h b/eeschema/sch_sheet_path.h index 88376c47f6..30c6ee330a 100644 --- a/eeschema/sch_sheet_path.h +++ b/eeschema/sch_sheet_path.h @@ -436,13 +436,6 @@ public: */ SCH_SHEET_PATH* GetSheetByPath( const wxString aPath, bool aHumanReadable = true ); - /** - * Function IsAutoSaveRequired - * checks the entire hierarchy for any modifications that require auto save. - * @return True if the hierarchy is modified otherwise false. - */ - bool IsAutoSaveRequired(); - /** * Function AnnotatePowerSymbols * clear and annotates the entire hierarchy of the sheet path list. diff --git a/eeschema/schframe.cpp b/eeschema/schframe.cpp index 131f03e27b..a9c7a07e55 100644 --- a/eeschema/schframe.cpp +++ b/eeschema/schframe.cpp @@ -1179,12 +1179,9 @@ bool SCH_EDIT_FRAME::isAutoSaveRequired() const { // In case this event happens before g_RootSheet is initialized which does happen // on mingw64 builds. - if( g_RootSheet != NULL ) { - SCH_SHEET_LIST sheetList; - - return sheetList.IsAutoSaveRequired(); + return g_RootSheet->IsAutoSaveRequired(); } return false; diff --git a/include/eda_pattern_match.h b/include/eda_pattern_match.h new file mode 100644 index 0000000000..db0ec968a1 --- /dev/null +++ b/include/eda_pattern_match.h @@ -0,0 +1,98 @@ +/* -*- c++ -*- + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Chris Pavlina + * Copyright (C) 2015 KiCad Developers, see change_log.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 2 + * 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, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/** + * @file eda_pattern_match.h + * @brief Abstract pattern-matching tool and implementations. + */ + +#ifndef EDA_PATTERN_MATCH_H +#define EDA_PATTERN_MATCH_H + +#include +#include +#include +#include + +static const int EDA_PATTERN_NOT_FOUND = wxNOT_FOUND; + +/* + * Interface for a pattern matcher, for which there are several implementations + */ +class EDA_PATTERN_MATCH +{ +public: + virtual ~EDA_PATTERN_MATCH() {} + + /** + * Set the pattern against which candidates will be matched. If the pattern + * can not be processed, returns false. + */ + virtual bool SetPattern( const wxString& aPattern ) = 0; + + /** + * Return the location of a match iff a given candidate string matches the set pattern. + * Otherwise, return EDA_PATTERN_NOT_FOUND. + */ + virtual int Find( const wxString& aCandidate ) const = 0; +}; + + +/* + * Match simple substring + */ +class EDA_PATTERN_MATCH_SUBSTR : public EDA_PATTERN_MATCH +{ +public: + virtual bool SetPattern( const wxString& aPattern ); + virtual int Find( const wxString& aCandidate ) const; + +protected: + wxString m_pattern; +}; + + +/* + * Match regular expression + */ +class EDA_PATTERN_MATCH_REGEX : public EDA_PATTERN_MATCH +{ +public: + virtual bool SetPattern( const wxString& aPattern ); + virtual int Find( const wxString& aCandidate ) const; + +protected: + wxString m_pattern; + wxRegEx m_regex; +}; + + +class EDA_PATTERN_MATCH_WILDCARD : public EDA_PATTERN_MATCH_REGEX +{ +public: + virtual bool SetPattern( const wxString& aPattern ); + virtual int Find( const wxString& aCandidate ) const; +}; + +#endif // EDA_PATTERN_MATCH_H diff --git a/include/kicad_curl/kicad_curl.h b/include/kicad_curl/kicad_curl.h new file mode 100644 index 0000000000..3639400c92 --- /dev/null +++ b/include/kicad_curl/kicad_curl.h @@ -0,0 +1,82 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Mark Roszko + * Copyright (C) 2015 KiCad Developers, see CHANGELOG.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, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ +#ifndef KICAD_CURL_H_ +#define KICAD_CURL_H_ + +/* + * KICAD_CURL.h must be included before wxWidgets because on Windows, + * wxWidgets ends up including windows.h before winsocks2.h inside curl + * this causes build warnings + * Because we are before wx, we must explicitly define we are building with unicode. + * wxWidgets defaults to supporting unicode now, so this should be safe. + */ +#if defined(WIN32) + #ifndef UNICODE + # define UNICODE + #endif + + #ifndef _UNICODE + # define _UNICODE + #endif +#endif + +#include +#include + +/** + * Class KICAD_CURL + * simple wrapper class to call curl_global_init and curl_global_cleanup for KiCad. + */ +class KICAD_CURL +{ +public: + /** + * Function Init + * calls curl_global_init for the application. It must be used only once + * and before any curl functions that perform requests. + * + * @return bool - True if successful, false if CURL returned an error + */ + static bool Init(); + + /** + * Function Cleanup + * calls curl_global_cleanup for the application. It must be used only after + * curl_global_init was called. + */ + static void Cleanup(); + + /** + * Function GetVersion + * wrapper for curl_version(). Reports back a short string of loaded libraries. + * + * @return std::string - String reported by libcurl + */ + static std::string GetVersion(); + +private: + static bool m_initialized; +}; + +#endif // KICAD_CURL_H_ \ No newline at end of file diff --git a/include/kicad_curl/kicad_curl_easy.h b/include/kicad_curl/kicad_curl_easy.h new file mode 100644 index 0000000000..a87c3d02b1 --- /dev/null +++ b/include/kicad_curl/kicad_curl_easy.h @@ -0,0 +1,166 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Mark Roszko + * Copyright (C) 2015 KiCad Developers, see CHANGELOG.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, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ +#ifndef KICAD_CURL_EASY_H_ +#define KICAD_CURL_EASY_H_ + +/* + * KICAD_CURL_EASY.h must included before wxWidgets because on Windows, + * wxWidgets ends up including windows.h before winsocks2.h inside curl + * this causes build warnings + * Because we are before wx, we must explicitly define we are building with unicode + * wxWidgets defaults to supporting unicode now, so this should be safe. + */ +#if defined(WIN32) + #ifndef UNICODE + # define UNICODE + #endif + + #ifndef _UNICODE + # define _UNICODE + #endif +#endif + + +#include +#include + +/** + * Struct KICAD_EASY_CURL_BUFFER + * is a struct used for storing the libcurl received data in its callbacks. + * Do not use directly, KICAD_CURL_EASY uses it. + */ +struct KICAD_EASY_CURL_BUFFER +{ + char* payload; + size_t size; +}; + + +/** + * Class KICAD_CURL_EASY + * wrapper interface around the curl_easy API + * + * Handling of using the curl_easy API to make a request and save the response to + * a memory buffer + * + * Here is a small example usage: + * @code + * KICAD_CURL_EASY curl; + * curl.SetURL("http://github.com"); + * curl.SetUserAgent("KiCad-EDA"); + * curl.SetHeader("Accept", "application/json"); + * curl.Perform(); + * @endcode + */ +class KICAD_CURL_EASY +{ +public: + KICAD_CURL_EASY(); + ~KICAD_CURL_EASY(); + + /** + * Function perform + * equivalent to curl_easy_perform. Executes the request + * that was previously setup. + * + * @throw IO_ERROR, if there is a CURL request error + */ + void Perform(); + + /** + * Function SetHeader + * sets an arbitrary header for the HTTP(s) request. + * + * @param aName is the left hand side of the header, i.e. Accept without the colon + * @param aValue is the right hand side of the header, i.e. application/json + */ + void SetHeader( const std::string& aName, const std::string& aValue ); + + /** + * Function SetUserAgent + * sets the request user agent + * + * @param aAgent is the string to set for the user agent + * @return bool - True if successful, false if not + */ + bool SetUserAgent( const std::string& aAgent ); + + /** + * Function SetURL + * sets the request URL + * + * @param aURL is the URL + * @return bool - True if successful, false if not + */ + bool SetURL( const std::string& aURL ); + + /** + * Function SetFollowRedirects + * enables the following of HTTP(s) and other redirects, by default curl + * does not follow redirects. + * + * @param aFollow is a boolean where true will enable following redirects + * @return bool - True if successful, false if not + */ + bool SetFollowRedirects( bool aFollow ); + + /** + * Function GetErrorText + * fetches CURL's "friendly" error string for a given error code + * + * @param aCode is CURL error code + * @return std::string - the corresponding error string for the given code + */ + std::string GetErrorText( CURLcode aCode ); + + /** + * Function SetOption + * sets a curl option, only supports single parameter curl options + * + * @param aOption is CURL option, see CURL manual for options + * @param aArg is the argument being passed to CURL, ensure it is the right type per manual + * @return CURLcode - CURL error code, will return CURLE_OK unless a problem was encountered + */ + template CURLcode SetOption( CURLoption aOption, T aArg ) + { + return curl_easy_setopt( m_CURL, aOption, aArg ); + } + + /** + * Function GetBuffer + * returns a const pointer to the data buffer + * + * @return KICAD_EASY_CURL_BUFFER* - pointer to buffer + */ + const KICAD_EASY_CURL_BUFFER* GetBuffer() + { + return &m_Buffer; + } +private: + CURL *m_CURL; + struct curl_slist *m_headers; + struct KICAD_EASY_CURL_BUFFER m_Buffer; +}; + +#endif // KICAD_CURL_EASY_H_ \ No newline at end of file diff --git a/include/wxBasePcbFrame.h b/include/wxBasePcbFrame.h index d8607551f8..9a1177e98d 100644 --- a/include/wxBasePcbFrame.h +++ b/include/wxBasePcbFrame.h @@ -76,9 +76,6 @@ public: int m_FastGrid1; // 1st fast grid setting (index in EDA_DRAW_FRAME::m_gridSelectBox) int m_FastGrid2; // 2nd fast grid setting (index in EDA_DRAW_FRAME::m_gridSelectBox) - EDA_3D_FRAME* m_Draw3DFrame; - - protected: BOARD* m_Pcb; GENERAL_COLLECTOR* m_Collector; @@ -111,6 +108,11 @@ public: ~PCB_BASE_FRAME(); + /** + * @return a reference to the 3D viewer frame, when exists, or NULL + */ + EDA_3D_FRAME* Get3DViewerFrame(); + /** * Function LoadFootprint * attempts to load \a aFootprintId from the footprint library table. @@ -283,12 +285,17 @@ public: * puts up a dialog and allows the user to pick a library, for unspecified use. * * @param aNicknameExisting is the current choice to highlight - * * @return wxString - the library or wxEmptyString on abort. */ wxString SelectLibrary( const wxString& aNicknameExisting ); - MODULE* GetModuleByName(); + /** + * Function GetFootprintFromBoardByReference + * @return a reference to the footprint found by its refence + * on the curent board. the reference is entered by the user from + * a dialog (by awxTextCtlr, or a list of available references) + */ + MODULE* GetFootprintFromBoardByReference(); /** * Function OnModify diff --git a/include/wxPcbStruct.h b/include/wxPcbStruct.h index 8fcd89ac4b..82751702d8 100644 --- a/include/wxPcbStruct.h +++ b/include/wxPcbStruct.h @@ -1552,6 +1552,8 @@ public: // Autoplacement: void OnPlaceOrRouteFootprints( wxCommandEvent& event ); +#if defined( KICAD_SCRIPTING_WXPYTHON ) + /** * Function ScriptingConsoleEnableDisable * enables or disabled the scripting console @@ -1560,6 +1562,8 @@ public: void OnUpdateScriptingConsoleState( wxUpdateUIEvent& aEvent ); +#endif + void OnSelectAutoPlaceMode( wxCommandEvent& aEvent ); /** diff --git a/pcbnew/CMakeLists.txt b/pcbnew/CMakeLists.txt index ff99a93764..b5bc9101f5 100644 --- a/pcbnew/CMakeLists.txt +++ b/pcbnew/CMakeLists.txt @@ -88,6 +88,7 @@ set( PCBNEW_DIALOGS dialogs/dialog_gen_module_position_file_base.cpp dialogs/dialog_general_options.cpp dialogs/dialog_general_options_BoardEditor_base.cpp + dialogs/dialog_get_footprint_by_name_base.cpp dialogs/dialog_global_edit_tracks_and_vias.cpp dialogs/dialog_global_edit_tracks_and_vias_base.cpp dialogs/dialog_global_modules_fields_edition.cpp @@ -678,6 +679,12 @@ if( KICAD_SCRIPTING ) DESTINATION ${KICAD_DATA}/scripting/plugins FILE_PERMISSIONS OWNER_EXECUTE OWNER_READ OWNER_WRITE GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ ) + + # scripting python shell + install( DIRECTORY ${PROJECT_SOURCE_DIR}/pcbnew/scripting/kicad_pyshell/ + DESTINATION ${KICAD_DATA}/scripting/kicad_pyshell + FILE_PERMISSIONS OWNER_EXECUTE OWNER_READ OWNER_WRITE GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ + ) endif() if( KICAD_SCRIPTING_MODULES ) diff --git a/pcbnew/basepcbframe.cpp b/pcbnew/basepcbframe.cpp index a5a5f5f489..92d5a7f45b 100644 --- a/pcbnew/basepcbframe.cpp +++ b/pcbnew/basepcbframe.cpp @@ -39,6 +39,8 @@ #include #include +#include <3d_viewer.h> + #include #include #include @@ -98,7 +100,6 @@ PCB_BASE_FRAME::PCB_BASE_FRAME( KIWAY* aKiway, wxWindow* aParent, FRAME_T aFrame EDA_DRAW_FRAME( aKiway, aParent, aFrameType, aTitle, aPos, aSize, aStyle, aFrameName ) { m_Pcb = NULL; - m_Draw3DFrame = NULL; // Display Window in 3D mode (OpenGL) m_UserGridSize = wxRealPoint( 100.0, 100.0 ); m_UserGridUnit = INCHES; @@ -123,6 +124,14 @@ PCB_BASE_FRAME::~PCB_BASE_FRAME() } +EDA_3D_FRAME* PCB_BASE_FRAME::Get3DViewerFrame() +{ + // return the 3D viewer frame, when exists, or NULL + return dynamic_cast + ( wxWindow::FindWindowByName( VIEWER3D_FRAMENAME ) ); +} + + FP_LIB_TABLE* PROJECT::PcbFootprintLibs() { // This is a lazy loading function, it loads the project specific table when diff --git a/pcbnew/class_pad_draw_functions.cpp b/pcbnew/class_pad_draw_functions.cpp index 184d089870..f26bc00ce3 100644 --- a/pcbnew/class_pad_draw_functions.cpp +++ b/pcbnew/class_pad_draw_functions.cpp @@ -423,6 +423,7 @@ void D_PAD::DrawShape( EDA_RECT* aClipBox, wxDC* aDC, PAD_DRAWINFO& aDrawInfo ) blackpenstate = GetGRForceBlackPenState(); GRForceBlackPen( false ); aDrawInfo.m_HoleColor = WHITE; + aDrawInfo.m_NPHoleColor = WHITE; } else { diff --git a/pcbnew/dialogs/dialog_copper_zones.cpp b/pcbnew/dialogs/dialog_copper_zones.cpp index 53ebd2fc5d..46c77286fb 100644 --- a/pcbnew/dialogs/dialog_copper_zones.cpp +++ b/pcbnew/dialogs/dialog_copper_zones.cpp @@ -452,7 +452,9 @@ bool DIALOG_COPPER_ZONE::AcceptOptions( bool aPromptForErrors, bool aUseExportab (double) m_settings.m_ThermalReliefCopperBridge / IU_PER_MILS ); } - if( m_settings.m_ThermalReliefCopperBridge <= m_settings.m_ZoneMinThickness ) + if( ( m_settings.GetPadConnection() == PAD_ZONE_CONN_THT_THERMAL + || m_settings.GetPadConnection() == PAD_ZONE_CONN_THERMAL ) + && m_settings.m_ThermalReliefCopperBridge <= m_settings.m_ZoneMinThickness ) { DisplayError( this, _( "Thermal relief spoke must be greater than the minimum width." ) ); diff --git a/pcbnew/dialogs/dialog_find_base.fbp b/pcbnew/dialogs/dialog_find_base.fbp index 3d827182df..7ce64bc569 100644 --- a/pcbnew/dialogs/dialog_find_base.fbp +++ b/pcbnew/dialogs/dialog_find_base.fbp @@ -1,8 +1,8 @@ - + - + C++ 1 source_name @@ -16,9 +16,9 @@ none 1 dialog_find - + . - + 1 1 1 @@ -27,67 +27,67 @@ 0 wxAUI_MGR_DEFAULT - + wxBOTH - + 1 1 impl_virtual - - - + + + 0 wxID_ANY - - + + DIALOG_FIND_BASE - + -1,-1 wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER DIALOG_SHIM; dialog_shim.h Find - - - - - - - - - - - - - + + + + + + + + + + + + + onClose - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + - + bSizerMain wxHORIZONTAL none @@ -96,7 +96,7 @@ wxEXPAND|wxTOP|wxBOTTOM 1 - + bSizerLeft wxVERTICAL none @@ -109,78 +109,78 @@ 1 1 1 - - - - - - - + + + + + + + 1 0 1 - + 1 0 Dock 0 Left 1 - + 1 - + 0 0 wxID_ANY Search for: - + 0 - - + + 0 - + 1 m_staticText1 1 - - + + protected 1 - + Resizable 1 - - - + + + 0 - - - - + + + + -1 - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + @@ -192,86 +192,86 @@ 1 1 1 - - - - - - - + + + + + + + 1 0 1 - + 1 0 Dock 0 Left 1 - + 1 - + 0 0 wxID_ANY - + 0 - + 0 - + 0 - + 1 m_SearchTextCtrl 1 - - + + protected 1 - + Resizable 1 200,-1 - - + + 0 - - + + wxFILTER_NONE wxDefaultValidator - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -283,83 +283,83 @@ 1 1 1 - - - - - - - + + + + + + + 1 0 0 1 - + 1 0 Dock 0 Left 1 - + 1 - + 0 0 wxID_ANY Do not warp mouse pointer - + 0 - - + + 0 - + 1 m_NoMouseWarpCheckBox 1 - - + + protected 1 - + Resizable 1 - - - + + + 0 - - + + wxFILTER_NONE wxDefaultValidator - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -369,7 +369,7 @@ wxALL 0 - + bSizerRight wxVERTICAL none @@ -382,17 +382,17 @@ 1 1 1 - - - - - - - + + + + + + + 1 0 1 - + 1 1 0 @@ -400,65 +400,65 @@ 0 Left 1 - + 1 - + 0 0 wxID_ANY Find Item - + 0 - - + + 0 - + 1 m_button1 1 - - + + protected 1 - + Resizable 1 - - - + + + 0 - - + + wxFILTER_NONE wxDefaultValidator - - - - + + + + onButtonFindItemClick - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + @@ -470,17 +470,17 @@ 1 1 1 - - - - - - - + + + + + + + 1 0 1 - + 1 0 0 @@ -488,65 +488,65 @@ 0 Left 1 - + 1 - + 0 0 wxID_ANY Find Marker - + 0 - - + + 0 - + 1 m_button2 1 - - + + protected 1 - + Resizable 1 - - - + + + 0 - - + + wxFILTER_NONE wxDefaultValidator - - - - + + + + onButtonFindMarkerClick - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + @@ -558,17 +558,17 @@ 1 1 1 - - - - - - - + + + + + + + 1 0 1 - + 1 0 0 @@ -576,65 +576,65 @@ 0 Left 1 - + 1 - + 0 0 wxID_CANCEL Close - + 0 - - + + 0 - + 1 m_button3 1 - - + + protected 1 - + Resizable 1 - - - + + + 0 - - + + wxFILTER_NONE wxDefaultValidator - - - - + + + + onButtonCloseClick - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pcbnew/dialogs/dialog_get_footprint_by_name.h b/pcbnew/dialogs/dialog_get_footprint_by_name.h new file mode 100644 index 0000000000..2f4bbf347f --- /dev/null +++ b/pcbnew/dialogs/dialog_get_footprint_by_name.h @@ -0,0 +1,68 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 1992-2015 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 2 + * 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, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/** + * @file dialog_get_footprint_by_name.h + */ + +#ifndef DIALOG_GET_FOOTPRINT_BY_NAME_H +#define DIALOG_GET_FOOTPRINT_BY_NAME_H + +#include + +/** + * DIALOG_GET_FOOTPRINT_BY_NAME is a helper dialog to select a footprint by its reference + * One can enter any reference or select it in the list of fp references + * Get a footprint ref from user and return a pointer to the corresponding footprint + */ +class DIALOG_GET_FOOTPRINT_BY_NAME: public DIALOG_GET_FOOTPRINT_BY_NAME_BASE +{ +public: + DIALOG_GET_FOOTPRINT_BY_NAME( PCB_BASE_FRAME* aParent, wxArrayString& aFpList ) : + DIALOG_GET_FOOTPRINT_BY_NAME_BASE( aParent ) + { + m_sdbSizerOK->SetDefault(); + m_choiceFpList->Append( aFpList ); + + // Dialog should not shrink beyond it's minimal size. + GetSizer()->SetSizeHints( this ); + } + + // returns the selected text (fp reference) + const wxString GetValue() + { + return m_SearchTextCtrl->GetValue(); + } + +private: + // Called when selecting an item from the item list + void OnSelectFootprint( wxCommandEvent& aEvent ) + { + if( m_choiceFpList->GetSelection() >= 0 ) + m_SearchTextCtrl->SetValue( + m_choiceFpList->GetString( m_choiceFpList->GetSelection() ).BeforeFirst( ' ' ) ); + } +}; + +#endif // #ifndef DIALOG_GET_FOOTPRINT_BY_NAME_H diff --git a/pcbnew/dialogs/dialog_get_footprint_by_name_base.cpp b/pcbnew/dialogs/dialog_get_footprint_by_name_base.cpp new file mode 100644 index 0000000000..3b5b5d43af --- /dev/null +++ b/pcbnew/dialogs/dialog_get_footprint_by_name_base.cpp @@ -0,0 +1,79 @@ +/////////////////////////////////////////////////////////////////////////// +// C++ code generated with wxFormBuilder (version Jun 17 2015) +// http://www.wxformbuilder.org/ +// +// PLEASE DO "NOT" EDIT THIS FILE! +/////////////////////////////////////////////////////////////////////////// + +#include "dialog_get_footprint_by_name_base.h" + +/////////////////////////////////////////////////////////////////////////// + +DIALOG_GET_FOOTPRINT_BY_NAME_BASE::DIALOG_GET_FOOTPRINT_BY_NAME_BASE( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : DIALOG_SHIM( parent, id, title, pos, size, style ) +{ + this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + + wxBoxSizer* bSizerMain; + bSizerMain = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizerUpper; + bSizerUpper = new wxBoxSizer( wxHORIZONTAL ); + + wxFlexGridSizer* fgSizer1; + fgSizer1 = new wxFlexGridSizer( 0, 2, 0, 0 ); + fgSizer1->SetFlexibleDirection( wxBOTH ); + fgSizer1->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + + m_staticTextRef = new wxStaticText( this, wxID_ANY, _("Reference:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextRef->Wrap( -1 ); + fgSizer1->Add( m_staticTextRef, 0, wxTOP|wxRIGHT|wxLEFT|wxALIGN_CENTER_VERTICAL, 5 ); + + m_SearchTextCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 200,-1 ), 0 ); + m_SearchTextCtrl->SetMaxLength( 0 ); + fgSizer1->Add( m_SearchTextCtrl, 0, wxEXPAND|wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + m_staticTextRef1 = new wxStaticText( this, wxID_ANY, _("Available:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextRef1->Wrap( -1 ); + fgSizer1->Add( m_staticTextRef1, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + wxArrayString m_choiceFpListChoices; + m_choiceFpList = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_choiceFpListChoices, 0 ); + m_choiceFpList->SetSelection( 0 ); + fgSizer1->Add( m_choiceFpList, 0, wxALL|wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 ); + + + bSizerUpper->Add( fgSizer1, 1, wxEXPAND, 5 ); + + + bSizerMain->Add( bSizerUpper, 1, wxEXPAND, 5 ); + + m_staticline1 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizerMain->Add( m_staticline1, 0, wxEXPAND|wxTOP|wxBOTTOM, 5 ); + + m_sdbSizer = new wxStdDialogButtonSizer(); + m_sdbSizerOK = new wxButton( this, wxID_OK ); + m_sdbSizer->AddButton( m_sdbSizerOK ); + m_sdbSizerCancel = new wxButton( this, wxID_CANCEL ); + m_sdbSizer->AddButton( m_sdbSizerCancel ); + m_sdbSizer->Realize(); + + bSizerMain->Add( m_sdbSizer, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); + + + this->SetSizer( bSizerMain ); + this->Layout(); + + this->Centre( wxBOTH ); + + // Connect Events + this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DIALOG_GET_FOOTPRINT_BY_NAME_BASE::onClose ) ); + m_choiceFpList->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_GET_FOOTPRINT_BY_NAME_BASE::OnSelectFootprint ), NULL, this ); +} + +DIALOG_GET_FOOTPRINT_BY_NAME_BASE::~DIALOG_GET_FOOTPRINT_BY_NAME_BASE() +{ + // Disconnect Events + this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DIALOG_GET_FOOTPRINT_BY_NAME_BASE::onClose ) ); + m_choiceFpList->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_GET_FOOTPRINT_BY_NAME_BASE::OnSelectFootprint ), NULL, this ); + +} diff --git a/pcbnew/dialogs/dialog_get_footprint_by_name_base.fbp b/pcbnew/dialogs/dialog_get_footprint_by_name_base.fbp new file mode 100644 index 0000000000..ef7fa81e34 --- /dev/null +++ b/pcbnew/dialogs/dialog_get_footprint_by_name_base.fbp @@ -0,0 +1,580 @@ + + + + + + C++ + 1 + source_name + 0 + 0 + res + UTF-8 + connect + dialog_get_footprint_by_name_base + 1000 + none + 1 + dialog_get_footprint_by_name + + . + + 1 + 1 + 1 + 1 + UI + 0 + 0 + + 0 + wxAUI_MGR_DEFAULT + + wxBOTH + + 1 + 1 + impl_virtual + + + + 0 + wxID_ANY + + + DIALOG_GET_FOOTPRINT_BY_NAME_BASE + + 341,176 + wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER + DIALOG_SHIM; dialog_shim.h + Search for footprint + + + + + + + + + + + + + + onClose + + + + + + + + + + + + + + + + + + + + + + + + + + + + + bSizerMain + wxVERTICAL + none + + 5 + wxEXPAND + 1 + + + bSizerUpper + wxHORIZONTAL + none + + 5 + wxEXPAND + 1 + + 2 + wxBOTH + + + 0 + + fgSizer1 + wxFLEX_GROWMODE_SPECIFIED + none + 0 + 0 + + 5 + wxTOP|wxRIGHT|wxLEFT|wxALIGN_CENTER_VERTICAL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Reference: + + 0 + + + 0 + + 1 + m_staticTextRef + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxEXPAND|wxALL|wxALIGN_CENTER_VERTICAL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + 0 + + 0 + + 1 + m_SearchTextCtrl + 1 + + + protected + 1 + + Resizable + 1 + 200,-1 + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALL|wxALIGN_CENTER_VERTICAL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Available: + + 0 + + + 0 + + 1 + m_staticTextRef1 + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALL|wxEXPAND|wxALIGN_CENTER_VERTICAL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + + 1 + m_choiceFpList + 1 + + + protected + 1 + + Resizable + 0 + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + OnSelectFootprint + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxEXPAND|wxTOP|wxBOTTOM + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + + 1 + m_staticline1 + 1 + + + protected + 1 + + Resizable + 1 + + wxLI_HORIZONTAL + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT + 0 + + 0 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + + m_sdbSizer + protected + + + + + + + + + + + + + + diff --git a/pcbnew/dialogs/dialog_get_footprint_by_name_base.h b/pcbnew/dialogs/dialog_get_footprint_by_name_base.h new file mode 100644 index 0000000000..f8e8aecd2e --- /dev/null +++ b/pcbnew/dialogs/dialog_get_footprint_by_name_base.h @@ -0,0 +1,62 @@ +/////////////////////////////////////////////////////////////////////////// +// C++ code generated with wxFormBuilder (version Jun 17 2015) +// http://www.wxformbuilder.org/ +// +// PLEASE DO "NOT" EDIT THIS FILE! +/////////////////////////////////////////////////////////////////////////// + +#ifndef __DIALOG_GET_FOOTPRINT_BY_NAME_BASE_H__ +#define __DIALOG_GET_FOOTPRINT_BY_NAME_BASE_H__ + +#include +#include +#include +class DIALOG_SHIM; + +#include "dialog_shim.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////////////// + + +/////////////////////////////////////////////////////////////////////////////// +/// Class DIALOG_GET_FOOTPRINT_BY_NAME_BASE +/////////////////////////////////////////////////////////////////////////////// +class DIALOG_GET_FOOTPRINT_BY_NAME_BASE : public DIALOG_SHIM +{ + private: + + protected: + wxStaticText* m_staticTextRef; + wxTextCtrl* m_SearchTextCtrl; + wxStaticText* m_staticTextRef1; + wxChoice* m_choiceFpList; + wxStaticLine* m_staticline1; + wxStdDialogButtonSizer* m_sdbSizer; + wxButton* m_sdbSizerOK; + wxButton* m_sdbSizerCancel; + + // Virtual event handlers, overide them in your derived class + virtual void onClose( wxCloseEvent& event ) { event.Skip(); } + virtual void OnSelectFootprint( wxCommandEvent& event ) { event.Skip(); } + + + public: + + DIALOG_GET_FOOTPRINT_BY_NAME_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Search for footprint"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 341,176 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); + ~DIALOG_GET_FOOTPRINT_BY_NAME_BASE(); + +}; + +#endif //__DIALOG_GET_FOOTPRINT_BY_NAME_BASE_H__ diff --git a/pcbnew/edit.cpp b/pcbnew/edit.cpp index aa8001d899..eae9b4cd75 100644 --- a/pcbnew/edit.cpp +++ b/pcbnew/edit.cpp @@ -703,7 +703,7 @@ void PCB_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) break; case ID_POPUP_PCB_GET_AND_MOVE_MODULE_REQUEST: // get module by name and move it - SetCurItem( GetModuleByName() ); + SetCurItem( GetFootprintFromBoardByReference() ); module = (MODULE*) GetCurItem(); if( module == NULL ) diff --git a/pcbnew/files.cpp b/pcbnew/files.cpp index 1567f2ceae..f4e9793ccf 100644 --- a/pcbnew/files.cpp +++ b/pcbnew/files.cpp @@ -597,8 +597,10 @@ bool PCB_EDIT_FRAME::OpenProjectFiles( const std::vector& aFileSet, in SetMsgPanel( GetBoard() ); // Refresh the 3D view, if any - if( m_Draw3DFrame ) - m_Draw3DFrame->NewDisplay(); + EDA_3D_FRAME* draw3DFrame = Get3DViewerFrame(); + + if( draw3DFrame ) + draw3DFrame->NewDisplay(); #if 0 && defined(DEBUG) // Output the board object tree to stdout, but please run from command prompt: diff --git a/pcbnew/footprint_wizard_frame.cpp b/pcbnew/footprint_wizard_frame.cpp index 81f2640e2a..ff4009ef18 100644 --- a/pcbnew/footprint_wizard_frame.cpp +++ b/pcbnew/footprint_wizard_frame.cpp @@ -210,8 +210,10 @@ FOOTPRINT_WIZARD_FRAME::FOOTPRINT_WIZARD_FRAME( KIWAY* aKiway, FOOTPRINT_WIZARD_FRAME::~FOOTPRINT_WIZARD_FRAME() { - if( m_Draw3DFrame ) - m_Draw3DFrame->Destroy(); + EDA_3D_FRAME* draw3DFrame = Get3DViewerFrame(); + + if( draw3DFrame ) + draw3DFrame->Destroy(); } @@ -513,26 +515,28 @@ bool FOOTPRINT_WIZARD_FRAME::GeneralControl( wxDC* aDC, const wxPoint& aPosition void FOOTPRINT_WIZARD_FRAME::Show3D_Frame( wxCommandEvent& event ) { - if( m_Draw3DFrame ) + EDA_3D_FRAME* draw3DFrame = Get3DViewerFrame(); + + if( draw3DFrame ) { // Raising the window does not show the window on Windows if iconized. // This should work on any platform. - if( m_Draw3DFrame->IsIconized() ) - m_Draw3DFrame->Iconize( false ); + if( draw3DFrame->IsIconized() ) + draw3DFrame->Iconize( false ); - m_Draw3DFrame->Raise(); + draw3DFrame->Raise(); // Raising the window does not set the focus on Linux. This should work on any platform. - if( wxWindow::FindFocus() != m_Draw3DFrame ) - m_Draw3DFrame->SetFocus(); + if( wxWindow::FindFocus() != draw3DFrame ) + draw3DFrame->SetFocus(); return; } - m_Draw3DFrame = new EDA_3D_FRAME( &Kiway(), this, wxEmptyString ); + draw3DFrame = new EDA_3D_FRAME( &Kiway(), this, wxEmptyString ); Update3D_Frame( false ); - m_Draw3DFrame->Raise(); // Needed with some Window Managers - m_Draw3DFrame->Show( true ); + draw3DFrame->Raise(); // Needed with some Window Managers + draw3DFrame->Show( true ); } @@ -543,20 +547,22 @@ void FOOTPRINT_WIZARD_FRAME::Show3D_Frame( wxCommandEvent& event ) */ void FOOTPRINT_WIZARD_FRAME::Update3D_Frame( bool aForceReloadFootprint ) { - if( m_Draw3DFrame == NULL ) + EDA_3D_FRAME* draw3DFrame = Get3DViewerFrame(); + + if( draw3DFrame == NULL ) return; wxString frm3Dtitle; frm3Dtitle.Printf( _( "ModView: 3D Viewer [%s]" ), GetChars( m_wizardName ) ); - m_Draw3DFrame->SetTitle( frm3Dtitle ); + draw3DFrame->SetTitle( frm3Dtitle ); if( aForceReloadFootprint ) { - m_Draw3DFrame->ReloadRequest(); + draw3DFrame->ReloadRequest(); // Force 3D screen refresh immediately if( GetBoard()->m_Modules ) - m_Draw3DFrame->NewDisplay(); + draw3DFrame->NewDisplay(); } } diff --git a/pcbnew/github/CMakeLists.txt b/pcbnew/github/CMakeLists.txt index c1a4ee1f0f..758c0fc7a7 100644 --- a/pcbnew/github/CMakeLists.txt +++ b/pcbnew/github/CMakeLists.txt @@ -24,28 +24,15 @@ # Download avhttp and install the headers, not actually compiled ################################################# -include( download_avhttp ) - -find_package( OpenSSL REQUIRED ) -#message( STATUS "OPENSSL_FOUND:${OPENSSL_FOUND} OPENSSL_LIBRARIES:${OPENSSL_LIBRARIES}" ) - -# FindOpenSSL.cmake does not set this var into cache, so is not globally visible, -# do it here incase some other link image needs these libraries -set( OPENSSL_LIBRARIES "${OPENSSL_LIBRARIES}" CACHE FILEPATH "OpenSSL link libraries" ) -set( OPENSSL_INCLUDE_DIR "${OPENSSL_INCLUDE_DIR}" CACHE FILEPATH "OpenSSL include dir" ) # These are additions to any inherited from pcbnew dir: -include_directories( . ${OPENSSL_INCLUDE_DIR} ${AVHTTP_INCLUDE_DIR} ) +include_directories( . ) # Tell AVHTTP we have SSL. -add_definitions( -DAVHTTP_ENABLE_OPENSSL ) - -# tone down the compiler warnings for avhttp header library: -set( CMAKE_CXX_FLAGS - "${CMAKE_CXX_FLAGS} -Wno-sign-compare -Wno-reorder -Wno-unused-variable -Wno-unused-function -Wno-strict-aliasing" ) - set( GITHUB_PLUGIN_SRCS - github_plugin.cpp github_getliblist.cpp html_link_parser.cpp + github_plugin.cpp + github_getliblist.cpp + html_link_parser.cpp ) add_library( github_plugin STATIC ${GITHUB_PLUGIN_SRCS} ) @@ -53,7 +40,7 @@ add_library( github_plugin STATIC ${GITHUB_PLUGIN_SRCS} ) # No, you don't get github without boost and openssl. Boost_LIBRARIES now moved up # into CMakeLists.txt for pcbnew and cvpcb: target_link_libraries( github_plugin - ${OPENSSL_LIBRARIES} + common ) if( MINGW ) @@ -64,9 +51,4 @@ if( MINGW ) endif() add_dependencies( github_plugin boost ) -add_dependencies( github_plugin avhttp ) - -if( MINGW AND NOT OPENSSL_ROOT_DIR ) - add_dependencies( github_plugin openssl ) -endif() diff --git a/pcbnew/github/github_getliblist.cpp b/pcbnew/github/github_getliblist.cpp index 7ef26553b2..4802013946 100644 --- a/pcbnew/github/github_getliblist.cpp +++ b/pcbnew/github/github_getliblist.cpp @@ -41,35 +41,7 @@ * JP Charras. */ - -#if 0 -/* - * FIX ME - * I do not include avhttp.hpp here, because it is already included in - * github_plugin.cpp - * and if it is also included in this file, the link fails (double definiton of modules) - * therefore, the GITHUB_GETLIBLIST method which uses avhttp to download dats from gitub - * is in github_plugin.cpp - */ - -#ifndef WIN32_LEAN_AND_MEAN -// when WIN32_LEAN_AND_MEAN is defined, some useless includes in -// are skipped, and this avoid some compil issues -#define WIN32_LEAN_AND_MEAN -#endif - -#ifdef WIN32 -// defines needed by avhttp -// Minimal Windows version is XP: Google for _WIN32_WINNT - #define _WIN32_WINNT 0x0501 - #define WINVER 0x0501 -#endif - -#include -#include - -#endif - +#include /* Include before any wx file */ #include #include @@ -97,7 +69,7 @@ bool GITHUB_GETLIBLIST::Get3DshapesLibsList( wxArrayString* aList, wxString errorMsg; fullURLCommand = repoURL.utf8_str(); - bool success = remote_get_json( &fullURLCommand, &errorMsg ); + bool success = remoteGetJSON( fullURLCommand, &errorMsg ); if( !success ) { @@ -147,7 +119,7 @@ bool GITHUB_GETLIBLIST::GetFootprintLibraryList( wxArrayString& aList ) while( 1 ) { - bool success = remote_get_json( &fullURLCommand, &errorMsg ); + bool success = remoteGetJSON( fullURLCommand, &errorMsg ); if( !success ) { @@ -232,3 +204,37 @@ bool GITHUB_GETLIBLIST::repoURL2listURL( const wxString& aRepoURL, return false; } + + +bool GITHUB_GETLIBLIST::remoteGetJSON( const std::string& aFullURLCommand, wxString* aMsgError ) +{ + KICAD_CURL_EASY kcurl; + + wxLogDebug( wxT( "Attempting to download: " ) + aFullURLCommand ); + + kcurl.SetURL(aFullURLCommand); + kcurl.SetUserAgent("KiCad-EDA"); + kcurl.SetHeader("Accept", m_option_string); + kcurl.SetFollowRedirects(true); + + try + { + kcurl.Perform(); + m_image.assign(kcurl.GetBuffer()->payload, kcurl.GetBuffer()->size); + return true; + } + catch( const IO_ERROR& ioe ) + { + if( aMsgError ) + { + UTF8 fmt( _( "Error fetching JSON data from URL '%s'.\nReason: '%s'" ) ); + + std::string msg = StrPrintf( fmt.c_str(), + aFullURLCommand.c_str(), + TO_UTF8( ioe.errorText ) ); + + *aMsgError = FROM_UTF8( msg.c_str() ); + } + return false; + } +} \ No newline at end of file diff --git a/pcbnew/github/github_getliblist.h b/pcbnew/github/github_getliblist.h index 6fd059800f..0d38b8aebc 100644 --- a/pcbnew/github/github_getliblist.h +++ b/pcbnew/github/github_getliblist.h @@ -103,7 +103,7 @@ protected: int aItemCountMax, int aPage = 1 ); /** - * Function remote_get_json + * Function remoteGetJSON * Download a json text from a github repo. The text image * is received into the m_input_stream. * @param aFullURLCommand the full command, i.e. the url with options like @@ -111,7 +111,7 @@ protected: * @param aMsgError a pointer to a wxString which can store an error message * @return true if OK, false if error (which an error message in *aMsgError */ - bool remote_get_json( std::string* aFullURLCommand, wxString* aMsgError ); + bool remoteGetJSON( const std::string& aFullURLCommand, wxString* aMsgError ); wxString m_github_path; ///< Something like https://api.github.com/orgs/KiCad std::string m_image; ///< image of the downloaded data in its entirety. diff --git a/pcbnew/github/github_plugin.cpp b/pcbnew/github/github_plugin.cpp index 5da5c40a49..0039734478 100644 --- a/pcbnew/github/github_plugin.cpp +++ b/pcbnew/github/github_plugin.cpp @@ -38,8 +38,7 @@ I have lost my enthusiasm for local caching until a faster time stamp retrieval mechanism can be found, or github gets more servers. But note that the occasionally slow response is the exception rather than the norm. Normally the response is down around a 1/3 of a second. The information we would use is in the header -named "Last-Modified" as seen below. This would need parsing, but avhttp may -offer some help there, if not, then boost async probably does. +named "Last-Modified" as seen below. HTTP/1.1 200 OK @@ -64,20 +63,7 @@ X-GitHub-Request-Id: 411087C2:659E:50FD6E6:52E67F66 Vary: Accept-Encoding */ - - -#ifndef WIN32_LEAN_AND_MEAN -// when WIN32_LEAN_AND_MEAN is defined, some useless includes in -// are skipped, and this avoid some compil issues -#define WIN32_LEAN_AND_MEAN -#endif - -#ifdef WIN32 - // defines needed by avhttp - // Minimal Windows version is XP: Google for _WIN32_WINNT - #define _WIN32_WINNT 0x0501 - #define WINVER 0x0501 -#endif +#include /* Include before any wx file */ #include #include @@ -88,10 +74,6 @@ Vary: Accept-Encoding #include #include -// Under Windows Mingw/msys, avhttp.hpp should be included after fctsys.h -// in fact after wx/wx.h, included by fctsys.h, -// to avoid issues (perhaps due to incompatible defines) -#include // chinese SSL magic #include #include @@ -103,6 +85,7 @@ Vary: Accept-Encoding #include // ExpandSubstitutions() #include + using namespace std; @@ -431,7 +414,7 @@ void GITHUB_PLUGIN::cacheLib( const wxString& aLibraryPath, const PROPERTIES* aP m_gh_cache = new GH_CACHE(); // INIT_LOGGER( "/tmp", "test.log" ); - remote_get_zip( aLibraryPath ); + remoteGetZip( aLibraryPath ); // UNINIT_LOGGER(); m_lib_path = aLibraryPath; @@ -460,7 +443,7 @@ void GITHUB_PLUGIN::cacheLib( const wxString& aLibraryPath, const PROPERTIES* aP } -bool GITHUB_PLUGIN::repoURL_zipURL( const wxString& aRepoURL, string* aZipURL ) +bool GITHUB_PLUGIN::repoURL_zipURL( const wxString& aRepoURL, std::string& aZipURL ) { // e.g. "https://github.com/liftoff-sr/pretty_footprints" //D(printf("aRepoURL:%s\n", TO_UTF8( aRepoURL ) );) @@ -470,12 +453,12 @@ bool GITHUB_PLUGIN::repoURL_zipURL( const wxString& aRepoURL, string* aZipURL ) if( repo.HasServer() && repo.HasPath() ) { // scheme might be "http" or if truly github.com then "https". - wxString zip_url = repo.GetScheme(); - - zip_url += "://"; + wxString zip_url; if( repo.GetServer() == "github.com" ) { + //codeload.github.com only supports https + zip_url = "https://"; #if 0 // A proper code path would be this one, but it is not the fastest. zip_url += repo.GetServer(); zip_url += repo.GetPath(); // path comes with a leading '/' @@ -488,8 +471,6 @@ bool GITHUB_PLUGIN::repoURL_zipURL( const wxString& aRepoURL, string* aZipURL ) // In order to bypass this redirect, saving time, we use the // redirected URL on first attempt to save one HTTP GET hit. - // avhttp would do the redirect behind the scenes normally, but that would - // be slower than doing this bypass. zip_url += "codeload.github.com"; zip_url += repo.GetPath(); // path comes with a leading '/' zip_url += "/zip/master"; @@ -498,9 +479,11 @@ bool GITHUB_PLUGIN::repoURL_zipURL( const wxString& aRepoURL, string* aZipURL ) else { + zip_url = repo.GetScheme(); + zip_url += "://"; + // This is the generic code path for any server which can serve // up zip files. The schemes tested include: http and https. - // (I don't know what the avhttp library supports beyond that.) // zip_url goal: "://[:]/" @@ -526,124 +509,48 @@ bool GITHUB_PLUGIN::repoURL_zipURL( const wxString& aRepoURL, string* aZipURL ) // this code path with the needs of one particular inflexible server. } - *aZipURL = zip_url.utf8_str(); + aZipURL = zip_url.utf8_str(); return true; } return false; } -void GITHUB_PLUGIN::remote_get_zip( const wxString& aRepoURL ) throw( IO_ERROR ) +void GITHUB_PLUGIN::remoteGetZip( const wxString& aRepoURL ) throw( IO_ERROR ) { - string zip_url; + std::string zip_url; - if( !repoURL_zipURL( aRepoURL, &zip_url ) ) + if( !repoURL_zipURL( aRepoURL, zip_url ) ) { wxString msg = wxString::Format( _( "Unable to parse URL:\n'%s'" ), GetChars( aRepoURL ) ); THROW_IO_ERROR( msg ); } - boost::asio::io_service io; - avhttp::http_stream h( io ); - avhttp::request_opts options; + wxLogDebug( wxT( "Attempting to download: " ) + zip_url ); - options.insert( "Accept", "application/zip" ); - options.insert( "User-Agent", "http://kicad-pcb.org" ); // THAT WOULD BE ME. - h.request_options( options ); + KICAD_CURL_EASY kcurl; + + kcurl.SetURL(zip_url.c_str()); + kcurl.SetUserAgent("KiCad-EDA"); + kcurl.SetHeader("Accept", "application/zip"); + kcurl.SetFollowRedirects(true); try { - ostringstream os; - - h.open( zip_url ); // only one file, therefore do it synchronously. - os << &h; - - // Keep zip file byte image in RAM. That plus the MODULE_MAP will constitute - // the cache. We don't cache the MODULEs per se, we parse those as needed from - // this zip file image. - m_zip_image = os.str(); - - // 4 lines, using SSL, top that. + kcurl.Perform(); + m_zip_image.assign(kcurl.GetBuffer()->payload, kcurl.GetBuffer()->size); } - catch( const boost::system::system_error& e ) + catch( const IO_ERROR& ioe ) { - // https "GET" has faild, report this to API caller. - static const char errorcmd[] = "http GET command failed"; // Do not translate this message - UTF8 fmt( _( "%s\nCannot get/download Zip archive: '%s'\nfor library path: '%s'.\nReason: '%s'" ) ); - string msg = StrPrintf( fmt.c_str(), - errorcmd, - // Report both secret zip_url and Lib Path, to user. The secret - // zip_url may go bad at some point in future if github changes - // their server architecture. Then fix repoURL_zipURL() to reflect - // new architecture. - zip_url.c_str(), TO_UTF8( aRepoURL ), - e.what() ); + std::string msg = StrPrintf( fmt.c_str(), + zip_url.c_str(), + TO_UTF8( aRepoURL ), + TO_UTF8( ioe.errorText ) ); THROW_IO_ERROR( msg ); } - catch( const exception& exc ) - { - UTF8 error( _( "Exception '%s' in avhttp while open()-ing URI:'%s'" ) ); - - string msg = StrPrintf( error.c_str(), exc.what(), zip_url.c_str() ); - THROW_IO_ERROR( msg ); - } -} - - -// This GITHUB_GETLIBLIST method should not be here, but in github_getliblist.cpp ! -// However it is here just because we need to include to compile it. -// and when we include avhttp in two .cpp files, the link fails because it detects duplicate -// avhttp functions. -// So until it is fixed, this code is here. -bool GITHUB_GETLIBLIST::remote_get_json( std::string* aFullURLCommand, wxString* aMsgError ) -{ - boost::asio::io_service io; - avhttp::http_stream h( io ); - avhttp::request_opts options; - - - options.insert( "Accept", m_option_string ); - options.insert( "User-Agent", "http://kicad-pcb.org" ); // THAT WOULD BE ME. - h.request_options( options ); - - try - { - std::ostringstream os; - - h.open( *aFullURLCommand ); // only one file, therefore do it synchronously. - os << &h; - - // Keep downloaded text file image in RAM. - m_image = os.str(); - - // 4 lines, using SSL, top that. - } - catch( boost::system::system_error& e ) - { - // https "GET" has faild, report this to API caller. - static const char errorcmd[] = "https GET command failed"; // Do not translate this message - - UTF8 fmt( _( "%s\nCannot get/download data from: '%s'\nReason: '%s'" ) ); - - std::string msg = StrPrintf( fmt.c_str(), - errorcmd, - // Report secret list_url to user. The secret - // list_url may go bad at some point in future if github changes - // their server architecture. Then fix repoURL_zipURL() to reflect - // new architecture. - aFullURLCommand->c_str(), e.what() ); - - if( aMsgError ) - { - *aMsgError = FROM_UTF8( msg.c_str() ); - return false; - } - } - - return true; } #if 0 && defined(STANDALONE) diff --git a/pcbnew/github/github_plugin.h b/pcbnew/github/github_plugin.h index 5a041d0581..8588fc955f 100644 --- a/pcbnew/github/github_plugin.h +++ b/pcbnew/github/github_plugin.h @@ -210,14 +210,14 @@ protected: * @param aZipURL is where to put the zip file URL. * @return bool - true if @a aRepoULR was parseable, else false */ - static bool repoURL_zipURL( const wxString& aRepoURL, std::string* aZipURL ); + static bool repoURL_zipURL( const wxString& aRepoURL, std::string& aZipURL ); /** - * Function remote_get_zip + * Function remoteGetZip * fetches a zip file image from a github repo synchronously. The byte image * is received into the m_input_stream. */ - void remote_get_zip( const wxString& aRepoURL ) throw( IO_ERROR ); + void remoteGetZip( const wxString& aRepoURL ) throw( IO_ERROR ); wxString m_lib_path; ///< from aLibraryPath, something like https://github.com/liftoff-sr/pretty_footprints std::string m_zip_image; ///< byte image of the zip file in its entirety. diff --git a/pcbnew/modedit.cpp b/pcbnew/modedit.cpp index 9e8ca54ebc..c51e171f4c 100644 --- a/pcbnew/modedit.cpp +++ b/pcbnew/modedit.cpp @@ -192,8 +192,10 @@ void FOOTPRINT_EDIT_FRAME::LoadModuleFromBoard( wxCommandEvent& event ) GetScreen()->ClearUndoRedoList(); GetScreen()->ClrModify(); - if( m_Draw3DFrame ) - m_Draw3DFrame->NewDisplay(); + EDA_3D_FRAME* draw3DFrame = Get3DViewerFrame(); + + if( draw3DFrame ) + draw3DFrame->NewDisplay(); } @@ -370,8 +372,10 @@ void FOOTPRINT_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) updateView(); m_canvas->Refresh(); - if( m_Draw3DFrame ) - m_Draw3DFrame->NewDisplay(); + EDA_3D_FRAME* draw3DFrame = Get3DViewerFrame(); + + if( draw3DFrame ) + draw3DFrame->NewDisplay(); GetScreen()->ClrModify(); } @@ -513,9 +517,12 @@ void FOOTPRINT_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) GetScreen()->ClrModify(); Zoom_Automatique( false ); m_canvas->Refresh(); + { + EDA_3D_FRAME* draw3DFrame = Get3DViewerFrame(); - if( m_Draw3DFrame ) - m_Draw3DFrame->NewDisplay(); + if( draw3DFrame ) + draw3DFrame->NewDisplay(); + } break; @@ -572,8 +579,12 @@ void FOOTPRINT_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) Zoom_Automatique( false ); - if( m_Draw3DFrame ) - m_Draw3DFrame->NewDisplay(); + { + EDA_3D_FRAME* draw3DFrame = Get3DViewerFrame(); + + if( draw3DFrame ) + draw3DFrame->NewDisplay(); + } GetScreen()->ClrModify(); diff --git a/pcbnew/moduleframe.cpp b/pcbnew/moduleframe.cpp index 80302a7eb4..9a9f259514 100644 --- a/pcbnew/moduleframe.cpp +++ b/pcbnew/moduleframe.cpp @@ -672,25 +672,27 @@ void FOOTPRINT_EDIT_FRAME::OnUpdateSelectCurrentLib( wxUpdateUIEvent& aEvent ) void FOOTPRINT_EDIT_FRAME::Show3D_Frame( wxCommandEvent& event ) { - if( m_Draw3DFrame ) + EDA_3D_FRAME* draw3DFrame = Get3DViewerFrame(); + + if( draw3DFrame ) { // Raising the window does not show the window on Windows if iconized. // This should work on any platform. - if( m_Draw3DFrame->IsIconized() ) - m_Draw3DFrame->Iconize( false ); + if( draw3DFrame->IsIconized() ) + draw3DFrame->Iconize( false ); - m_Draw3DFrame->Raise(); + draw3DFrame->Raise(); // Raising the window does not set the focus on Linux. This should work on any platform. - if( wxWindow::FindFocus() != m_Draw3DFrame ) - m_Draw3DFrame->SetFocus(); + if( wxWindow::FindFocus() != draw3DFrame ) + draw3DFrame->SetFocus(); return; } - m_Draw3DFrame = new EDA_3D_FRAME( &Kiway(), this, _( "3D Viewer" ) ); - m_Draw3DFrame->Raise(); // Needed with some Window Managers - m_Draw3DFrame->Show( true ); + draw3DFrame = new EDA_3D_FRAME( &Kiway(), this, _( "3D Viewer" ) ); + draw3DFrame->Raise(); // Needed with some Window Managers + draw3DFrame->Show( true ); } @@ -735,9 +737,10 @@ void FOOTPRINT_EDIT_FRAME::OnModify() { PCB_BASE_FRAME::OnModify(); - if( m_Draw3DFrame ) - m_Draw3DFrame->ReloadRequest(); -} + EDA_3D_FRAME* draw3DFrame = Get3DViewerFrame(); + + if( draw3DFrame ) + draw3DFrame->ReloadRequest();} void FOOTPRINT_EDIT_FRAME::updateTitle() diff --git a/pcbnew/modules.cpp b/pcbnew/modules.cpp index cb83e39b38..a31a2e60a5 100644 --- a/pcbnew/modules.cpp +++ b/pcbnew/modules.cpp @@ -1,10 +1,10 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2015 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck * Copyright (C) 2012 Wayne Stambaugh - * Copyright (C) 1992-2012 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 1992-2015 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 @@ -41,7 +41,7 @@ #include #include - +#include static void MoveFootprint( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aPosition, bool aErase ); @@ -56,17 +56,23 @@ static PICKED_ITEMS_LIST s_PickedList; /* a picked list to * and dragged tracks */ -/* Get a module name from user and return a pointer to the corresponding module - */ -MODULE* PCB_BASE_FRAME::GetModuleByName() + +MODULE* PCB_BASE_FRAME::GetFootprintFromBoardByReference() { - wxString moduleName; - MODULE* module = NULL; + wxString moduleName; + MODULE* module = NULL; + wxArrayString fplist; - wxTextEntryDialog dlg( this, _( "Reference:" ), _( "Search for footprint" ), moduleName ); + // Build list of available fp references, to display them in dialog + for( MODULE* fp = GetBoard()->m_Modules; fp; fp = fp->Next() ) + fplist.Add( fp->GetReference() + wxT(" ( ") + fp->GetValue() + wxT(" )") ); - if( dlg.ShowModal() != wxID_OK ) - return NULL; //Aborted by user + fplist.Sort(); + + DIALOG_GET_FOOTPRINT_BY_NAME dlg( this, fplist ); + + if( dlg.ShowModal() != wxID_OK ) //Aborted by user + return NULL; moduleName = dlg.GetValue(); moduleName.Trim( true ); diff --git a/pcbnew/modview_frame.cpp b/pcbnew/modview_frame.cpp index ee88cc6c43..c03d541cc4 100644 --- a/pcbnew/modview_frame.cpp +++ b/pcbnew/modview_frame.cpp @@ -283,8 +283,10 @@ FOOTPRINT_VIEWER_FRAME::FOOTPRINT_VIEWER_FRAME( KIWAY* aKiway, wxWindow* aParent FOOTPRINT_VIEWER_FRAME::~FOOTPRINT_VIEWER_FRAME() { - if( m_Draw3DFrame ) - m_Draw3DFrame->Destroy(); + EDA_3D_FRAME* draw3DFrame = Get3DViewerFrame(); + + if( draw3DFrame ) + draw3DFrame->Destroy(); } @@ -613,47 +615,51 @@ bool FOOTPRINT_VIEWER_FRAME::GeneralControl( wxDC* aDC, const wxPoint& aPosition void FOOTPRINT_VIEWER_FRAME::Show3D_Frame( wxCommandEvent& event ) { - if( m_Draw3DFrame ) + EDA_3D_FRAME* draw3DFrame = Get3DViewerFrame(); + + if( draw3DFrame ) { // Raising the window does not show the window on Windows if iconized. // This should work on any platform. - if( m_Draw3DFrame->IsIconized() ) - m_Draw3DFrame->Iconize( false ); + if( draw3DFrame->IsIconized() ) + draw3DFrame->Iconize( false ); - m_Draw3DFrame->Raise(); + draw3DFrame->Raise(); // Raising the window does not set the focus on Linux. This should work on any platform. - if( wxWindow::FindFocus() != m_Draw3DFrame ) - m_Draw3DFrame->SetFocus(); + if( wxWindow::FindFocus() != draw3DFrame ) + draw3DFrame->SetFocus(); return; } - m_Draw3DFrame = new EDA_3D_FRAME( &Kiway(), this, wxEmptyString ); + draw3DFrame = new EDA_3D_FRAME( &Kiway(), this, wxEmptyString ); Update3D_Frame( false ); - m_Draw3DFrame->Raise(); // Needed with some Window Managers - m_Draw3DFrame->Show( true ); + draw3DFrame->Raise(); // Needed with some Window Managers + draw3DFrame->Show( true ); } void FOOTPRINT_VIEWER_FRAME::Update3D_Frame( bool aForceReloadFootprint ) { - if( m_Draw3DFrame == NULL ) + EDA_3D_FRAME* draw3DFrame = Get3DViewerFrame(); + + if( draw3DFrame == NULL ) return; wxString frm3Dtitle = wxString::Format( _( "ModView: 3D Viewer [%s]" ), GetChars( getCurFootprintName() ) ); - m_Draw3DFrame->SetTitle( frm3Dtitle ); + draw3DFrame->SetTitle( frm3Dtitle ); if( aForceReloadFootprint ) { - m_Draw3DFrame->ReloadRequest(); + draw3DFrame->ReloadRequest(); // Force 3D screen refresh immediately if( GetBoard()->m_Modules ) - m_Draw3DFrame->NewDisplay(); + draw3DFrame->NewDisplay(); } } diff --git a/pcbnew/pcbframe.cpp b/pcbnew/pcbframe.cpp index b19fca1935..21bdc5489a 100644 --- a/pcbnew/pcbframe.cpp +++ b/pcbnew/pcbframe.cpp @@ -70,8 +70,6 @@ #include #include -#include - #if defined(KICAD_SCRIPTING) || defined(KICAD_SCRIPTING_WXPYTHON) #include #endif @@ -209,10 +207,12 @@ BEGIN_EVENT_TABLE( PCB_EDIT_FRAME, PCB_BASE_FRAME ) EVT_TOOL( ID_TOOLBARH_PCB_MODE_TRACKS, PCB_EDIT_FRAME::OnSelectAutoPlaceMode ) EVT_TOOL( ID_TOOLBARH_PCB_FREEROUTE_ACCESS, PCB_EDIT_FRAME::Access_to_External_Tool ) +#if defined( KICAD_SCRIPTING_WXPYTHON ) // has meaning only with KICAD_SCRIPTING_WXPYTHON enabled EVT_TOOL( ID_TOOLBARH_PCB_SCRIPTING_CONSOLE, PCB_EDIT_FRAME::ScriptingConsoleEnableDisable ) EVT_UPDATE_UI( ID_TOOLBARH_PCB_SCRIPTING_CONSOLE, PCB_EDIT_FRAME::OnUpdateScriptingConsoleState ) +#endif // Option toolbar EVT_TOOL( ID_TB_OPTIONS_DRC_OFF, @@ -637,26 +637,28 @@ void PCB_EDIT_FRAME::OnCloseWindow( wxCloseEvent& Event ) void PCB_EDIT_FRAME::Show3D_Frame( wxCommandEvent& event ) { - if( m_Draw3DFrame ) + EDA_3D_FRAME* draw3DFrame = Get3DViewerFrame(); + + if( draw3DFrame ) { // Raising the window does not show the window on Windows if iconized. // This should work on any platform. - if( m_Draw3DFrame->IsIconized() ) - m_Draw3DFrame->Iconize( false ); + if( draw3DFrame->IsIconized() ) + draw3DFrame->Iconize( false ); - m_Draw3DFrame->Raise(); + draw3DFrame->Raise(); // Raising the window does not set the focus on Linux. This should work on any platform. - if( wxWindow::FindFocus() != m_Draw3DFrame ) - m_Draw3DFrame->SetFocus(); + if( wxWindow::FindFocus() != draw3DFrame ) + draw3DFrame->SetFocus(); return; } - m_Draw3DFrame = new EDA_3D_FRAME( &Kiway(), this, _( "3D Viewer" ) ); - m_Draw3DFrame->SetDefaultFileName( GetBoard()->GetFileName() ); - m_Draw3DFrame->Raise(); // Needed with some Window Managers - m_Draw3DFrame->Show( true ); + draw3DFrame = new EDA_3D_FRAME( &Kiway(), this, _( "3D Viewer" ) ); + draw3DFrame->SetDefaultFileName( GetBoard()->GetFileName() ); + draw3DFrame->Raise(); // Needed with some Window Managers + draw3DFrame->Show( true ); } @@ -937,8 +939,10 @@ void PCB_EDIT_FRAME::OnModify( ) { PCB_BASE_FRAME::OnModify(); - if( m_Draw3DFrame ) - m_Draw3DFrame->ReloadRequest(); + EDA_3D_FRAME* draw3DFrame = Get3DViewerFrame(); + + if( draw3DFrame ) + draw3DFrame->ReloadRequest(); } @@ -980,8 +984,7 @@ void PCB_EDIT_FRAME::UpdateTitle() } -wxSize PYTHON_CONSOLE_FRAME::m_frameSize; ///< The size of the PYTHON_CONSOLE_FRAME frame, stored during a session -wxPoint PYTHON_CONSOLE_FRAME::m_framePos; ///< The position ofPYTHON_CONSOLE_FRAME the frame, stored during a session +#if defined( KICAD_SCRIPTING_WXPYTHON ) void PCB_EDIT_FRAME::ScriptingConsoleEnableDisable( wxCommandEvent& aEvent ) { @@ -990,13 +993,18 @@ void PCB_EDIT_FRAME::ScriptingConsoleEnableDisable( wxCommandEvent& aEvent ) bool pythonPanelShown = true; if( pythonPanelFrame == NULL ) - pythonPanelFrame = new PYTHON_CONSOLE_FRAME( this, pythonConsoleNameId() ); + pythonPanelFrame = CreatePythonShellWindow( this, pythonConsoleNameId() ); else pythonPanelShown = ! pythonPanelFrame->IsShown(); - pythonPanelFrame->Show( pythonPanelShown ); + if( pythonPanelFrame ) + pythonPanelFrame->Show( pythonPanelShown ); + else + wxMessageBox( wxT( "Error: unable to create the Python Console" ) ); } +#endif + void PCB_EDIT_FRAME::OnSelectAutoPlaceMode( wxCommandEvent& aEvent ) { diff --git a/pcbnew/pcbnew.cpp b/pcbnew/pcbnew.cpp index 11a271ea13..1ee40e0ab8 100644 --- a/pcbnew/pcbnew.cpp +++ b/pcbnew/pcbnew.cpp @@ -242,36 +242,26 @@ static bool scriptingSetup() } } - // TODO: make this path definable by the user, and set more than one path - // (and remove the fixed paths from /scripting/kicadplugins.i) - - // wizard plugins are stored in kicad/bin/plugins. - // so add this path to python scripting default search paths + // wizard plugins are stored in ../share/kicad/scripting/plugins. + // so add the base scripting path to python scripting default search paths // which are ( [KICAD_PATH] is an environment variable to define) + // [KICAD_PATH]/scripting // [KICAD_PATH]/scripting/plugins // Add this default search path: - path_frag = Pgm().GetExecutablePath() + wxT( "../share/kicad/scripting/plugins" ); + path_frag = Pgm().GetExecutablePath() + wxT( "../share/kicad/scripting" ); #elif defined( __WXMAC__ ) - // TODO: - // For scripting currently only the bundle scripting path and the path - // defined by $(KICAD_PATH)/scripting/plugins is defined. - // These paths are defined here and in kicadplugins.i - // In future, probably more paths are of interest: - // * User folder (~/Library/Application Support/kicad/scripting/plugins) - // => GetOSXKicadUserDataDir() + wxT( "/scripting/plugins" ); - // * Machine folder (/Library/Application Support/kicad/scripting/plugins) - // => GetOSXKicadMachineDataDir() + wxT( "/scripting/plugins" ); // This path is given to LoadPlugins() from kicadplugins.i, which - // only supports one path. Only use bundle scripting path for now. - path_frag = GetOSXKicadDataDir() + wxT( "/scripting/plugins" ); + // only supports one path, the bundle scripting path for now. + // All other paths are determined by the pcbnew.py initialisation code + path_frag = GetOSXKicadDataDir() + wxT( "/scripting" ); // Add default paths to PYTHONPATH wxString pypath; - // Bundle scripting folder (/Contents/SharedSupport/scripting/plugins) - pypath += GetOSXKicadDataDir() + wxT( "/scripting/plugins" ); + // Bundle scripting folder (/Contents/SharedSupport/scripting) + pypath += GetOSXKicadDataDir() + wxT( "/scripting" ); // $(KICAD_PATH)/scripting/plugins is always added in kicadplugins.i if( wxGetenv("KICAD_PATH") != NULL ) @@ -304,9 +294,11 @@ static bool scriptingSetup() wxSetEnv( wxT( "PYTHONPATH" ), pypath ); // Add this default search path: - path_frag = Pgm().GetExecutablePath() + wxT( "../share/kicad/scripting/plugins" ); + path_frag = Pgm().GetExecutablePath() + wxT( "../share/kicad/scripting" ); #endif + // path_frag is the path to the bundled scripts and plugins, all other paths are + // determined by the python pcbnew.py initialisation code. if( !pcbnewInitPythonScripting( TO_UTF8( path_frag ) ) ) { wxLogError( wxT( "pcbnewInitPythonScripting() failed." ) ); @@ -378,7 +370,7 @@ void IFACE::OnKifaceEnd() { end_common(); -#if KICAD_SCRIPTING_WXPYTHON +#if defined( KICAD_SCRIPTING_WXPYTHON ) // Restore the thread state and tell Python to cleanup after itself. // wxPython will do its own cleanup as part of that process. // This should only be called if python was setup correctly. diff --git a/pcbnew/scripting/kicad_pyshell/__init__.py b/pcbnew/scripting/kicad_pyshell/__init__.py new file mode 100644 index 0000000000..7da0005784 --- /dev/null +++ b/pcbnew/scripting/kicad_pyshell/__init__.py @@ -0,0 +1,223 @@ +# -*- coding: utf-8 -*- +"""KiCad Python Shell. + +This module provides the python shell for KiCad. + +Currently the shell is only available inside PCBNEW. + +PCBNEW starts the shell once, by calling makePcbnewShellWindow() the +first time it is opened, subsequently the shell window is just hidden +or shown, as per user requirements. + +IF makePcbnewShellWindow() is called again, a second/third shell window +can be created. PCBNEW does not do this, but a user may call this from +the first shell if they require. + +""" +import wx +import sys +import os + +from wx.py import crust, editor, version, dispatcher +from wx.py.editor import EditorNotebook + +import pcbnew + +INTRO = "KiCAD:PCBNEW - Python Shell - PyAlaMode %s" % version.VERSION + + +class PcbnewPyShell(editor.EditorNotebookFrame): + + """The Pythonshell of PCBNEW.""" + + def _setup_startup(self): + """Initialise the startup script.""" + # Create filename for startup script. + self.startup_file = os.path.join(self.config_dir, + "PyShell_pcbnew_startup.py") + self.execStartupScript = True + + # Check if startup script exists + if not os.path.isfile(self.startup_file): + # Not, so create a default. + default_startup = open(self.startup_file, 'w') + # provide the content for the default startup file. + default_startup.write( + "### DEFAULT STARTUP FILE FOR KiCad:PCBNEW Python Shell\n" + + "# Enter any Python code you would like to execute when" + + " the PCBNEW python shell first runs.\n" + + "\n" + + "# Eg:\n" + + "\n" + + "# import pcbnew\n" + + "# board = pcbnew.GetBoard()\n") + default_startup.close() + + def _setup(self): + """ + Setup prior to first buffer creation. + + Called automatically by base class during init. + """ + self.notebook = EditorNotebook(parent=self) + intro = 'Py %s' % version.VERSION + import imp + module = imp.new_module('__main__') + import __builtin__ + module.__dict__['__builtins__'] = __builtin__ + namespace = module.__dict__.copy() + + self.config_dir = pcbnew.GetKicadConfigPath() + self.dataDir = self.config_dir + + self._setup_startup() + self.history_file = os.path.join(self.config_dir, + "PyShell_pcbnew.history") + + self.config_file = os.path.join(self.config_dir, + "PyShell_pcbnew.cfg") + self.config = wx.FileConfig(localFilename=self.config_file) + self.config.SetRecordDefaults(True) + self.autoSaveSettings = False + self.autoSaveHistory = False + self.LoadSettings() + + self.crust = crust.Crust(parent=self.notebook, + intro=intro, locals=namespace, + rootLabel="locals()", + startupScript=self.startup_file, + execStartupScript=self.execStartupScript) + + self.shell = self.crust.shell + # Override the filling so that status messages go to the status bar. + self.crust.filling.tree.setStatusText = self.SetStatusText + # Override the shell so that status messages go to the status bar. + self.shell.setStatusText = self.SetStatusText + # Fix a problem with the sash shrinking to nothing. + self.crust.filling.SetSashPosition(200) + self.notebook.AddPage(page=self.crust, text='*Shell*', select=True) + self.setEditor(self.crust.editor) + self.crust.editor.SetFocus() + + self.LoadHistory() + + def OnAbout(self, event): + """Display an About window.""" + title = 'About : KiCad:PCBNEW - Python Shell' + text = "Enahnced Python Shell for KiCad:PCBNEW\n\n" + \ + "This KiCad Python Shell is based on wxPython PyAlaMode.\n\n" + \ + "see: http://wiki.wxpython.org/PyAlaMode\n\n" + \ + "KiCad Revision: %s\n" % "??.??" + \ + "PyAlaMode Revision : %s\n" % version.VERSION + \ + "Platform: %s\n" % sys.platform + \ + "Python Version: %s\n" % sys.version.split()[0] + \ + "wxPython Version: %s\n" % wx.VERSION_STRING + \ + ("\t(%s)\n" % ", ".join(wx.PlatformInfo[1:])) + + dialog = wx.MessageDialog(self, text, title, + wx.OK | wx.ICON_INFORMATION) + dialog.ShowModal() + dialog.Destroy() + + def EditStartupScript(self): + """Open a Edit buffer of the startup script file.""" + self.bufferCreate(filename=self.startup_file) + + def LoadSettings(self): + """Load settings for the shell.""" + if self.config is not None: + editor.EditorNotebookFrame.LoadSettings(self, self.config) + self.autoSaveSettings = \ + self.config.ReadBool('Options/AutoSaveSettings', False) + self.execStartupScript = \ + self.config.ReadBool('Options/ExecStartupScript', True) + self.autoSaveHistory = \ + self.config.ReadBool('Options/AutoSaveHistory', False) + self.hideFoldingMargin = \ + self.config.ReadBool('Options/HideFoldingMargin', True) + + def SaveSettings(self, force=False): + """ + Save settings for the shell. + + Arguments: + + force -- False - Autosaving. True - Manual Saving. + """ + if self.config is not None: + # always save these + self.config.WriteBool('Options/AutoSaveSettings', + self.autoSaveSettings) + if self.autoSaveSettings or force: + editor.EditorNotebookFrame.SaveSettings(self, self.config) + + self.config.WriteBool('Options/AutoSaveHistory', + self.autoSaveHistory) + self.config.WriteBool('Options/ExecStartupScript', + self.execStartupScript) + self.config.WriteBool('Options/HideFoldingMargin', + self.hideFoldingMargin) + if self.autoSaveHistory: + self.SaveHistory() + + def DoSaveSettings(self): + """Menu function to trigger saving the shells settings.""" + if self.config is not None: + self.SaveSettings(force=True) + self.config.Flush() + + def SaveHistory(self): + """Save shell history to the shell history file.""" + if self.dataDir: + try: + name = self.history_file + f = file(name, 'w') + hist = [] + enc = wx.GetDefaultPyEncoding() + for h in self.shell.history: + if isinstance(h, unicode): + h = h.encode(enc) + hist.append(h) + hist = '\x00\n'.join(hist) + f.write(hist) + f.close() + except: + d = wx.MessageDialog(self, "Error saving history file.", + "Error", wx.ICON_EXCLAMATION | wx.OK) + d.ShowModal() + d.Destroy() + raise + + def LoadHistory(self): + """Load shell history from the shell history file.""" + if self.dataDir: + name = self.history_file + if os.path.exists(name): + try: + f = file(name, 'U') + hist = f.read() + f.close() + self.shell.history = hist.split('\x00\n') + dispatcher.send(signal="Shell.loadHistory", + history=self.shell.history) + except: + d = wx.MessageDialog(self, + "Error loading history file!", + "Error", wx.ICON_EXCLAMATION | wx.OK) + d.ShowModal() + d.Destroy() + + +def makePcbnewShellWindow(parent=None): + """ + Create a new Shell Window and return its handle. + + Arguments: + parent -- The parent window to attach to. + + Returns: + The handle to the new window. + """ + pyshell = PcbnewPyShell(parent, id=-1, title=INTRO) + pyshell.Show() + return pyshell diff --git a/pcbnew/toolbars_update_user_interface.cpp b/pcbnew/toolbars_update_user_interface.cpp index 8bd2aaf845..693eb93223 100644 --- a/pcbnew/toolbars_update_user_interface.cpp +++ b/pcbnew/toolbars_update_user_interface.cpp @@ -104,6 +104,9 @@ void PCB_EDIT_FRAME::OnUpdateLayerSelectBox( wxUpdateUIEvent& aEvent ) m_SelLayerBox->SetLayerSelection( GetActiveLayer() ); } + +#if defined( KICAD_SCRIPTING_WXPYTHON ) + // Used only when the DKICAD_SCRIPTING_WXPYTHON option is on void PCB_EDIT_FRAME::OnUpdateScriptingConsoleState( wxUpdateUIEvent& aEvent ) { @@ -112,6 +115,8 @@ void PCB_EDIT_FRAME::OnUpdateScriptingConsoleState( wxUpdateUIEvent& aEvent ) aEvent.Check( pythonPanelShown ); } +#endif + void PCB_EDIT_FRAME::OnUpdateZoneDisplayStyle( wxUpdateUIEvent& aEvent ) { diff --git a/pcbnew/tools/selection_tool.cpp b/pcbnew/tools/selection_tool.cpp index dc52429a4c..b31d933ac7 100644 --- a/pcbnew/tools/selection_tool.cpp +++ b/pcbnew/tools/selection_tool.cpp @@ -727,7 +727,7 @@ int SELECTION_TOOL::find( const TOOL_EVENT& aEvent ) int SELECTION_TOOL::findMove( const TOOL_EVENT& aEvent ) { - MODULE* module = m_frame->GetModuleByName(); + MODULE* module = m_frame->GetFootprintFromBoardByReference(); if( module ) { diff --git a/plugins/3d/vrml/v2/vrml2_base.cpp b/plugins/3d/vrml/v2/vrml2_base.cpp index 87721eb84e..bbba4f26c6 100644 --- a/plugins/3d/vrml/v2/vrml2_base.cpp +++ b/plugins/3d/vrml/v2/vrml2_base.cpp @@ -63,9 +63,9 @@ bool WRL2BASE::SetParent( WRL2NODE* aParent ) } -WRL2NODE* WRL2BASE::FindNode( const char *aNodeName, const WRL2NODE *aCaller ) +WRL2NODE* WRL2BASE::FindNode( const std::string& aNodeName, const WRL2NODE *aCaller ) { - if( NULL == aNodeName || 0 == aNodeName[0] ) + if( aNodeName.empty() ) return NULL; if( !m_Name.compare( aNodeName ) ) @@ -178,158 +178,13 @@ bool WRL2BASE::Read( WRLPROC& proc ) return false; } - std::string glob; - bool hasComma = false; - WRL2NODES ntype; + WRL2NODE* node = NULL; - while( proc.ReadName( glob ) ) - { - // Process node name: - // the names encountered at this point should be one of the - // built-in node names or one of: - // DEF, USE - // PROTO, EXTERNPROTO - // ROUTE - // any PROTO or EXTERNPROTO defined name - // since we do not support PROTO or EXTERNPROTO, any unmatched names are - // assumed to be defined via PROTO/EXTERNPROTO and deleted according to - // a typical pattern. - if( !glob.compare( "USE" ) ) - { - // XXX - implement - } + while( !readNode( proc, this, node ) ); - if( !glob.compare( "DEF" ) ) - { - // XXX - implement - } + if( proc.eof() ) + return true; - if( !glob.compare( "PROTO" ) ) - { - if( !proc.ReadName( glob ) || !proc.ReadName( glob ) || !proc.DiscardList() ) - { - #ifdef DEBUG - std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; - std::cerr << proc.GetError() << "\n"; - #endif - } - } - - if( !glob.compare( "EXTERNPROTO" ) ) - { - // XXX - implement - } - - if( !glob.compare( "ROUTE" ) ) - { - // XXX - implement - } - - ntype = getNodeTypeID( glob ); - - switch( ntype ) - { - // - // items to be implemented: - // - case WRL2_APPEARANCE: - // note: - break; - - case WRL2_BOX: - break; - - case WRL2_COLOR: - break; - - case WRL2_CONE: - break; - - case WRL2_COORDINATE: - break; - - case WRL2_CYLINDER: - break; - - case WRL2_ELEVATIONGRID: - break; - - case WRL2_EXTRUSION: - break; - - case WRL2_INDEXEDFACESET: - break; - - case WRL2_MATERIAL: - break; - - case WRL2_NORMAL: - break; - - case WRL2_SHAPE: - break; - - case WRL2_SPHERE: - break; - - case WRL2_TRANSFORM: - case WRL2_GROUP: - break; - - // - // items not implemented or for optional future implementation: - // - case WRL2_ANCHOR: - case WRL2_AUDIOCLIP: - case WRL2_BACKGROUND: - case WRL2_BILLBOARD: - case WRL2_COLLISION: - case WRL2_COLORINTERPOLATOR: - case WRL2_COORDINATEINTERPOLATOR: - case WRL2_CYLINDERSENSOR: - case WRL2_DIRECTIONALLIGHT: - case WRL2_FOG: - case WRL2_FONTSTYLE: - case WRL2_IMAGETEXTURE: - case WRL2_INDEXEDLINESET: - case WRL2_INLINE: - case WRL2_LOD: - case WRL2_MOVIETEXTURE: - case WRL2_NAVIGATIONINFO: - case WRL2_NORMALINTERPOLATOR: - case WRL2_ORIENTATIONINTERPOLATOR: - case WRL2_PIXELTEXTURE: - case WRL2_PLANESENSOR: - case WRL2_POINTLIGHT: - case WRL2_POINTSET: - case WRL2_POSITIONINTERPOLATOR: - case WRL2_PROXIMITYSENSOR: - case WRL2_SCALARINTERPOLATOR: - case WRL2_SCRIPT: - case WRL2_SOUND: - case WRL2_SPHERESENSOR: - case WRL2_SPOTLIGHT: - case WRL2_SWITCH: - case WRL2_TEXT: - case WRL2_TEXTURECOORDINATE: - case WRL2_TEXTURETRANSFORM: - case WRL2_TIMESENSOR: - case WRL2_TOUCHSENSOR: - case WRL2_VIEWPOINT: - case WRL2_VISIBILITYSENSOR: - case WRL2_WORLDINFO: - case WRL2_INVALID: - default: // any nodes which may have been defined via PROTO/EXTERNPROTO - break; - } - - //xxx; - }; - - // XXX - determine why ReadName failed - - // XXX - - #warning TO BE IMPLEMENTED return false; } @@ -338,3 +193,280 @@ bool WRL2BASE::isDangling( void ) { return false; } + + +bool WRL2BASE::implementUse( WRLPROC& proc, WRL2NODE* aParent ) +{ + if( !aParent ) + { + #ifdef DEBUG + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [BUG] invoked with NULL parent\n"; + #endif + + return false; + } + + std::string glob; + + if( !proc.ReadName( glob ) ) + { + #ifdef DEBUG + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << proc.GetError() << "\n"; + #endif + + return false; + } + + WRL2NODE* ref = aParent->FindNode( glob, NULL ); + + // return 'true' - the file may be defective but it may still be somewhat OK + if( NULL == ref ) + { + #ifdef DEBUG + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [INFO] node '" << glob << "' not found\n"; + #endif + + return true; + } + + if( !aParent->AddRefNode( ref ) ) + { + #ifdef DEBUG + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [INFO] failed to add node '" << glob << "' ("; + std::cerr << ref->GetNodeTypeName( ref->GetNodeType() ) << ") to parent of type "; + std::cerr << aParent->GetNodeTypeName( aParent->GetNodeType() ) << "\n"; + #endif + + return false; + } + + return true; +} + + +bool WRL2BASE::implementDef( WRLPROC& proc, WRL2NODE* aParent ) +{ + // XXX - TO BE IMPLEMENTED + return false; +} + + +bool WRL2BASE::readNode( WRLPROC& proc, WRL2NODE* aParent, WRL2NODE** aNode ) +{ + if( NULL == aNode ) + { + #ifdef DEBUG + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [BUG] invalid node handle (NULL)\n"; + #endif + + return false; + } + + if( NULL == aParent ) + { + #ifdef DEBUG + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [BUG] invalid parent pointer (NULL)\n"; + #endif + + return false; + } + + *aNode = NULL; + + std::string glob; + bool hasComma = false; + WRL2NODES ntype; + + if( !proc.ReadName( glob ) ) + { + #ifdef DEBUG + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << proc.GetError() << "\n"; + #endif + + return false; + } + + // Process node name: + // the names encountered at this point should be one of the + // built-in node names or one of: + // DEF, USE + // PROTO, EXTERNPROTO + // ROUTE + // any PROTO or EXTERNPROTO defined name + // since we do not support PROTO or EXTERNPROTO, any unmatched names are + // assumed to be defined via PROTO/EXTERNPROTO and deleted according to + // a typical pattern. + if( !glob.compare( "USE" ) ) + { + if( !implementUse( aParent ) ) + { + #ifdef DEBUG + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << proc.GetError() << "\n"; + #endif + + return false; + } + + return true; + } + + if( !glob.compare( "DEF" ) ) + { + // XXX - implement + implementDef( aParent ); + } + + if( !glob.compare( "PROTO" ) ) + { + if( !proc.ReadName( glob ) || !proc.DiscardList() ) + { + #ifdef DEBUG + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << proc.GetError() << "\n"; + #endif + + return false; + } + + return true; + } + + if( !glob.compare( "EXTERNPROTO" ) ) + { + if( !proc.ReadName( glob ) || !proc.ReadName( glob ) || !proc.DiscardList() ) + { + #ifdef DEBUG + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << proc.GetError() << "\n"; + #endif + + return false; + } + + return true; + } + + if( !glob.compare( "ROUTE" ) ) + { + if( !proc.ReadGlob( glob ) || !proc.ReadGlob( glob ) || !proc.ReadGlob( glob ) ) + { + #ifdef DEBUG + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << proc.GetError() << "\n"; + #endif + + return false; + } + + return true; + } + + ntype = getNodeTypeID( glob ); + + switch( ntype ) + { + // + // items to be implemented: + // + case WRL2_APPEARANCE: + // note: + break; + + case WRL2_BOX: + break; + + case WRL2_COLOR: + break; + + case WRL2_CONE: + break; + + case WRL2_COORDINATE: + break; + + case WRL2_CYLINDER: + break; + + case WRL2_ELEVATIONGRID: + break; + + case WRL2_EXTRUSION: + break; + + case WRL2_INDEXEDFACESET: + break; + + case WRL2_MATERIAL: + break; + + case WRL2_NORMAL: + break; + + case WRL2_SHAPE: + break; + + case WRL2_SPHERE: + break; + + case WRL2_TRANSFORM: + case WRL2_GROUP: + break; + + // + // items not implemented or for optional future implementation: + // + case WRL2_ANCHOR: + case WRL2_AUDIOCLIP: + case WRL2_BACKGROUND: + case WRL2_BILLBOARD: + case WRL2_COLLISION: + case WRL2_COLORINTERPOLATOR: + case WRL2_COORDINATEINTERPOLATOR: + case WRL2_CYLINDERSENSOR: + case WRL2_DIRECTIONALLIGHT: + case WRL2_FOG: + case WRL2_FONTSTYLE: + case WRL2_IMAGETEXTURE: + case WRL2_INDEXEDLINESET: + case WRL2_INLINE: + case WRL2_LOD: + case WRL2_MOVIETEXTURE: + case WRL2_NAVIGATIONINFO: + case WRL2_NORMALINTERPOLATOR: + case WRL2_ORIENTATIONINTERPOLATOR: + case WRL2_PIXELTEXTURE: + case WRL2_PLANESENSOR: + case WRL2_POINTLIGHT: + case WRL2_POINTSET: + case WRL2_POSITIONINTERPOLATOR: + case WRL2_PROXIMITYSENSOR: + case WRL2_SCALARINTERPOLATOR: + case WRL2_SCRIPT: + case WRL2_SOUND: + case WRL2_SPHERESENSOR: + case WRL2_SPOTLIGHT: + case WRL2_SWITCH: + case WRL2_TEXT: + case WRL2_TEXTURECOORDINATE: + case WRL2_TEXTURETRANSFORM: + case WRL2_TIMESENSOR: + case WRL2_TOUCHSENSOR: + case WRL2_VIEWPOINT: + case WRL2_VISIBILITYSENSOR: + case WRL2_WORLDINFO: + case WRL2_INVALID: + default: // any nodes which may have been defined via PROTO/EXTERNPROTO + break; + } + + // XXX - TO BE IMPLEMENTED + return NULL; +} diff --git a/plugins/3d/vrml/v2/vrml2_base.h b/plugins/3d/vrml/v2/vrml2_base.h index daae1c2eed..cac2ed9251 100644 --- a/plugins/3d/vrml/v2/vrml2_base.h +++ b/plugins/3d/vrml/v2/vrml2_base.h @@ -70,6 +70,13 @@ public: void unlinkRefNode( const WRL2NODE* aNode ); bool isDangling( void ); + // handle cases of USE / DEF + bool implementUse( WRLPROC& proc, WRL2NODE* aParent ); + bool implementDef( WRLPROC& proc, WRL2NODE* aParent ); + + // read in a VRML node + bool readNode( WRLPROC& proc, WRL2NODE* aParent, WRL2NODE** aNode ); + public: WRL2BASE(); virtual ~WRL2BASE(); @@ -81,7 +88,7 @@ public: // functions inherited from WRL2NODE bool Read( WRLPROC& proc ); bool SetParent( WRL2NODE* aParent ); - WRL2NODE* FindNode( const char *aNodeName, const WRL2NODE *aCaller ); + WRL2NODE* FindNode( const std::string& aNodeName, const WRL2NODE *aCaller ); bool AddRefNode( WRL2NODE* aNode ); bool AddChildNode( WRL2NODE* aNode ); }; diff --git a/plugins/3d/vrml/v2/vrml2_node.cpp b/plugins/3d/vrml/v2/vrml2_node.cpp index 197706b2f6..e55f5f0aa4 100644 --- a/plugins/3d/vrml/v2/vrml2_node.cpp +++ b/plugins/3d/vrml/v2/vrml2_node.cpp @@ -268,7 +268,7 @@ WRL2NODES WRL2NODE::getNodeTypeID( const std::string aNodeName ) } -const char* WRL2NODE::GetError( void ) +std::string WRL2NODE::GetError( void ) { - return m_error.c_str(); + return m_error; } diff --git a/plugins/3d/vrml/v2/vrml2_node.h b/plugins/3d/vrml/v2/vrml2_node.h index fda75bbf19..024e504e3e 100644 --- a/plugins/3d/vrml/v2/vrml2_node.h +++ b/plugins/3d/vrml/v2/vrml2_node.h @@ -162,13 +162,13 @@ public: * @param aCaller is a pointer to the node invoking this function * @return is a valid node pointer on success, otherwise NULL */ - virtual WRL2NODE* FindNode( const char *aNodeName, const WRL2NODE *aCaller ) = 0; + virtual WRL2NODE* FindNode( const std::string& aNodeName, const WRL2NODE *aCaller ) = 0; virtual bool AddRefNode( WRL2NODE* aNode ) = 0; virtual bool AddChildNode( WRL2NODE* aNode ) = 0; - const char* GetError( void ); + std::string GetError( void ); }; #endif // VRML2_NODE_H diff --git a/plugins/3d/vrml/v2/wrlproc.cpp b/plugins/3d/vrml/v2/wrlproc.cpp index e7b54f4bbf..d6beb6b602 100644 --- a/plugins/3d/vrml/v2/wrlproc.cpp +++ b/plugins/3d/vrml/v2/wrlproc.cpp @@ -2144,3 +2144,18 @@ bool WRLPROC::ReadMFVec3f( std::vector< WRLVEC3F >& aMFVec3f ) ++m_linepos; return true; } + + +bool WRLPROC::eof( void ) +{ + if( !m_file.is_open() ) + return false; + + return m_file.eof(); +} + + +std::string WRLPROC::GetError( void ) +{ + return m_error; +} diff --git a/plugins/3d/vrml/v2/wrlproc.h b/plugins/3d/vrml/v2/wrlproc.h index 598f59ed19..1e1085f5b8 100644 --- a/plugins/3d/vrml/v2/wrlproc.h +++ b/plugins/3d/vrml/v2/wrlproc.h @@ -67,9 +67,13 @@ public: bool Open( const std::string& aFileName ); void Close(); + bool eof( void ); + // return the VRML Version WRLVERSION GetVRMLType( void ); + std::string GetError( void ); + // helper routines // read up to the next whitespace or comma diff --git a/scripting/kicadplugins.i b/scripting/kicadplugins.i index 9a310faa59..918896d15d 100644 --- a/scripting/kicadplugins.i +++ b/scripting/kicadplugins.i @@ -78,21 +78,59 @@ def ReloadPlugins(): ReloadPlugin(k) -def LoadPlugins(plugpath): +def LoadPlugins(bundlepath=None): + """ + Initialise Scripting/Plugin python environment and load plugins. + + Arguments: + scriptpath -- The path to the bundled scripts. + The bunbled Plugins are relative to this path, in the + "plugins" subdirectory. + + NOTE: These are all of the possible "default" search paths for kicad + python scripts. These paths will ONLY be added to the python + search path ONLY IF they already exist. + + The Scripts bundled with the KiCad installation: + / + /plugins/ + + The Scripts relative to the KiCad search path environment variable: + [KICAD_PATH]/scripting/ + [KICAD_PATH]/scripting/plugins/ + + The Scripts relative to the KiCad Users configuration: + /scripting/ + /scripting/plugins/ + + And on Linux ONLY, extra paths relative to the users home directory: + ~/.kicad_plugins/ + ~/.kicad/scripting/ + ~/.kicad/scripting/plugins/ + """ import os import sys + import pcbnew kicad_path = os.environ.get('KICAD_PATH') + config_path = pcbnew.GetKicadConfigPath() plugin_directories=[] - if plugpath: - plugin_directories.append(plugpath) + if bundlepath: + plugin_directories.append(bundlepath) + plugin_directories.append(os.path.join(bundlepath, 'plugins')) if kicad_path: + plugin_directories.append(os.path.join(kicad_path, 'scripting')) plugin_directories.append(os.path.join(kicad_path, 'scripting', 'plugins')) + if config_path: + plugin_directories.append(os.path.join(config_path, 'scripting')) + plugin_directories.append(os.path.join(config_path, 'scripting', 'plugins')) + if sys.platform.startswith('linux'): plugin_directories.append(os.environ['HOME']+'/.kicad_plugins/') + plugin_directories.append(os.environ['HOME']+'/.kicad/scripting/') plugin_directories.append(os.environ['HOME']+'/.kicad/scripting/plugins/') for plugins_dir in plugin_directories: diff --git a/scripting/python_scripting.cpp b/scripting/python_scripting.cpp index c74abf5ed5..f2b3d22de0 100644 --- a/scripting/python_scripting.cpp +++ b/scripting/python_scripting.cpp @@ -136,7 +136,7 @@ static void swigSwitchPythonBuiltin() PyThreadState* g_PythonMainTState; -bool pcbnewInitPythonScripting( const char * aUserPluginsPath ) +bool pcbnewInitPythonScripting( const char * aUserScriptingPath ) { swigAddBuiltin(); // add builtin functions swigAddModules(); // add our own modules @@ -191,7 +191,7 @@ bool pcbnewInitPythonScripting( const char * aUserPluginsPath ) snprintf( cmd, sizeof(cmd), "import sys, traceback\n" "sys.path.append(\".\")\n" "import pcbnew\n" - "pcbnew.LoadPlugins(\"%s\")", aUserPluginsPath ); + "pcbnew.LoadPlugins(\"%s\")", aUserScriptingPath ); PyRun_SimpleString( cmd ); } @@ -227,20 +227,15 @@ void RedirectStdio() } -wxWindow* CreatePythonShellWindow( wxWindow* parent ) +wxWindow* CreatePythonShellWindow( wxWindow* parent, const wxString& aFramenameId ) { - const char* pycrust_panel = - "import wx\n" - "from wx.py import shell, version\n" - "\n" - "intro = \"PyCrust %s - KiCAD Python Shell\" % version.VERSION\n" + const char* pcbnew_pyshell = + "import kicad_pyshell\n" "\n" "def makeWindow(parent):\n" - " pycrust = shell.Shell(parent, -1, introText=intro)\n" - " return pycrust\n" + " return kicad_pyshell.makePcbnewShellWindow(parent)\n" "\n"; - wxWindow* window = NULL; PyObject* result; @@ -257,7 +252,7 @@ wxWindow* CreatePythonShellWindow( wxWindow* parent ) Py_DECREF( builtins ); // Execute the code to make the makeWindow function we defined above - result = PyRun_String( pycrust_panel, Py_file_input, globals, globals ); + result = PyRun_String( pcbnew_pyshell, Py_file_input, globals, globals ); // Was there an exception? if( !result ) @@ -297,6 +292,8 @@ wxWindow* CreatePythonShellWindow( wxWindow* parent ) wxASSERT_MSG( success, _T( "Returned object was not a wxWindow!" ) ); Py_DECREF( result ); + + window->SetName( aFramenameId ); } // Release the python objects we still have diff --git a/scripting/python_scripting.h b/scripting/python_scripting.h index 8d0ae174fe..ca25de435d 100644 --- a/scripting/python_scripting.h +++ b/scripting/python_scripting.h @@ -24,14 +24,14 @@ * Initializes the Python engine inside pcbnew */ -bool pcbnewInitPythonScripting( const char * aUserPluginsPath ); +bool pcbnewInitPythonScripting( const char * aUserScriptingPath ); void pcbnewFinishPythonScripting(); #ifdef KICAD_SCRIPTING_WXPYTHON void RedirectStdio(); -wxWindow* CreatePythonShellWindow( wxWindow* parent ); +wxWindow* CreatePythonShellWindow( wxWindow* parent, const wxString& aFramenameId ); class PyLOCK {