diff --git a/common/dsnlexer.cpp b/common/dsnlexer.cpp index 47a6d7c4bc..b21a79eb7d 100644 --- a/common/dsnlexer.cpp +++ b/common/dsnlexer.cpp @@ -148,6 +148,34 @@ void DSNLEXER::SetSpecctraMode( bool aMode ) } } + +bool DSNLEXER::SyncLineReaderWith( DSNLEXER& aLexer ) +{ + // Synchronize the pointers handling the data read by the LINE_READER + // only if aLexer shares the same LINE_READER, because only in this case + // the char buffer can be common + + if( reader != aLexer.reader ) + return false; + + // Be sure the char buffer is common + if( reader->Line() != aLexer.reader->Line() ) + return false; + + // We can synchronize the pointers which handle the data currently read + start = aLexer.start; + next = aLexer.next; + limit = aLexer.limit; + + // Sync these parameters is not mandatory, but could help + // for instance in debug + curText = aLexer.curText; + curOffset = aLexer.curOffset; + + return true; +} + + void DSNLEXER::PushReader( LINE_READER* aLineReader ) { readerStack.push_back( aLineReader ); diff --git a/common/footprint_info.cpp b/common/footprint_info.cpp index 99dde1c4bd..382e141bb3 100644 --- a/common/footprint_info.cpp +++ b/common/footprint_info.cpp @@ -275,6 +275,9 @@ bool FOOTPRINT_LIST::ReadFootprintFiles( FP_LIB_TABLE* aTable, const wxString* a FOOTPRINT_INFO* FOOTPRINT_LIST::GetModuleInfo( const wxString& aFootprintName ) { + if( aFootprintName.IsEmpty() ) + return NULL; + BOOST_FOREACH( FOOTPRINT_INFO& fp, m_list ) { FPID fpid; diff --git a/eeschema/dialogs/dialog_bom.cpp b/eeschema/dialogs/dialog_bom.cpp index 6a3bbe66dd..6f71d20960 100644 --- a/eeschema/dialogs/dialog_bom.cpp +++ b/eeschema/dialogs/dialog_bom.cpp @@ -69,7 +69,6 @@ public: private: void parsePlugin() throw( IO_ERROR, PARSE_ERROR ); - }; // PCB_PLOT_PARAMS_PARSER @@ -162,7 +161,7 @@ private: // the first is the title // the second is the command line wxArrayString m_plugins; - wxConfigBase* m_config; // to store the "plugins" + wxConfigBase* m_config; // to store the "plugins" public: // Constructor and destructor @@ -175,7 +174,6 @@ private: void OnCancelClick( wxCommandEvent& event ); void OnHelp( wxCommandEvent& event ); void OnAddPlugin( wxCommandEvent& event ); - void OnChoosePlugin( wxCommandEvent& event ); void OnRemovePlugin( wxCommandEvent& event ); void OnEditPlugin( wxCommandEvent& event ); void OnCommandLineEdited( wxCommandEvent& event ); @@ -183,6 +181,25 @@ private: void pluginInit(); void installPluginsList(); + + /** + * @return the Plugin filename from a command line + * @param aCommand = the command line + */ + wxString getPluginFileName( const wxString& aCommand ); + + /** + * display (when exists) the text found between the keyword "@package" + * (compatible with doxygen comments) + * and the end of comment block (""" in python", --> in xml) + */ + void displayPluginInfo( FILE * aFile, const wxString& aFilename ); + + /** + * Browse plugin files, and set m_CommandStringCtrl field + * @return a command line ro run the plugin + */ + wxString choosePlugin(); }; // Create and show DIALOG_BOM. @@ -215,12 +232,14 @@ DIALOG_BOM::~DIALOG_BOM() STRING_FORMATTER writer; writer.Print( 0, "(plugins" ); + for( unsigned ii = 0; ii < m_plugins.GetCount(); ii += 2 ) { writer.Print( 1, "(plugin %s (cmd %s))", writer.Quotew( m_plugins[ii] ).c_str(), writer.Quotew( m_plugins[ii+1] ).c_str() ); } + writer.Print( 0, ")" ); wxString list( FROM_UTF8( writer.GetString().c_str() ) ); @@ -272,6 +291,7 @@ void DIALOG_BOM::OnPluginSelected( wxCommandEvent& event ) pluginInit(); } +#include void DIALOG_BOM::pluginInit() { int ii = m_lbPlugins->GetSelection(); @@ -285,9 +305,71 @@ void DIALOG_BOM::pluginInit() m_textCtrlName->SetValue( m_plugins[2 * ii] ); m_textCtrlCommand->SetValue( m_plugins[(2 * ii)+1] ); + + wxString pluginName = getPluginFileName( m_textCtrlCommand->GetValue() ); + + if( pluginName.IsEmpty() ) + return; + + FILE* pluginFile = wxFopen( pluginName, "rt" ); + + if( pluginFile == NULL ) + { + wxString msg; + msg.Printf( _( "Failed to open file '%s'" ), GetChars( pluginName ) ); + DisplayError( this, msg ); + return; + } + + displayPluginInfo( pluginFile, pluginName ); } +void DIALOG_BOM::displayPluginInfo( FILE * aFile, const wxString& aFilename ) +{ + m_Messages->Clear(); + + // display (when exists) the text found between the keyword "@package" + // (compatible with doxygen comments) + // and the end of comment block (""" in python", --> in xml) + + wxString data; + wxFFile fdata( aFile ); // dtor will close the file + + if( !fdata.ReadAll( &data ) ) + return; + + wxString header( wxT( "@package" ) ); + wxString endsection( wxT( "-->" ) ); // For xml + + wxFileName fn( aFilename ); + + if( fn.GetExt().IsSameAs( wxT("py"), false ) ) + endsection = wxT( "\"\"\"" ); + else if( !fn.GetExt().IsSameAs( wxT("xsl"), false ) ) + // If this is not a python file, we know nothing about file + // and the info cannot be found + return; + + // Extract substring between @package and """ + int strstart = data.Find( header ); + + if( strstart == wxNOT_FOUND ) + return; + + strstart += header.Length(); + int strend = data.find( endsection, strstart ); + + if( strend == wxNOT_FOUND) + return; + + // Remove emty line if any + while( data[strstart] < ' ' ) + strstart++; + + m_Messages->SetValue( data.SubString( strstart, strend-1 ) ); +} + /** * Function RunPlugin * run the plugin command line @@ -350,8 +432,17 @@ void DIALOG_BOM::OnRemovePlugin( wxCommandEvent& event ) */ void DIALOG_BOM::OnAddPlugin( wxCommandEvent& event ) { + wxString cmdLine = choosePlugin(); + + if( cmdLine.IsEmpty() ) + return; + // Creates a new plugin entry - wxString name = wxGetTextFromUser( _("Plugin") ); + wxFileName fn( getPluginFileName( cmdLine ) ); + + wxString defaultName = fn.GetName(); + wxString name = wxGetTextFromUser( _("Plugin name in plugin list") , + _("Plugin name"), defaultName ); if( name.IsEmpty() ) return; @@ -361,22 +452,26 @@ void DIALOG_BOM::OnAddPlugin( wxCommandEvent& event ) { if( name == m_plugins[ii] ) { - wxMessageBox( _("This plugin already exists. Abort") ); + wxMessageBox( _("This name already exists. Abort") ); return; } } + // Eppend the new plugin m_plugins.Add( name ); m_plugins.Add( wxEmptyString ); + m_lbPlugins->SetSelection( m_lbPlugins->GetCount() - 1 ); m_lbPlugins->Append( name ); m_lbPlugins->SetSelection( m_lbPlugins->GetCount() - 1 ); + m_textCtrlCommand->SetValue( cmdLine ); + pluginInit(); } /* * Browse plugin files, and set m_CommandStringCtrl field */ -void DIALOG_BOM::OnChoosePlugin( wxCommandEvent& event ) +wxString DIALOG_BOM::choosePlugin() { wxString mask = wxT( "*" ); #ifndef __WXMAC__ @@ -395,7 +490,7 @@ void DIALOG_BOM::OnChoosePlugin( wxCommandEvent& event ) true ); if( fullFileName.IsEmpty() ) - return; + return wxEmptyString; // Creates a default command line, // suitable to run the external tool xslproc or python @@ -414,44 +509,65 @@ void DIALOG_BOM::OnChoosePlugin( wxCommandEvent& event ) else cmdLine.Printf(wxT("\"%s\""), GetChars( fullFileName ) ); - m_textCtrlCommand->SetValue( cmdLine ); + return cmdLine; } -void DIALOG_BOM::OnEditPlugin( wxCommandEvent& event ) + +wxString DIALOG_BOM::getPluginFileName( const wxString& aCommand ) { - wxString pluginName, cmdline; + wxString pluginName; // Try to find the plugin name. // This is possible if the name ends by .py or .xsl - cmdline = m_textCtrlCommand->GetValue(); int pos = -1; - if( (pos = cmdline.Find( wxT(".py") )) != wxNOT_FOUND ) + if( (pos = aCommand.Find( wxT(".py") )) != wxNOT_FOUND ) pos += 2; - else if( (pos = cmdline.Find( wxT(".xsl") )) != wxNOT_FOUND ) + else if( (pos = aCommand.Find( wxT(".xsl") )) != wxNOT_FOUND ) pos += 3; // the end of plugin name is at position pos. if( pos > 0 ) { // Be sure this is the end of the name: the next char is " or space - int eos = cmdline[pos+1]; + int eos = aCommand[pos+1]; if( eos == ' '|| eos == '\"' ) { // search for the starting point of the name int jj = pos-1; while( jj >= 0 ) - if( cmdline[jj] != eos ) + if( aCommand[jj] != eos ) jj--; else break; // extract the name if( jj >= 0 ) - pluginName = cmdline.SubString( jj, pos ); + { + eos = aCommand[jj]; + + if( eos == ' '|| eos == '\"' ) // do not include delimiters + jj++; + + pluginName = aCommand.SubString( jj, pos ); + } } } + + return pluginName; +} + +void DIALOG_BOM::OnEditPlugin( wxCommandEvent& event ) +{ + wxString pluginName = getPluginFileName( m_textCtrlCommand->GetValue() ); + + if( pluginName.Length() <= 2 ) // if name != "" + { + wxMessageBox( _("Plugin file name not found. Cannot edit plugin file") ); + return; + } + AddDelimiterString( pluginName ); wxString editorname = Pgm().GetEditorName(); diff --git a/eeschema/dialogs/dialog_bom_base.cpp b/eeschema/dialogs/dialog_bom_base.cpp index e8888467a5..6f96e35428 100644 --- a/eeschema/dialogs/dialog_bom_base.cpp +++ b/eeschema/dialogs/dialog_bom_base.cpp @@ -16,7 +16,6 @@ BEGIN_EVENT_TABLE( DIALOG_BOM_BASE, DIALOG_SHIM ) EVT_BUTTON( wxID_CANCEL, DIALOG_BOM_BASE::_wxFB_OnCancelClick ) EVT_BUTTON( ID_HELP, DIALOG_BOM_BASE::_wxFB_OnHelp ) EVT_BUTTON( ID_ADD_PLUGIN, DIALOG_BOM_BASE::_wxFB_OnAddPlugin ) - EVT_BUTTON( wxID_BROWSE_PLUGINS, DIALOG_BOM_BASE::_wxFB_OnChoosePlugin ) EVT_BUTTON( ID_REMOVEL_PLUGIN, DIALOG_BOM_BASE::_wxFB_OnRemovePlugin ) EVT_BUTTON( wxID_ANY, DIALOG_BOM_BASE::_wxFB_OnEditPlugin ) EVT_TEXT( ID_CMDLINE, DIALOG_BOM_BASE::_wxFB_OnCommandLineEdited ) @@ -72,9 +71,6 @@ DIALOG_BOM_BASE::DIALOG_BOM_BASE( wxWindow* parent, wxWindowID id, const wxStrin m_buttonAddPlugin = new wxButton( this, ID_ADD_PLUGIN, _("Add Plugin"), wxDefaultPosition, wxDefaultSize, 0 ); bRightSizer->Add( m_buttonAddPlugin, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 ); - m_buttonBrowsePlugin = new wxButton( this, wxID_BROWSE_PLUGINS, _("Set Plugin Cmd"), wxDefaultPosition, wxDefaultSize, 0 ); - bRightSizer->Add( m_buttonBrowsePlugin, 0, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 ); - m_buttonDelPlugin = new wxButton( this, ID_REMOVEL_PLUGIN, _("Remove Plugin"), wxDefaultPosition, wxDefaultSize, 0 ); bRightSizer->Add( m_buttonDelPlugin, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 ); @@ -103,6 +99,13 @@ DIALOG_BOM_BASE::DIALOG_BOM_BASE( wxWindow* parent, wxWindowID id, const wxStrin bMainSizer->Add( bbottomSizer, 0, wxEXPAND, 5 ); + m_staticTextInfo = new wxStaticText( this, wxID_ANY, _("Plugin Info:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextInfo->Wrap( -1 ); + bMainSizer->Add( m_staticTextInfo, 0, wxRIGHT|wxLEFT, 5 ); + + m_Messages = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_READONLY ); + bMainSizer->Add( m_Messages, 1, wxALL|wxEXPAND, 5 ); + this->SetSizer( bMainSizer ); this->Layout(); diff --git a/eeschema/dialogs/dialog_bom_base.fbp b/eeschema/dialogs/dialog_bom_base.fbp index 49b6273625..3393de4827 100644 --- a/eeschema/dialogs/dialog_bom_base.fbp +++ b/eeschema/dialogs/dialog_bom_base.fbp @@ -44,7 +44,7 @@ DIALOG_BOM_BASE - 404,315 + 409,393 wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER DIALOG_SHIM; dialog_shim.h Bill of Material @@ -900,94 +900,6 @@ - - 5 - wxEXPAND|wxTOP|wxRIGHT|wxLEFT - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_BROWSE_PLUGINS - Set Plugin Cmd - - 0 - - - 0 - - 1 - m_buttonBrowsePlugin - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - OnChoosePlugin - - - - - - - - - - - - - - - - - - - - - - - - - 5 wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxTOP|wxRIGHT|wxLEFT @@ -1353,6 +1265,180 @@ + + 5 + wxRIGHT|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Plugin Info: + + 0 + + + 0 + + 1 + m_staticTextInfo + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALL|wxEXPAND + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + + 0 + + 1 + m_Messages + 1 + + + protected + 1 + + Resizable + 1 + + wxTE_MULTILINE|wxTE_READONLY + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/eeschema/dialogs/dialog_bom_base.h b/eeschema/dialogs/dialog_bom_base.h index 2ba54c81f9..cf47f8fea4 100644 --- a/eeschema/dialogs/dialog_bom_base.h +++ b/eeschema/dialogs/dialog_bom_base.h @@ -44,7 +44,6 @@ class DIALOG_BOM_BASE : public DIALOG_SHIM void _wxFB_OnCancelClick( wxCommandEvent& event ){ OnCancelClick( event ); } void _wxFB_OnHelp( wxCommandEvent& event ){ OnHelp( event ); } void _wxFB_OnAddPlugin( wxCommandEvent& event ){ OnAddPlugin( event ); } - void _wxFB_OnChoosePlugin( wxCommandEvent& event ){ OnChoosePlugin( event ); } void _wxFB_OnRemovePlugin( wxCommandEvent& event ){ OnRemovePlugin( event ); } void _wxFB_OnEditPlugin( wxCommandEvent& event ){ OnEditPlugin( event ); } void _wxFB_OnCommandLineEdited( wxCommandEvent& event ){ OnCommandLineEdited( event ); } @@ -57,7 +56,6 @@ class DIALOG_BOM_BASE : public DIALOG_SHIM ID_CREATE_BOM, ID_HELP, ID_ADD_PLUGIN, - wxID_BROWSE_PLUGINS, ID_REMOVEL_PLUGIN, ID_CMDLINE }; @@ -71,11 +69,12 @@ class DIALOG_BOM_BASE : public DIALOG_SHIM wxButton* m_buttonHelp; wxStaticLine* m_staticline2; wxButton* m_buttonAddPlugin; - wxButton* m_buttonBrowsePlugin; wxButton* m_buttonDelPlugin; wxButton* m_buttonEdit; wxStaticText* m_staticTextCmd; wxTextCtrl* m_textCtrlCommand; + wxStaticText* m_staticTextInfo; + wxTextCtrl* m_Messages; // Virtual event handlers, overide them in your derived class virtual void OnPluginSelected( wxCommandEvent& event ) { event.Skip(); } @@ -84,7 +83,6 @@ class DIALOG_BOM_BASE : public DIALOG_SHIM virtual void OnCancelClick( wxCommandEvent& event ) { event.Skip(); } virtual void OnHelp( wxCommandEvent& event ) { event.Skip(); } virtual void OnAddPlugin( wxCommandEvent& event ) { event.Skip(); } - virtual void OnChoosePlugin( wxCommandEvent& event ) { event.Skip(); } virtual void OnRemovePlugin( wxCommandEvent& event ) { event.Skip(); } virtual void OnEditPlugin( wxCommandEvent& event ) { event.Skip(); } virtual void OnCommandLineEdited( wxCommandEvent& event ) { event.Skip(); } @@ -92,7 +90,7 @@ class DIALOG_BOM_BASE : public DIALOG_SHIM public: - DIALOG_BOM_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Bill of Material"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 404,315 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); + DIALOG_BOM_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Bill of Material"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 409,393 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); ~DIALOG_BOM_BASE(); }; diff --git a/eeschema/dialogs/dialog_bom_help.html b/eeschema/dialogs/dialog_bom_help.html index 4ba5c5bac1..7f8dbd2d34 100644 --- a/eeschema/dialogs/dialog_bom_help.html +++ b/eeschema/dialogs/dialog_bom_help.html @@ -1,210 +1,262 @@ - - - - kicad help - - - - - - -

-1 - Full -documentation:

-

-The -Eeschema -documentation, chapter 14 -describes this intermediate netlist and gives examples
See also -
https://answers.launchpad.net/kicad/+faq/2265

-

-2 - The -intermediate Netlist File

-

-BOM files (and -netlist files) can be created from an Intermediate netlist file -created by Eeschema.

-

-This file uses XML -syntax and is called the intermediate netlist. The intermediate -netlist includes a large amount of data about your board and because -of this, it can be used with post-processing to create a BOM or other -reports.

-

-Depending on the -output (BOM or netlist), different subsets of the complete -Intermediate Netlist file will be used in the post-processing.

-

-3 - Conversion to -a new format

-

-By applying a -post-processing filter to the Intermediate netlist file you can -generate foreign netlist files as well as BOM files. Because this -conversion is a text to text transformation.

-

-this post-processing -filter can be written using Python, XSLT, or any other tool capable -of taking XML as input.

-

-XSLT + p { margin-bottom: 0.21cm; widows: 0; orphans: 0; page-break-before: auto; page-break-after: auto } + p.western { font-family: "Arial", sans-serif; font-size: 10pt; so-language: en-US } + a:link { color: #004586; text-decoration: none } + a.western:link { font-family: "Liberation Sans", sans-serif; so-language: zxx; font-style: italic } + a.sdfootnotesym-western { font-family: "DejaVu Serif", serif } + + + +

+1 +- Full documentation:

+

+The +Eeschema +documentation, chapter 14 describes +this intermediate netlist and gives examples
See also +
https://answers.launchpad.net/kicad/+faq/2265

+

+2 +- The intermediate Netlist File

+

+BOM +files (and netlist files) can be created from an Intermediate netlist +file created by Eeschema.

+

+This +file uses XML syntax and is called the intermediate netlist. The +intermediate netlist includes a large amount of data about your board +and because of this, it can be used with post-processing to create a +BOM or other reports.

+

+Depending +on the output (BOM or netlist), different subsets of the complete +Intermediate Netlist file will be used in the post-processing.

+

+3 +- Conversion to a new format

+

+By +applying a post-processing filter to the Intermediate netlist file +you can generate foreign netlist files as well as BOM files. Because +this conversion is a text to text transformation.

+

+this +post-processing filter can be written using Python, XSLT, or any +other tool capable of taking XML as input.

+

+XSLT itself is a XML language very suitable for XML transformations. There -is a free program called xsltproc -that -you can download and install. The -xsltproc +is a free program called xsltproc +that +you can download and install. The +xsltproc program can be used to read the Intermediate XML netlist input file, -apply a +apply a style-sheet to transform the input, and save the results in an output file. Use of xsltproc requires a style-sheet file using XSLT -conventions. The full conversion process is handled -by +conventions. The full conversion process is handled +by Eeschema, after it is configured once to run xsltproc in a specific -way.

-

-4 - -Initialization of the dialog window

-

-You should add a new -pluging (a script) in plugin list by clicking on the Add Plugin -button.

-

-4.1 - Plugin -Configuration Parameters

-

-The Eeschema plug-in -configuration dialog requires the following information:

-
    -
  • - The title: for - instance, the name of the netlist format.

    -
  • - The command line to - launch the converter (usually a script).

    -
-

-Once you click on -the generate button the following will happen:

-
    -
  1. - Eeschema creates an - intermediate netlist file *.xml, for instance test.xml.

    -
  2. - Eeschema runs the - script from the command line to create the final output file.

    -
-

-4.2 - Generate -netlist files with the command line

-

-Assuming we are -using the program xsltproc.exe -to -apply the sheet style to the intermediate file, xsltproc.exe -is -executed with the following command.

-

-xsltproc.exe -o < -output filename > < style-sheet filename > < input XML -file to convert >

-

-On -Windows the command line is the -following.
f:/kicad/bin/xsltproc.exe --o “%O” f:/kicad/bin/plugins/myconverter.xsl “%I”

-

-On -Linux the command becomes as -following.
xsltproc +way.

+

+4 +- Initialization of the dialog window

+

+You +should add a new pluging (a script) in plugin list by clicking on the +Add Plugin button.

+

+4.1 +- Plugin Configuration Parameters

+

+The +Eeschema plug-in configuration dialog requires the following +information:

+
    +
  • +

    + The + title: for instance, the name of the netlist format.

    +
  • +

    + The + command line to launch the converter (usually a script).

    +
+

+Once +you click on the generate button the following will happen:

+
    +
  1. +

    + Eeschema + creates an intermediate netlist file *.xml, for instance test.xml.

    +
  2. +

    + Eeschema + runs the script from the command line to create the final output + file.

    +
+

+4.2 +- Generate netlist files with the command line

+

+Assuming +we are using the program xsltproc.exe +to +apply the sheet style to the intermediate file, xsltproc.exe +is +executed with the following command.

+

+xsltproc.exe +-o < output filename > < style-sheet filename > < +input XML file to convert >

+

+On +Windows the command line is +the following.
f:/kicad/bin/xsltproc.exe +-o “%O” f:/kicad/bin/plugins/myconverter.xsl “%I”

+

+On +Linux the command becomes as +following.
xsltproc -o “%O” /usr/local/kicad/bin/plugins/myconverter .xsl -“%I”

-

-Where -myconverter.xsl -is +“%I”

+

+Where +myconverter.xsl +is the style-sheet that you are applying. Do not forget the double -quotes -around +quotes +around the file names, this allows them to have spaces after the -substitution by Eeschema.

-

-The command line -format accepts parameters for filenames:

-

-The supported -formatting parameters are.

-
    -
  • - %B => base - filename and path of selected output file, minus path and extension.

    -
  • - %I => complete - filename and path of the temporary input file (the intermediate net - file).

    -
  • - %O => complete - filename and path of the user chosen output file.

    -
-

-%I will be replaced -by the actual intermediate file name
%O -will be replaced by the actual output file name.

-

-4.3 - Command -line format: example for xsltproc

-

-The -command line format for xsltproc is the following:
< path of -
xsltproc > xsltproc -< xsltproc parameters >

-

-On -Windows:
f:/kicad/bin/xsltproc.exe -o “%O” -f:/kicad/bin/plugins/netlist_form_pads-pcb.xsl “%I”

-

-On -Linux:
xsltproc +substitution by Eeschema.

+

+The +command line format accepts parameters for filenames:

+

+The +supported formatting parameters are.

+
    +
  • +

    + %B + => base filename and path of selected output file, minus path and + extension.

    +
  • +

    + %I + => complete filename and path of the temporary input file (the + intermediate net file).

    +
  • +

    + %O + => complete filename and path (but without extension) of the user + chosen output file.

    +
+

+%I +will be replaced by the actual intermediate file name
%O +will be replaced by the actual output file name.

+

+4.3 +- Command line format: example for xsltproc

+

+4.3.1 +- Command line

+

+The +command line format for xsltproc is the following:
< path of +
xsltproc > xsltproc +< xsltproc parameters >

+

+On +Windows:
f:/kicad/bin/xsltproc.exe -o “%O” +f:/kicad/bin/plugins/netlist_form_pads-pcb.xsl “%I”

+

+On +Linux:
xsltproc -o “%O” -/usr/local/kicad/bin/plugins/netlist_form_pads-pcb.xsl “%I”

-

-The -above examples assume -xsltproc +/usr/local/kicad/bin/plugins/netlist_form_pads-pcb.xsl “%I”

+

+The +above examples assume +xsltproc is installed on your PC under Windows and all files located in -kicad/bin.

-

-4.4 - Command -line format: example for -python scripts

-

-The command line -format for python is something like:
python -< -script file name > < input filename > < -output filename >

-

-On -Windows:
python.exe f:/kicad/python/my_python_script.py -“%I” “%O”

-

-On Linux:
python -/usr/local/kicad/python/my_python_script.py%I” -“%O”

-

-Assuming python is -installed on your PC.

-

-
-

- - \ No newline at end of file +kicad/bin.

+

+4.3.2 +- Remark:

+

+Most +of time, the created file must have an extension, depending on its +type.
Therefore you have to add to the option %O the +right file extension.

+

+For +instance %O.csv to create a .csv file (comma separated +value file).

+

+
+ +

+

+4.4 +- Command line format: example for +python scripts

+

+4.4.1 +- Command line

+

+The +command line format for python is something like:
python +< +script file name > < input filename > < +output filename >

+

+On +Windows:
python.exe f:/kicad/python/my_python_script.py +“%I” “%O”

+

+On +Linux:
python +/usr/local/kicad/python/my_python_script.py%I” +“%O”

+

+Assuming +python is installed on your PC.

+

+
+ +

+

+4.4.2 +- Remark:

+

+Most +of time, the created file must have an extension, depending on its +type.
Therefore you have to add to the option %O the +right file extension.

+

+For +instance %O.html to create a .html file.

+

+
+ +

+ + \ No newline at end of file diff --git a/eeschema/netform.cpp b/eeschema/netform.cpp index 16f9bde6a8..a87dec87f3 100644 --- a/eeschema/netform.cpp +++ b/eeschema/netform.cpp @@ -381,7 +381,7 @@ bool SCH_EDIT_FRAME::WriteNetListFile( NETLIST_OBJECT_LIST * aConnectedItemsList NETLIST_EXPORT_TOOL helper( aConnectedItemsList, Prj().SchLibs() ); - bool open_file = aFormat < NET_TYPE_CUSTOM1; + bool open_file = (aFormat < NET_TYPE_CUSTOM1) && (aFormat >= 0); if( (aFormat == NET_TYPE_PCBNEW) && (aNetlistOptions & NET_PCBNEW_USE_NEW_FORMAT ) ) open_file = false; @@ -390,7 +390,7 @@ bool SCH_EDIT_FRAME::WriteNetListFile( NETLIST_OBJECT_LIST * aConnectedItemsList if( ( f = wxFopen( aFullFileName, wxT( "wt" ) ) ) == NULL ) { wxString msg; - msg.Printf( _( "Failed to create file <%s>" ), + msg.Printf( _( "Failed to create file '%s'" ), GetChars( aFullFileName ) ); DisplayError( this, msg ); return false; diff --git a/eeschema/plugins/bom2csv.xsl b/eeschema/plugins/bom2csv.xsl index 3140609928..1991d4953e 100644 --- a/eeschema/plugins/bom2csv.xsl +++ b/eeschema/plugins/bom2csv.xsl @@ -19,6 +19,14 @@ in the filename. --> + + ]> diff --git a/eeschema/plugins/bom_cvs.xsl b/eeschema/plugins/bom_cvs.xsl index eacf860ea1..78a6108692 100644 --- a/eeschema/plugins/bom_cvs.xsl +++ b/eeschema/plugins/bom_cvs.xsl @@ -7,6 +7,14 @@ How to use: Eeschema.pdf: chapter 14 --> + @@ -18,20 +26,18 @@ - - - , - , + + ," + "," + "," - &nl; + "&nl; - qty,partname,description,lib&nl; + Qty,partname,description,lib&nl; diff --git a/gerbview/events_called_functions.cpp b/gerbview/events_called_functions.cpp index 96b5d3d577..c06911658b 100644 --- a/gerbview/events_called_functions.cpp +++ b/gerbview/events_called_functions.cpp @@ -90,9 +90,6 @@ BEGIN_EVENT_TABLE( GERBVIEW_FRAME, EDA_DRAW_FRAME ) EVT_MENU( wxID_HELP, EDA_DRAW_FRAME::GetKicadHelp ) EVT_MENU( wxID_ABOUT, EDA_DRAW_FRAME::GetKicadAbout ) - EVT_TOOL( wxID_CUT, GERBVIEW_FRAME::Process_Special_Functions ) - EVT_TOOL( wxID_COPY, GERBVIEW_FRAME::Process_Special_Functions ) - EVT_TOOL( wxID_PASTE, GERBVIEW_FRAME::Process_Special_Functions ) EVT_TOOL( wxID_UNDO, GERBVIEW_FRAME::Process_Special_Functions ) EVT_TOOL( wxID_PRINT, GERBVIEW_FRAME::ToPrinter ) EVT_COMBOBOX( ID_TOOLBARH_GERBVIEW_SELECT_ACTIVE_LAYER, @@ -145,9 +142,6 @@ void GERBVIEW_FRAME::Process_Special_Functions( wxCommandEvent& event ) switch( id ) { - case wxID_CUT: - case wxID_COPY: - case ID_POPUP_DELETE_BLOCK: case ID_POPUP_PLACE_BLOCK: case ID_POPUP_ZOOM_BLOCK: break; @@ -219,12 +213,6 @@ void GERBVIEW_FRAME::Process_Special_Functions( wxCommandEvent& event ) HandleBlockEnd( &dc ); break; - case ID_POPUP_DELETE_BLOCK: - GetScreen()->m_BlockLocate.SetCommand( BLOCK_DELETE ); - GetScreen()->m_BlockLocate.SetMessageBlock( this ); - HandleBlockEnd( &dc ); - break; - default: wxFAIL_MSG( wxT( "GERBVIEW_FRAME::Process_Special_Functions error" ) ); break; diff --git a/gerbview/files.cpp b/gerbview/files.cpp index b35a61a021..98f4122d41 100644 --- a/gerbview/files.cpp +++ b/gerbview/files.cpp @@ -80,7 +80,7 @@ void GERBVIEW_FRAME::Files_io( wxCommandEvent& event ) break; case ID_GERBVIEW_ERASE_ALL: - Clear_DrawLayers( true ); + Clear_DrawLayers( false ); Zoom_Automatique( false ); m_canvas->Refresh(); ClearMsgPanel(); diff --git a/gerbview/onrightclick.cpp b/gerbview/onrightclick.cpp index 33928cc488..8f5cfe33b0 100644 --- a/gerbview/onrightclick.cpp +++ b/gerbview/onrightclick.cpp @@ -24,7 +24,6 @@ #include #include -#include #include #include @@ -75,8 +74,6 @@ bool GERBVIEW_FRAME::OnRightClick( const wxPoint& aPosition, wxMenu* PopMenu ) PopMenu->AppendSeparator(); AddMenuItem( PopMenu, ID_POPUP_PLACE_BLOCK, _( "Place Block" ), KiBitmap( checked_ok_xpm ) ); - AddMenuItem( PopMenu, ID_POPUP_DELETE_BLOCK, - _( "Delete Block (ctrl + drag mouse)" ), KiBitmap( delete_xpm ) ); } else { diff --git a/include/dsnlexer.h b/include/dsnlexer.h index b6f3a87516..6384e47790 100644 --- a/include/dsnlexer.h +++ b/include/dsnlexer.h @@ -71,7 +71,7 @@ enum DSN_SYNTAX_T { /** - * Class DLEXER + * Class DSNLEXER * implements a lexical analyzer for the SPECCTRA DSN file format. It * reads lexical tokens from the current LINE_READER through the NextTok() * function. @@ -215,6 +215,16 @@ public: virtual ~DSNLEXER(); + /** + * Useable only for DSN lexers which share the same LINE_READER + * Synchronizes the pointers handling the data read by the LINE_READER + * Allows 2 DNSLEXER to share the same current line, when switching from a + * DNSLEXER to an other DNSLEXER + * @param aLexer = the model + * @return true if the sync can be made ( at least the same line reader ) + */ + bool SyncLineReaderWith( DSNLEXER& aLexer ); + /** * Function SetSpecctraMode * changes the behavior of this lexer into or out of "specctra mode". If diff --git a/pcbnew/board_items_to_polygon_shape_transform.cpp b/pcbnew/board_items_to_polygon_shape_transform.cpp index 4c98c8c77c..67446d245c 100644 --- a/pcbnew/board_items_to_polygon_shape_transform.cpp +++ b/pcbnew/board_items_to_polygon_shape_transform.cpp @@ -580,7 +580,10 @@ void D_PAD:: TransformShapeWithClearanceToPolygon( CPOLYGONS_LIST& aCornerBuffer ClipperLib::Paths shapeWithClearance; for( int ii = 0; ii < 4; ii++ ) + { + corners[ii] += PadShapePos; outline << ClipperLib::IntPoint( corners[ii].x, corners[ii].y ); + } ClipperLib::ClipperOffset offset_engine; // Prepare an offset (inflate) transform, with edges connected by arcs @@ -600,19 +603,7 @@ void D_PAD:: TransformShapeWithClearanceToPolygon( CPOLYGONS_LIST& aCornerBuffer offset_engine.Execute( shapeWithClearance, rounding_radius ); // get new outline (only one polygon is expected) - // For info, ClipperLib uses long long to handle integer coordinates - ClipperLib::Path& polygon = shapeWithClearance[0]; - - for( unsigned jj = 0; jj < polygon.size(); jj++ ) - { - corner_position.x = int( polygon[jj].X ); - corner_position.y = int( polygon[jj].Y ); - corner_position += PadShapePos; - CPolyPt polypoint( corner_position.x, corner_position.y ); - aCornerBuffer.Append( polypoint ); - } - - aCornerBuffer.CloseLastContour(); + aCornerBuffer.ImportFrom( shapeWithClearance ); } break; } @@ -1008,7 +999,6 @@ void CreateThermalReliefPadPolygon( CPOLYGONS_LIST& aCornerBuffer, double angle = aPad.GetOrientation(); int rounding_radius = KiROUND( aThermalGap * aCorrectionFactor ); // Corner rounding radius - double angle_pg; // Polygon increment angle for( int i = 0; i < aCircleToSegmentsCount / 4 + 1; i++ ) { @@ -1016,7 +1006,7 @@ void CreateThermalReliefPadPolygon( CPOLYGONS_LIST& aCornerBuffer, // Start at half increment offset RotatePoint( &corner_position, 1800.0 / aCircleToSegmentsCount ); - angle_pg = i * delta; + double angle_pg = i * delta; RotatePoint( &corner_position, angle_pg ); // Rounding vector rotation corner_position -= aPad.GetSize() / 2; // Rounding vector + Pad corner offset diff --git a/pcbnew/class_zone.cpp b/pcbnew/class_zone.cpp index 40ccb300a4..6acefe36c7 100644 --- a/pcbnew/class_zone.cpp +++ b/pcbnew/class_zone.cpp @@ -898,3 +898,14 @@ wxString ZONE_CONTAINER::GetSelectMenuText() const return msg; } + + +/* Copy polygons stored in aKiPolyList to m_FilledPolysList + * The previous m_FilledPolysList contents is replaced. + */ +void ZONE_CONTAINER::CopyPolygonsFromClipperPathsToFilledPolysList( + ClipperLib::Paths& aClipperPolyList ) +{ + m_FilledPolysList.RemoveAllContours(); + m_FilledPolysList.ImportFrom( aClipperPolyList ); +} diff --git a/pcbnew/class_zone.h b/pcbnew/class_zone.h index ee8fdbecdf..87d9727085 100644 --- a/pcbnew/class_zone.h +++ b/pcbnew/class_zone.h @@ -305,6 +305,14 @@ public: */ void CopyPolygonsFromKiPolygonListToFilledPolysList( KI_POLYGON_SET& aKiPolyList ); + /** + * Function CopyPolygonsFromClipperPathsToFilledPolysList + * Copy polygons stored in aKiPolyList to m_FilledPolysList + * The previous m_FilledPolysList contents is replaced. + * @param aClipperPolyList = a ClipperLib::Paths containing polygons. + */ + void CopyPolygonsFromClipperPathsToFilledPolysList( ClipperLib::Paths& aClipperPolyList ); + /** * Function CopyPolygonsFromFilledPolysListToKiPolygonList * Copy polygons from m_FilledPolysList to aKiPolyList diff --git a/pcbnew/eagle_plugin.cpp b/pcbnew/eagle_plugin.cpp index 1d307e9ede..fda3e90a98 100644 --- a/pcbnew/eagle_plugin.cpp +++ b/pcbnew/eagle_plugin.cpp @@ -1938,14 +1938,39 @@ void EAGLE_PLUGIN::packageWire( MODULE* aModule, CPTREE& aTree ) const wxPoint end( kicad_x( w.x2 ), kicad_y( w.y2 ) ); int width = kicad( w.width ); - EDGE_MODULE* dwg = new EDGE_MODULE( aModule, S_SEGMENT ); - aModule->GraphicalItems().PushBack( dwg ); + EDGE_MODULE* dwg; + if( !w.curve ) + { + dwg = new EDGE_MODULE( aModule, S_SEGMENT ); - dwg->SetStart0( start ); - dwg->SetEnd0( end ); + dwg->SetStart0( start ); + dwg->SetEnd0( end ); + } + else + { + dwg = new EDGE_MODULE( aModule, S_ARC ); + // Eagle give us start and end. + // S_ARC wants start to give the centre, and end to give the start + double dx = end.x - start.x, dy = end.y - start.y; + wxPoint mid = (start + end) / 2; + + double dlen = sqrt( dx*dx + dy*dy ); + double dist = dlen / ( 2 * tan( DEG2RAD( *w.curve ) / 2 ) ); + + wxPoint centre( + mid.x + dist * ( dy / dlen ), + mid.y - dist * ( dx / dlen ) + ); + + dwg->SetStart0( centre ); + dwg->SetEnd0( start ); + dwg->SetAngle( *w.curve * -10.0 ); // KiCad rotates the other way + } dwg->SetLayer( layer ); dwg->SetWidth( width ); + + aModule->GraphicalItems().PushBack( dwg ); } } diff --git a/pcbnew/edit.cpp b/pcbnew/edit.cpp index f43ebabde7..d5077f0d25 100644 --- a/pcbnew/edit.cpp +++ b/pcbnew/edit.cpp @@ -541,6 +541,9 @@ void PCB_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) break; case ID_POPUP_PCB_DELETE_ZONE_CONTAINER: + // Force the main contour selection, to remove the entire zone: + ((ZONE_CONTAINER*) GetCurItem())->SetSelectedCorner( 0 ); + // Fall through case ID_POPUP_PCB_DELETE_ZONE_CUTOUT: m_canvas->MoveCursorToCrossHair(); { diff --git a/pcbnew/event_handlers_tracks_vias_sizes.cpp b/pcbnew/event_handlers_tracks_vias_sizes.cpp index 21e8d4a000..3361f4b790 100644 --- a/pcbnew/event_handlers_tracks_vias_sizes.cpp +++ b/pcbnew/event_handlers_tracks_vias_sizes.cpp @@ -41,9 +41,7 @@ #include -/** - * Function Tracks_and_Vias_Size_Event - * Event handler for tracks and vias size selection (and some options) +/* Event handler for tracks and vias size selection (and some options) * relative to toolbars and popup events */ void PCB_EDIT_FRAME::Tracks_and_Vias_Size_Event( wxCommandEvent& event ) @@ -51,11 +49,11 @@ void PCB_EDIT_FRAME::Tracks_and_Vias_Size_Event( wxCommandEvent& event ) int ii; int id = event.GetId(); -/* Note: none of these events require aborting the current command (if any) - * (like move, edit or block command) - * so we do not test for a current command in progress and call - * m_canvas->m_endMouseCaptureCallback( m_canvas, &dc ); - */ + /* Note: none of these events require aborting the current command (if any) + * (like move, edit or block command) + * so we do not test for a current command in progress and call + * m_canvas->m_endMouseCaptureCallback( m_canvas, &dc ); + */ switch( id ) { case ID_AUX_TOOLBAR_PCB_SELECT_AUTO_WIDTH: @@ -142,5 +140,7 @@ void PCB_EDIT_FRAME::Tracks_and_Vias_Size_Event( wxCommandEvent& event ) }*/ //+hp //Refresh canvas, that we can see changes instantly. I use this because it dont,t throw mouse up-left corner. - m_canvas->Refresh(); + + if( m_canvas->IsMouseCaptured() ) + m_canvas->Refresh(); } diff --git a/pcbnew/hotkeys.cpp b/pcbnew/hotkeys.cpp index 1cfb3b4e9e..8f903b7d48 100644 --- a/pcbnew/hotkeys.cpp +++ b/pcbnew/hotkeys.cpp @@ -126,6 +126,10 @@ static EDA_HOTKEY HkCanvasOpenGL( wxT( "Switch to OpenGL Canvas" ), static EDA_HOTKEY HkCanvasCairo( wxT( "Switch to Cairo Canvas" ), HK_CANVAS_CAIRO, WXK_F12 ); +static EDA_HOTKEY HkZoneFillOrRefill( wxT( "Fill or Refill All Zones" ), + HK_ZONE_FILL_OR_REFILL, 'B' ); +static EDA_HOTKEY HkZoneRemoveFilled( wxT( "Remove Filled Areas in All Zones" ), + HK_ZONE_REMOVE_FILLED, 'N' ); /* Fit on Screen */ #if !defined( __WXMAC__ ) static EDA_HOTKEY HkZoomAuto( wxT( "Zoom Auto" ), HK_ZOOM_AUTO, WXK_HOME ); @@ -289,6 +293,7 @@ EDA_HOTKEY* board_edit_Hotkey_List[] = &HkRecordMacros8, &HkCallMacros8, &HkRecordMacros9, &HkCallMacros9, &HkSwitchHighContrastMode, &HkCanvasDefault, &HkCanvasCairo, &HkCanvasOpenGL, + &HkZoneFillOrRefill, &HkZoneRemoveFilled, NULL }; diff --git a/pcbnew/hotkeys.h b/pcbnew/hotkeys.h index b3bd3c183b..ca58a7fddd 100644 --- a/pcbnew/hotkeys.h +++ b/pcbnew/hotkeys.h @@ -114,7 +114,9 @@ enum hotkey_id_commnand { HK_CANVAS_OPENGL, HK_CANVAS_CAIRO, HK_LEFT_CLICK, - HK_LEFT_DCLICK + HK_LEFT_DCLICK, + HK_ZONE_FILL_OR_REFILL, + HK_ZONE_REMOVE_FILLED }; // Full list of hotkey descriptors for board editor and footprint editor diff --git a/pcbnew/hotkeys_board_editor.cpp b/pcbnew/hotkeys_board_editor.cpp index 3be8c527f9..5682dd770c 100644 --- a/pcbnew/hotkeys_board_editor.cpp +++ b/pcbnew/hotkeys_board_editor.cpp @@ -41,6 +41,7 @@ #include #include #include +#include /* How to add a new hotkey: * see hotkeys.cpp @@ -566,6 +567,13 @@ bool PCB_EDIT_FRAME::OnHotKey( wxDC* aDC, int aHotkeyCode, const wxPoint& aPosit case HK_CANVAS_DEFAULT: evt_type = ID_MENU_CANVAS_DEFAULT; break; + case HK_ZONE_FILL_OR_REFILL: + evt_type = ID_POPUP_PCB_FILL_ALL_ZONES; + break; + case HK_ZONE_REMOVE_FILLED: + evt_type = ID_POPUP_PCB_REMOVE_FILLED_AREAS_IN_ALL_ZONES; + break; + } if( evt_type != 0 ) diff --git a/pcbnew/onrightclick.cpp b/pcbnew/onrightclick.cpp index bafbffe37f..9de056f34f 100644 --- a/pcbnew/onrightclick.cpp +++ b/pcbnew/onrightclick.cpp @@ -319,10 +319,14 @@ bool PCB_EDIT_FRAME::OnRightClick( const wxPoint& aMousePos, wxMenu* aPopMenu ) if( GetBoard()->m_ZoneDescriptorList.size() > 0 ) { aPopMenu->AppendSeparator(); + msg = AddHotkeyName( _( "Fill or Refill All Zones" ), + g_Board_Editor_Hokeys_Descr, HK_ZONE_FILL_OR_REFILL ); AddMenuItem( aPopMenu, ID_POPUP_PCB_FILL_ALL_ZONES, - _( "Fill or Refill All Zones" ), KiBitmap( fill_zone_xpm ) ); + msg, KiBitmap( fill_zone_xpm ) ); + msg = AddHotkeyName( _( "Remove Filled Areas in All Zones" ), + g_Board_Editor_Hokeys_Descr, HK_ZONE_REMOVE_FILLED ); AddMenuItem( aPopMenu, ID_POPUP_PCB_REMOVE_FILLED_AREAS_IN_ALL_ZONES, - _( "Remove Filled Areas in All Zones" ), KiBitmap( zone_unfill_xpm ) ); + msg, KiBitmap( zone_unfill_xpm ) ); aPopMenu->AppendSeparator(); } diff --git a/pcbnew/pcb_parser.cpp b/pcbnew/pcb_parser.cpp index 0d53ff9263..1cfc1fb08e 100644 --- a/pcbnew/pcb_parser.cpp +++ b/pcbnew/pcb_parser.cpp @@ -1135,12 +1135,14 @@ void PCB_PARSER::parseSetup() throw( IO_ERROR, PARSE_ERROR ) { PCB_PLOT_PARAMS plotParams; PCB_PLOT_PARAMS_PARSER parser( reader ); + // parser must share the same current line as our current PCB parser + // synchronize it. + parser.SyncLineReaderWith( *this ); plotParams.Parse( &parser ); - m_board->SetPlotOptions( plotParams ); + SyncLineReaderWith( parser ); - // I don't know why but this seems to fix a problem in PCB_PLOT_PARAMS::Parse(). - NextTok(); + m_board->SetPlotOptions( plotParams ); } break; diff --git a/pcbnew/pcb_plot_params.cpp b/pcbnew/pcb_plot_params.cpp index 4855a89c1e..1e04a8b6c5 100644 --- a/pcbnew/pcb_plot_params.cpp +++ b/pcbnew/pcb_plot_params.cpp @@ -22,7 +22,7 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ -#include +//#include #include #include #include diff --git a/pcbnew/plot_board_layers.cpp b/pcbnew/plot_board_layers.cpp index 8e412f50f3..6d1f397aba 100644 --- a/pcbnew/plot_board_layers.cpp +++ b/pcbnew/plot_board_layers.cpp @@ -773,12 +773,25 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, zone->TransformOutlinesShapeWithClearanceToPolygon( bufferPolys, inflate, true ); + zone->TransformOutlinesShapeWithClearanceToPolygon( initialPolys, + 0, true ); } + // To avoid a lot of code, use a ZONE_CONTAINER + // to handle and plot polygons, because our polygons look exactly like + // filled areas in zones + // Note, also this code is not optimized: it creates a lot of copy/duplicate data + // However it is not complex, and fast enough for plot purposes (copy/convert data + // is only a very small calculation time for these calculations) + ZONE_CONTAINER zone( aBoard ); + zone.SetArcSegmentCount( 32 ); + zone.SetMinThickness( 0 ); // trace polygons only + zone.SetLayer ( layer ); + // Now: - // 1 - merge areas which are intersecting, i.e. remove gaps + // 1 - merge polygons which are intersecting, i.e. remove gaps // having a thickness < aMinThickness - // 2 - deflate resulting areas by aMinThickness/2 + // 2 - deflate resulting polygons by aMinThickness/2 KI_POLYGON_SET areasToMerge; bufferPolys.ExportTo( areasToMerge ); KI_POLYGON_SET initialAreas; @@ -788,29 +801,44 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, // = aMinThickness/2, shapes too close ( dist < aMinThickness ) // will be merged, because they are overlapping KI_POLYGON_SET areas; - areas |= areasToMerge; + areas |= areasToMerge; // Populates with merged polygons // Deflate: remove the extra margin, to create the actual shapes // Here I am using polygon:resize, because this function creates better shapes // than deflate algo. - // Use here deflate with arc creation and 18 segments per circle to create arcs - // In boost polygon (at least v 1.54 and previous) in very rare cases resize crashes - // with 16 segments (perhaps related to 45 degrees pads). So using 18 segments - // is a workaround to try to avoid these crashes - areas = resize( areas, -inflate , true, 18 ); + // Use here deflate made by Clipper, because: + // Clipper is (by far) faster and better, event using arcs to deflate shapes + // boost::polygon < 1.56 polygon resize function sometimes crashes when deflating using arcs + // boost::polygon >=1.56 polygon resize function just does not work + // Note also we combine polygons using boost::polygon, which works better than Clipper, + // especially with zones using holes linked to main outlines by overlapping segments + CPOLYGONS_LIST tmp; + tmp.ImportFrom( areas ); - // Resize slightly changes shapes. So *ensure* initial shapes are kept + // Deflate area using Clipper, better than boost::polygon + ClipperLib::Paths areasDeflate; + tmp.ExportTo( areasDeflate ); + + // Deflate areas: they will have the right size after deflate + ClipperLib::ClipperOffset offset_engine; + circleToSegmentsCount = 16; + offset_engine.ArcTolerance = (double)inflate / 3.14 / circleToSegmentsCount; + offset_engine.AddPaths( areasDeflate, ClipperLib::jtRound, ClipperLib::etClosedPolygon ); + offset_engine.Execute( areasDeflate, -inflate ); + + // Combine the current areas to initial areas. This is mandatory because + // inflate/deflate transform is not perfect, and we want the initial areas perfectly kept + tmp.RemoveAllContours(); + tmp.ImportFrom( areasDeflate ); + areas.clear(); + tmp.ExportTo( areas ); + + // Resize slightly changes shapes (the transform is not perfect). + // So *ensure* initial shapes are kept areas |= initialAreas; - // To avoid a lot of code, use a ZONE_CONTAINER - // to plot polygons, because they are exactly like - // filled areas in zones - ZONE_CONTAINER zone( aBoard ); - zone.SetArcSegmentCount( 32 ); - zone.SetMinThickness( 0 ); // trace polygons only - zone.SetLayer ( layer ); - zone.CopyPolygonsFromKiPolygonListToFilledPolysList( areas ); + itemplotter.PlotFilledAreas( &zone ); } diff --git a/pcbnew/zones_by_polygon.cpp b/pcbnew/zones_by_polygon.cpp index 512141d5fc..76ae549a9e 100644 --- a/pcbnew/zones_by_polygon.cpp +++ b/pcbnew/zones_by_polygon.cpp @@ -29,7 +29,6 @@ */ #include -//#include #include #include #include diff --git a/scripting/build_tools/fix_swig_imports.py b/scripting/build_tools/fix_swig_imports.py index 9fcbdc64c6..e333deb89a 100644 --- a/scripting/build_tools/fix_swig_imports.py +++ b/scripting/build_tools/fix_swig_imports.py @@ -13,7 +13,7 @@ from sys import argv,exit if len(argv)<2: print "usage:" - print " fixswigimports.py file.py" + print " fix_swig_imports.py file.py" print "" print " will fix the swig import code for working inside KiCad" print " where it happended that the external _pcbnew.so/dll was" @@ -52,7 +52,7 @@ if doneOk: print "swig_import_helper fixed for",filename else: print "Error: the swig import helper was not fixed, check",filename - print " and fix this script: fixswigimports.py" + print " and fix this script: fix_swig_imports.py" exit(2) diff --git a/scripts/bom-in-python/README-bom.txt b/scripts/bom-in-python/README-bom.txt index e5be840892..89e10c19a7 100644 --- a/scripts/bom-in-python/README-bom.txt +++ b/scripts/bom-in-python/README-bom.txt @@ -1,7 +1,7 @@ bom_?.py are some python scripts which read a generic xml netlist from eeschema, and create a bom. -All examples use ky_generic_netlist_reader.py, which is a python utility to read +All examples use ky_netlist_reader.py, which is a python utility to read and parse this generic xml netlist and create the corresponding data used to build the bom. @@ -12,3 +12,27 @@ python bom_example?.py See Eeschema doc, chapter 14 for info about the generic xml netlist format, and how to run a script from Eeschema to create a customized netlist or BOM. + +If the python comment +""" + @package + some comments +""" +is added to the begining of the python script, the comment will be displayed +in Eescheam, in the BOM dialog + +For instance: +""" + @package + Generate a HTML BOM list. + Components are sorted and grouped by value + Fields are (if exist) + Ref, Quantity, Value, Part, Datasheet, Description, Vendor +""" + +displays: + Generate a HTML BOM list. + Components are sorted and grouped by value + Fields are (if exist) + Ref, Quantity, Value, Part, Datasheet, Description, Vendor +in BOM dialog diff --git a/scripts/bom-in-python/bom-generation.py b/scripts/bom-in-python/bom-generation.py index c0cda72fd8..9d7d704af7 100644 --- a/scripts/bom-in-python/bom-generation.py +++ b/scripts/bom-in-python/bom-generation.py @@ -4,6 +4,15 @@ # Example: Sorted and Grouped HTML BOM with more advanced grouping # +""" + @package + Generate a HTML BOM list. + Components are sorted and grouped by value + Fields are (if exist) + Ref, Quantity, Value, Part, Datasheet, Description, Vendor +""" + + from __future__ import print_function # Import the KiCad python helper module and the csv formatter @@ -74,8 +83,9 @@ net = kicad_netlist_reader.netlist(sys.argv[1]) try: f = open(sys.argv[2], 'w') except IOError: + e = "Can't open output file for writing: " + sys.argv[2] print(__file__, ":", e, file=sys.stderr) - f = stdout + f = sys.stdout # Output a set of rows for a header providing general information html = html.replace('', net.getSource()) diff --git a/scripts/bom-in-python/bom_csv_by_ref.py b/scripts/bom-in-python/bom_csv_by_ref.py index 046272dec4..d30e8cdcb7 100644 --- a/scripts/bom-in-python/bom_csv_by_ref.py +++ b/scripts/bom-in-python/bom_csv_by_ref.py @@ -1,8 +1,14 @@ # # Example python script to generate a BOM from a KiCad generic netlist # -# Example: Tab delimited list (The same as std output) Ungrouped -# +""" + @package + Generate a csv list file. + Components are sorted by ref and grouped by value + One component per line + Fields are (if exist) + Ref, Quantity, value, Part, footprint, 'Description', 'Vendor' +""" from __future__ import print_function @@ -20,8 +26,9 @@ net = kicad_netlist_reader.netlist(sys.argv[1]) try: f = open(sys.argv[2], 'w') except IOError: - print(__file__, ":", e, file=sys.stderr) - f = stdout + e = "Can't open output file for writing: " + sys.argv[2] + print(__file__, ":", e, sys.stderr) + f = sys.stdout # Create a new csv writer object to use as the output formatter, although we # are created a tab delimited list instead! diff --git a/scripts/bom-in-python/bom_csv_by_ref_v2.py b/scripts/bom-in-python/bom_csv_by_ref_v2.py index ccb303e097..c82c3286bb 100644 --- a/scripts/bom-in-python/bom_csv_by_ref_v2.py +++ b/scripts/bom-in-python/bom_csv_by_ref_v2.py @@ -4,6 +4,15 @@ # Example: Ungrouped (One component per row) CSV output # +""" + @package + Generate a csv list file. + Components are sorted by ref and grouped by value + One component per line + Fields are (if exist) + Ref, value, Part, footprint, Datasheet, Manufacturer, Vendor +""" + from __future__ import print_function # Import the KiCad python helper module @@ -20,8 +29,9 @@ net = kicad_netlist_reader.netlist(sys.argv[1]) try: f = open(sys.argv[2], 'w') except IOError: - print(__file__, ":", e, file=sys.stderr) - f = stdout + e = "Can't open output file for writing: " + sys.argv[2] + print( __file__, ":", e, sys.stderr ) + f = sys.stdout # Create a new csv writer object to use as the output formatter out = csv.writer(f, lineterminator='\n', delimiter=',', quotechar="\"", quoting=csv.QUOTE_ALL) diff --git a/scripts/bom-in-python/bom_csv_grouped_by_value.py b/scripts/bom-in-python/bom_csv_grouped_by_value.py index 3051b93bba..4d3ddb3b82 100644 --- a/scripts/bom-in-python/bom_csv_grouped_by_value.py +++ b/scripts/bom-in-python/bom_csv_grouped_by_value.py @@ -27,7 +27,7 @@ try: f = open(sys.argv[2], 'w') except IOError: e = "Can't open output file for writing: " + sys.argv[2] - print(__file__, ":", e, file=sys.stderr) + print( __file__, ":", e, sys.stderr ) f = sys.stdout # subset the components to those wanted in the BOM, controlled @@ -46,7 +46,7 @@ columnset = compfields | partfields # union columns = ['Item', 'Qty', 'Reference(s)', 'Value', 'LibPart', 'Footprint', 'Datasheet'] + sorted(list(columnset)) # Create a new csv writer object to use as the output formatter -out = csv.writer(f, lineterminator='\n', delimiter=',', quotechar='\"', quoting=csv.QUOTE_MINIMAL) +out = csv.writer( f, lineterminator='\n', delimiter=',', quotechar='\"', quoting=csv.QUOTE_MINIMAL ) # override csv.writer's writerow() to support utf8 encoding: def writerow( acsvwriter, columns ): diff --git a/scripts/bom-in-python/bom_csv_grouped_by_value_with_fp.py b/scripts/bom-in-python/bom_csv_grouped_by_value_with_fp.py new file mode 100644 index 0000000000..2f24f1892a --- /dev/null +++ b/scripts/bom-in-python/bom_csv_grouped_by_value_with_fp.py @@ -0,0 +1,61 @@ +# +# Example python script to generate a BOM from a KiCad generic netlist +# +# Example: Sorted and Grouped CSV BOM +# + +""" + @package + Generate a Tab delimited list (csv file type). + Components are sorted by ref and grouped by value + Fields are (if exist) + 'Ref', 'Qnty', 'Value', 'Sch lib name', 'footprint', 'Description', 'Vendor' +""" + +# Import the KiCad python helper module and the csv formatter +import kicad_netlist_reader +import csv +import sys + +# Generate an instance of a generic netlist, and load the netlist tree from +# the command line option. If the file doesn't exist, execution will stop +net = kicad_netlist_reader.netlist(sys.argv[1]) + +# Open a file to write to, if the file cannot be opened output to stdout +# instead +try: + f = open(sys.argv[2], 'w') +except IOError: + e = "Can't open output file for writing: " + sys.argv[2] + print(__file__, ":", e, sys.stderr) + f = sys.stdout + +# Create a new csv writer object to use as the output formatter +out = csv.writer(f, lineterminator='\n', delimiter=',', quotechar='\"', quoting=csv.QUOTE_ALL) + +# Output a set of rows for a header providing general information +out.writerow(['Source:', net.getSource()]) +out.writerow(['Date:', net.getDate()]) +out.writerow(['Tool:', net.getTool()]) +out.writerow(['Component Count:', len(net.components)]) +out.writerow(['Ref', 'Qnty', 'Value', 'Sch lib name', 'footprint', 'Description', 'Vendor']) + +# Get all of the components in groups of matching parts + values +# (see ky_generic_netlist_reader.py) +grouped = net.groupComponents() + +# Output all of the component information +for group in grouped: + refs = "" + + # Add the reference of every component in the group and keep a reference + # to the component so that the other data can be filled in once per group + for component in group: + refs += component.getRef() + ", " + c = component + + # Fill in the component groups common data + out.writerow([refs, len(group), c.getValue(), c.getLibName() + "/" + c.getPartName(), c.getFootprint(), + c.getDescription(), c.getField("Vendor")]) + + diff --git a/scripts/bom-in-python/bom_html_by_value.py b/scripts/bom-in-python/bom_html_by_value.py index b4493f5fe4..c8205b0a1b 100644 --- a/scripts/bom-in-python/bom_html_by_value.py +++ b/scripts/bom-in-python/bom_html_by_value.py @@ -4,6 +4,15 @@ # Example: Sorted and Grouped HTML BOM with more advanced grouping # +""" + @package + Generate a HTML BOM list. + Components are sorted and grouped by ref + Fields are (if exist) + Ref, Quantity, Value, Part, Datasheet, Description, Vendor +""" + + from __future__ import print_function # Import the KiCad python helper module and the csv formatter @@ -74,8 +83,9 @@ net = kicad_netlist_reader.netlist(sys.argv[1]) try: f = open(sys.argv[2], 'w') except IOError: - print(__file__, ":", e, file=sys.stderr) - f = stdout + e = "Can't open output file for writing: " + sys.argv[2] + print( __file__, ":", e, sys.stderr ) + f = sys.stdout components = net.getInterestingComponents() diff --git a/scripts/bom-in-python/bom_html_grouped_by_value.py b/scripts/bom-in-python/bom_html_grouped_by_value.py index 175191bcc4..b9f7aa05f3 100644 --- a/scripts/bom-in-python/bom_html_grouped_by_value.py +++ b/scripts/bom-in-python/bom_html_grouped_by_value.py @@ -3,6 +3,13 @@ # # Example: Sorted and Grouped HTML BOM # +""" + @package + Generate a HTML BOM list. + Components are sorted by ref and grouped by value + Fields are (if exist) + Ref, Quantity, Value, Part, Datasheet, Description, Vendor +""" from __future__ import print_function @@ -39,8 +46,9 @@ net = kicad_netlist_reader.netlist(sys.argv[1]) try: f = open(sys.argv[2], 'w') except IOError: + e = "Can't open output file for writing: " + sys.argv[2] print(__file__, ":", e, file=sys.stderr) - f = stdout + f = sys.stdout components = net.getInterestingComponents() @@ -51,7 +59,8 @@ html = html.replace('', net.getTool()) html = html.replace('', "Component Count:" + \ str(len(components))) -row = "Ref" + "Qnty" +row = "Ref" +row += "Qnty" row += "Value" + "Part" + "Datasheet" row += "Description" + "Vendor" @@ -74,10 +83,11 @@ for group in grouped: c = component row = "" + refs +"" + str(len(group)) - row += "" + c.getValue() + "" + c.getLibName() + ":" - row += c.getPartName() + "" + c.getDatasheet() + "" - row += c.getDescription() + "" + c.getField("Vendor") - row += "" + row += "" + c.getValue() + row += "" + c.getLibName() + ":" + c.getPartName() + row += "" + c.getDatasheet() + row += "" + c.getDescription() + row += "" + c.getField("Vendor")+ "" html = html.replace('', row + "") diff --git a/scripts/bom-in-python/kicad_netlist_reader.py b/scripts/bom-in-python/kicad_netlist_reader.py index 8a01adcd19..c60e4432a9 100644 --- a/scripts/bom-in-python/kicad_netlist_reader.py +++ b/scripts/bom-in-python/kicad_netlist_reader.py @@ -7,6 +7,15 @@ # is due to be deprecated in 3.0+ soon # +""" + @package + Generate a HTML BOM list. + Components are sorted and grouped by value + Fields are (if exist) + Ref, Quantity, Value, Part, Datasheet, Description, Vendor +""" + + from __future__ import print_function import sys import xml.sax as sax diff --git a/scripts/bom-in-python/round_robin.py b/scripts/bom-in-python/round_robin.py index 245f7ad16d..0f15e6f292 100644 --- a/scripts/bom-in-python/round_robin.py +++ b/scripts/bom-in-python/round_robin.py @@ -21,7 +21,8 @@ net = kicad_netlist_reader.netlist(sys.argv[1]) try: f = open(sys.argv[2], 'w') except IOError: - print( __file__, ":", e, file=sys.stderr) - f = stdout + e = "Can't open output file for writing: " + sys.argv[2] + print( __file__, ":", e, sys.stderr) + f = sys.stdout print(net.formatXML(), file=f) diff --git a/scripts/bom-in-python/round_value_robin.py b/scripts/bom-in-python/round_value_robin.py index 028312fc2a..e1bf3ff5ff 100644 --- a/scripts/bom-in-python/round_value_robin.py +++ b/scripts/bom-in-python/round_value_robin.py @@ -64,8 +64,9 @@ net = kicad_netlist_reader.netlist(sys.argv[1]) try: f = open(sys.argv[2], 'w') except IOError: + e = "Can't open output file for writing: " + sys.argv[2] print(__file__, ":", e, file=sys.stderr) - f = stdout + f = sys.stdout for c in net.components: c.checkvalue()