Commit 5a202e16 authored by Garth Corral's avatar Garth Corral

Merge trunk @ 5315

parents 0cf91f46 58f2d2e8
...@@ -148,6 +148,34 @@ void DSNLEXER::SetSpecctraMode( bool aMode ) ...@@ -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 ) void DSNLEXER::PushReader( LINE_READER* aLineReader )
{ {
readerStack.push_back( aLineReader ); readerStack.push_back( aLineReader );
......
...@@ -275,6 +275,9 @@ bool FOOTPRINT_LIST::ReadFootprintFiles( FP_LIB_TABLE* aTable, const wxString* a ...@@ -275,6 +275,9 @@ bool FOOTPRINT_LIST::ReadFootprintFiles( FP_LIB_TABLE* aTable, const wxString* a
FOOTPRINT_INFO* FOOTPRINT_LIST::GetModuleInfo( const wxString& aFootprintName ) FOOTPRINT_INFO* FOOTPRINT_LIST::GetModuleInfo( const wxString& aFootprintName )
{ {
if( aFootprintName.IsEmpty() )
return NULL;
BOOST_FOREACH( FOOTPRINT_INFO& fp, m_list ) BOOST_FOREACH( FOOTPRINT_INFO& fp, m_list )
{ {
FPID fpid; FPID fpid;
......
...@@ -69,7 +69,6 @@ public: ...@@ -69,7 +69,6 @@ public:
private: private:
void parsePlugin() throw( IO_ERROR, PARSE_ERROR ); void parsePlugin() throw( IO_ERROR, PARSE_ERROR );
}; };
// PCB_PLOT_PARAMS_PARSER // PCB_PLOT_PARAMS_PARSER
...@@ -175,7 +174,6 @@ private: ...@@ -175,7 +174,6 @@ private:
void OnCancelClick( wxCommandEvent& event ); void OnCancelClick( wxCommandEvent& event );
void OnHelp( wxCommandEvent& event ); void OnHelp( wxCommandEvent& event );
void OnAddPlugin( wxCommandEvent& event ); void OnAddPlugin( wxCommandEvent& event );
void OnChoosePlugin( wxCommandEvent& event );
void OnRemovePlugin( wxCommandEvent& event ); void OnRemovePlugin( wxCommandEvent& event );
void OnEditPlugin( wxCommandEvent& event ); void OnEditPlugin( wxCommandEvent& event );
void OnCommandLineEdited( wxCommandEvent& event ); void OnCommandLineEdited( wxCommandEvent& event );
...@@ -183,6 +181,25 @@ private: ...@@ -183,6 +181,25 @@ private:
void pluginInit(); void pluginInit();
void installPluginsList(); 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. // Create and show DIALOG_BOM.
...@@ -215,12 +232,14 @@ DIALOG_BOM::~DIALOG_BOM() ...@@ -215,12 +232,14 @@ DIALOG_BOM::~DIALOG_BOM()
STRING_FORMATTER writer; STRING_FORMATTER writer;
writer.Print( 0, "(plugins" ); writer.Print( 0, "(plugins" );
for( unsigned ii = 0; ii < m_plugins.GetCount(); ii += 2 ) for( unsigned ii = 0; ii < m_plugins.GetCount(); ii += 2 )
{ {
writer.Print( 1, "(plugin %s (cmd %s))", writer.Print( 1, "(plugin %s (cmd %s))",
writer.Quotew( m_plugins[ii] ).c_str(), writer.Quotew( m_plugins[ii] ).c_str(),
writer.Quotew( m_plugins[ii+1] ).c_str() ); writer.Quotew( m_plugins[ii+1] ).c_str() );
} }
writer.Print( 0, ")" ); writer.Print( 0, ")" );
wxString list( FROM_UTF8( writer.GetString().c_str() ) ); wxString list( FROM_UTF8( writer.GetString().c_str() ) );
...@@ -272,6 +291,7 @@ void DIALOG_BOM::OnPluginSelected( wxCommandEvent& event ) ...@@ -272,6 +291,7 @@ void DIALOG_BOM::OnPluginSelected( wxCommandEvent& event )
pluginInit(); pluginInit();
} }
#include <wx/ffile.h>
void DIALOG_BOM::pluginInit() void DIALOG_BOM::pluginInit()
{ {
int ii = m_lbPlugins->GetSelection(); int ii = m_lbPlugins->GetSelection();
...@@ -285,9 +305,71 @@ void DIALOG_BOM::pluginInit() ...@@ -285,9 +305,71 @@ void DIALOG_BOM::pluginInit()
m_textCtrlName->SetValue( m_plugins[2 * ii] ); m_textCtrlName->SetValue( m_plugins[2 * ii] );
m_textCtrlCommand->SetValue( m_plugins[(2 * ii)+1] ); 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 * Function RunPlugin
* run the plugin command line * run the plugin command line
...@@ -350,8 +432,17 @@ void DIALOG_BOM::OnRemovePlugin( wxCommandEvent& event ) ...@@ -350,8 +432,17 @@ void DIALOG_BOM::OnRemovePlugin( wxCommandEvent& event )
*/ */
void DIALOG_BOM::OnAddPlugin( wxCommandEvent& event ) void DIALOG_BOM::OnAddPlugin( wxCommandEvent& event )
{ {
wxString cmdLine = choosePlugin();
if( cmdLine.IsEmpty() )
return;
// Creates a new plugin entry // 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() ) if( name.IsEmpty() )
return; return;
...@@ -361,22 +452,26 @@ void DIALOG_BOM::OnAddPlugin( wxCommandEvent& event ) ...@@ -361,22 +452,26 @@ void DIALOG_BOM::OnAddPlugin( wxCommandEvent& event )
{ {
if( name == m_plugins[ii] ) if( name == m_plugins[ii] )
{ {
wxMessageBox( _("This plugin already exists. Abort") ); wxMessageBox( _("This name already exists. Abort") );
return; return;
} }
} }
// Eppend the new plugin
m_plugins.Add( name ); m_plugins.Add( name );
m_plugins.Add( wxEmptyString ); m_plugins.Add( wxEmptyString );
m_lbPlugins->SetSelection( m_lbPlugins->GetCount() - 1 );
m_lbPlugins->Append( name ); m_lbPlugins->Append( name );
m_lbPlugins->SetSelection( m_lbPlugins->GetCount() - 1 ); m_lbPlugins->SetSelection( m_lbPlugins->GetCount() - 1 );
m_textCtrlCommand->SetValue( cmdLine );
pluginInit(); pluginInit();
} }
/* /*
* Browse plugin files, and set m_CommandStringCtrl field * Browse plugin files, and set m_CommandStringCtrl field
*/ */
void DIALOG_BOM::OnChoosePlugin( wxCommandEvent& event ) wxString DIALOG_BOM::choosePlugin()
{ {
wxString mask = wxT( "*" ); wxString mask = wxT( "*" );
#ifndef __WXMAC__ #ifndef __WXMAC__
...@@ -395,7 +490,7 @@ void DIALOG_BOM::OnChoosePlugin( wxCommandEvent& event ) ...@@ -395,7 +490,7 @@ void DIALOG_BOM::OnChoosePlugin( wxCommandEvent& event )
true true
); );
if( fullFileName.IsEmpty() ) if( fullFileName.IsEmpty() )
return; return wxEmptyString;
// Creates a default command line, // Creates a default command line,
// suitable to run the external tool xslproc or python // suitable to run the external tool xslproc or python
...@@ -414,44 +509,65 @@ void DIALOG_BOM::OnChoosePlugin( wxCommandEvent& event ) ...@@ -414,44 +509,65 @@ void DIALOG_BOM::OnChoosePlugin( wxCommandEvent& event )
else else
cmdLine.Printf(wxT("\"%s\""), GetChars( fullFileName ) ); 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. // Try to find the plugin name.
// This is possible if the name ends by .py or .xsl // This is possible if the name ends by .py or .xsl
cmdline = m_textCtrlCommand->GetValue();
int pos = -1; int pos = -1;
if( (pos = cmdline.Find( wxT(".py") )) != wxNOT_FOUND ) if( (pos = aCommand.Find( wxT(".py") )) != wxNOT_FOUND )
pos += 2; pos += 2;
else if( (pos = cmdline.Find( wxT(".xsl") )) != wxNOT_FOUND ) else if( (pos = aCommand.Find( wxT(".xsl") )) != wxNOT_FOUND )
pos += 3; pos += 3;
// the end of plugin name is at position pos. // the end of plugin name is at position pos.
if( pos > 0 ) if( pos > 0 )
{ {
// Be sure this is the end of the name: the next char is " or space // 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 == '\"' ) if( eos == ' '|| eos == '\"' )
{ {
// search for the starting point of the name // search for the starting point of the name
int jj = pos-1; int jj = pos-1;
while( jj >= 0 ) while( jj >= 0 )
if( cmdline[jj] != eos ) if( aCommand[jj] != eos )
jj--; jj--;
else else
break; break;
// extract the name // extract the name
if( jj >= 0 ) 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 ); AddDelimiterString( pluginName );
wxString editorname = Pgm().GetEditorName(); wxString editorname = Pgm().GetEditorName();
......
...@@ -16,7 +16,6 @@ BEGIN_EVENT_TABLE( DIALOG_BOM_BASE, DIALOG_SHIM ) ...@@ -16,7 +16,6 @@ BEGIN_EVENT_TABLE( DIALOG_BOM_BASE, DIALOG_SHIM )
EVT_BUTTON( wxID_CANCEL, DIALOG_BOM_BASE::_wxFB_OnCancelClick ) EVT_BUTTON( wxID_CANCEL, DIALOG_BOM_BASE::_wxFB_OnCancelClick )
EVT_BUTTON( ID_HELP, DIALOG_BOM_BASE::_wxFB_OnHelp ) EVT_BUTTON( ID_HELP, DIALOG_BOM_BASE::_wxFB_OnHelp )
EVT_BUTTON( ID_ADD_PLUGIN, DIALOG_BOM_BASE::_wxFB_OnAddPlugin ) 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( ID_REMOVEL_PLUGIN, DIALOG_BOM_BASE::_wxFB_OnRemovePlugin )
EVT_BUTTON( wxID_ANY, DIALOG_BOM_BASE::_wxFB_OnEditPlugin ) EVT_BUTTON( wxID_ANY, DIALOG_BOM_BASE::_wxFB_OnEditPlugin )
EVT_TEXT( ID_CMDLINE, DIALOG_BOM_BASE::_wxFB_OnCommandLineEdited ) 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 ...@@ -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 ); 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 ); 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 ); 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 ); 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 ...@@ -103,6 +99,13 @@ DIALOG_BOM_BASE::DIALOG_BOM_BASE( wxWindow* parent, wxWindowID id, const wxStrin
bMainSizer->Add( bbottomSizer, 0, wxEXPAND, 5 ); 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->SetSizer( bMainSizer );
this->Layout(); this->Layout();
......
This diff is collapsed.
...@@ -44,7 +44,6 @@ class DIALOG_BOM_BASE : public DIALOG_SHIM ...@@ -44,7 +44,6 @@ class DIALOG_BOM_BASE : public DIALOG_SHIM
void _wxFB_OnCancelClick( wxCommandEvent& event ){ OnCancelClick( event ); } void _wxFB_OnCancelClick( wxCommandEvent& event ){ OnCancelClick( event ); }
void _wxFB_OnHelp( wxCommandEvent& event ){ OnHelp( event ); } void _wxFB_OnHelp( wxCommandEvent& event ){ OnHelp( event ); }
void _wxFB_OnAddPlugin( wxCommandEvent& event ){ OnAddPlugin( event ); } void _wxFB_OnAddPlugin( wxCommandEvent& event ){ OnAddPlugin( event ); }
void _wxFB_OnChoosePlugin( wxCommandEvent& event ){ OnChoosePlugin( event ); }
void _wxFB_OnRemovePlugin( wxCommandEvent& event ){ OnRemovePlugin( event ); } void _wxFB_OnRemovePlugin( wxCommandEvent& event ){ OnRemovePlugin( event ); }
void _wxFB_OnEditPlugin( wxCommandEvent& event ){ OnEditPlugin( event ); } void _wxFB_OnEditPlugin( wxCommandEvent& event ){ OnEditPlugin( event ); }
void _wxFB_OnCommandLineEdited( wxCommandEvent& event ){ OnCommandLineEdited( event ); } void _wxFB_OnCommandLineEdited( wxCommandEvent& event ){ OnCommandLineEdited( event ); }
...@@ -57,7 +56,6 @@ class DIALOG_BOM_BASE : public DIALOG_SHIM ...@@ -57,7 +56,6 @@ class DIALOG_BOM_BASE : public DIALOG_SHIM
ID_CREATE_BOM, ID_CREATE_BOM,
ID_HELP, ID_HELP,
ID_ADD_PLUGIN, ID_ADD_PLUGIN,
wxID_BROWSE_PLUGINS,
ID_REMOVEL_PLUGIN, ID_REMOVEL_PLUGIN,
ID_CMDLINE ID_CMDLINE
}; };
...@@ -71,11 +69,12 @@ class DIALOG_BOM_BASE : public DIALOG_SHIM ...@@ -71,11 +69,12 @@ class DIALOG_BOM_BASE : public DIALOG_SHIM
wxButton* m_buttonHelp; wxButton* m_buttonHelp;
wxStaticLine* m_staticline2; wxStaticLine* m_staticline2;
wxButton* m_buttonAddPlugin; wxButton* m_buttonAddPlugin;
wxButton* m_buttonBrowsePlugin;
wxButton* m_buttonDelPlugin; wxButton* m_buttonDelPlugin;
wxButton* m_buttonEdit; wxButton* m_buttonEdit;
wxStaticText* m_staticTextCmd; wxStaticText* m_staticTextCmd;
wxTextCtrl* m_textCtrlCommand; wxTextCtrl* m_textCtrlCommand;
wxStaticText* m_staticTextInfo;
wxTextCtrl* m_Messages;
// Virtual event handlers, overide them in your derived class // Virtual event handlers, overide them in your derived class
virtual void OnPluginSelected( wxCommandEvent& event ) { event.Skip(); } virtual void OnPluginSelected( wxCommandEvent& event ) { event.Skip(); }
...@@ -84,7 +83,6 @@ class DIALOG_BOM_BASE : public DIALOG_SHIM ...@@ -84,7 +83,6 @@ class DIALOG_BOM_BASE : public DIALOG_SHIM
virtual void OnCancelClick( wxCommandEvent& event ) { event.Skip(); } virtual void OnCancelClick( wxCommandEvent& event ) { event.Skip(); }
virtual void OnHelp( wxCommandEvent& event ) { event.Skip(); } virtual void OnHelp( wxCommandEvent& event ) { event.Skip(); }
virtual void OnAddPlugin( 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 OnRemovePlugin( wxCommandEvent& event ) { event.Skip(); }
virtual void OnEditPlugin( wxCommandEvent& event ) { event.Skip(); } virtual void OnEditPlugin( wxCommandEvent& event ) { event.Skip(); }
virtual void OnCommandLineEdited( wxCommandEvent& event ) { event.Skip(); } virtual void OnCommandLineEdited( wxCommandEvent& event ) { event.Skip(); }
...@@ -92,7 +90,7 @@ class DIALOG_BOM_BASE : public DIALOG_SHIM ...@@ -92,7 +90,7 @@ class DIALOG_BOM_BASE : public DIALOG_SHIM
public: 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(); ~DIALOG_BOM_BASE();
}; };
......
This diff is collapsed.
...@@ -381,7 +381,7 @@ bool SCH_EDIT_FRAME::WriteNetListFile( NETLIST_OBJECT_LIST * aConnectedItemsList ...@@ -381,7 +381,7 @@ bool SCH_EDIT_FRAME::WriteNetListFile( NETLIST_OBJECT_LIST * aConnectedItemsList
NETLIST_EXPORT_TOOL helper( aConnectedItemsList, Prj().SchLibs() ); 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 ) ) if( (aFormat == NET_TYPE_PCBNEW) && (aNetlistOptions & NET_PCBNEW_USE_NEW_FORMAT ) )
open_file = false; open_file = false;
...@@ -390,7 +390,7 @@ bool SCH_EDIT_FRAME::WriteNetListFile( NETLIST_OBJECT_LIST * aConnectedItemsList ...@@ -390,7 +390,7 @@ bool SCH_EDIT_FRAME::WriteNetListFile( NETLIST_OBJECT_LIST * aConnectedItemsList
if( ( f = wxFopen( aFullFileName, wxT( "wt" ) ) ) == NULL ) if( ( f = wxFopen( aFullFileName, wxT( "wt" ) ) ) == NULL )
{ {
wxString msg; wxString msg;
msg.Printf( _( "Failed to create file <%s>" ), msg.Printf( _( "Failed to create file '%s'" ),
GetChars( aFullFileName ) ); GetChars( aFullFileName ) );
DisplayError( this, msg ); DisplayError( this, msg );
return false; return false;
......
...@@ -19,6 +19,14 @@ ...@@ -19,6 +19,14 @@
in the filename. in the filename.
--> -->
<!--
@package
Generate a Tab delimited list (csv file type).
One component per line
Fields are
Ref,Value, Footprint, Datasheet, Field5, Field4, price
-->
<!DOCTYPE xsl:stylesheet [ <!DOCTYPE xsl:stylesheet [
<!ENTITY nl "&#xd;&#xa;"> <!--new line CR, LF, or LF, your choice --> <!ENTITY nl "&#xd;&#xa;"> <!--new line CR, LF, or LF, your choice -->
]> ]>
......
...@@ -7,6 +7,14 @@ ...@@ -7,6 +7,14 @@
How to use: How to use:
Eeschema.pdf: chapter 14 Eeschema.pdf: chapter 14
--> -->
<!--
@package
Generate a comma separated value BOM list (csv file type).
Components are sorted by value
One component per line
Fields are
Quantity, 'Part name', Description, lib
-->
<!DOCTYPE xsl:stylesheet [ <!DOCTYPE xsl:stylesheet [
<!ENTITY nl "&#xd;&#xa;"> <!--new line CR, LF --> <!ENTITY nl "&#xd;&#xa;"> <!--new line CR, LF -->
...@@ -18,20 +26,18 @@ ...@@ -18,20 +26,18 @@
<!-- for each component --> <!-- for each component -->
<xsl:template match="libpart"> <xsl:template match="libpart">
<!-- <!-- -->
<xsl:value-of select="count(//comp/libsource/@part[@part])"/><xsl:text>,</xsl:text> <xsl:value-of select="count(//comp/libsource/@part[@part])"/><xsl:text>,"</xsl:text>
--> <xsl:value-of select="@part"/><xsl:text>","</xsl:text>
<xsl:value-of select="description"/><xsl:text>","</xsl:text>
<xsl:value-of select="@part"/><xsl:text>,</xsl:text>
<xsl:value-of select="description"/><xsl:text>,</xsl:text>
<xsl:value-of select="@lib"/> <xsl:value-of select="@lib"/>
<xsl:text>&nl;</xsl:text> <xsl:text>"&nl;</xsl:text>
</xsl:template> </xsl:template>
<xsl:template match="/export"> <xsl:template match="/export">
<xsl:text>qty,partname,description,lib&nl;</xsl:text> <xsl:text>Qty,partname,description,lib&nl;</xsl:text>
<xsl:apply-templates select="libparts/libpart"/> <xsl:apply-templates select="libparts/libpart"/>
</xsl:template> </xsl:template>
......
...@@ -90,9 +90,6 @@ BEGIN_EVENT_TABLE( GERBVIEW_FRAME, EDA_DRAW_FRAME ) ...@@ -90,9 +90,6 @@ BEGIN_EVENT_TABLE( GERBVIEW_FRAME, EDA_DRAW_FRAME )
EVT_MENU( wxID_HELP, EDA_DRAW_FRAME::GetKicadHelp ) EVT_MENU( wxID_HELP, EDA_DRAW_FRAME::GetKicadHelp )
EVT_MENU( wxID_ABOUT, EDA_DRAW_FRAME::GetKicadAbout ) 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_UNDO, GERBVIEW_FRAME::Process_Special_Functions )
EVT_TOOL( wxID_PRINT, GERBVIEW_FRAME::ToPrinter ) EVT_TOOL( wxID_PRINT, GERBVIEW_FRAME::ToPrinter )
EVT_COMBOBOX( ID_TOOLBARH_GERBVIEW_SELECT_ACTIVE_LAYER, EVT_COMBOBOX( ID_TOOLBARH_GERBVIEW_SELECT_ACTIVE_LAYER,
...@@ -145,9 +142,6 @@ void GERBVIEW_FRAME::Process_Special_Functions( wxCommandEvent& event ) ...@@ -145,9 +142,6 @@ void GERBVIEW_FRAME::Process_Special_Functions( wxCommandEvent& event )
switch( id ) switch( id )
{ {
case wxID_CUT:
case wxID_COPY:
case ID_POPUP_DELETE_BLOCK:
case ID_POPUP_PLACE_BLOCK: case ID_POPUP_PLACE_BLOCK:
case ID_POPUP_ZOOM_BLOCK: case ID_POPUP_ZOOM_BLOCK:
break; break;
...@@ -219,12 +213,6 @@ void GERBVIEW_FRAME::Process_Special_Functions( wxCommandEvent& event ) ...@@ -219,12 +213,6 @@ void GERBVIEW_FRAME::Process_Special_Functions( wxCommandEvent& event )
HandleBlockEnd( &dc ); HandleBlockEnd( &dc );
break; break;
case ID_POPUP_DELETE_BLOCK:
GetScreen()->m_BlockLocate.SetCommand( BLOCK_DELETE );
GetScreen()->m_BlockLocate.SetMessageBlock( this );
HandleBlockEnd( &dc );
break;
default: default:
wxFAIL_MSG( wxT( "GERBVIEW_FRAME::Process_Special_Functions error" ) ); wxFAIL_MSG( wxT( "GERBVIEW_FRAME::Process_Special_Functions error" ) );
break; break;
......
...@@ -80,7 +80,7 @@ void GERBVIEW_FRAME::Files_io( wxCommandEvent& event ) ...@@ -80,7 +80,7 @@ void GERBVIEW_FRAME::Files_io( wxCommandEvent& event )
break; break;
case ID_GERBVIEW_ERASE_ALL: case ID_GERBVIEW_ERASE_ALL:
Clear_DrawLayers( true ); Clear_DrawLayers( false );
Zoom_Automatique( false ); Zoom_Automatique( false );
m_canvas->Refresh(); m_canvas->Refresh();
ClearMsgPanel(); ClearMsgPanel();
......
...@@ -24,7 +24,6 @@ ...@@ -24,7 +24,6 @@
#include <fctsys.h> #include <fctsys.h>
#include <class_drawpanel.h> #include <class_drawpanel.h>
#include <confirm.h>
#include <id.h> #include <id.h>
#include <gerbview.h> #include <gerbview.h>
...@@ -75,8 +74,6 @@ bool GERBVIEW_FRAME::OnRightClick( const wxPoint& aPosition, wxMenu* PopMenu ) ...@@ -75,8 +74,6 @@ bool GERBVIEW_FRAME::OnRightClick( const wxPoint& aPosition, wxMenu* PopMenu )
PopMenu->AppendSeparator(); PopMenu->AppendSeparator();
AddMenuItem( PopMenu, ID_POPUP_PLACE_BLOCK, AddMenuItem( PopMenu, ID_POPUP_PLACE_BLOCK,
_( "Place Block" ), KiBitmap( checked_ok_xpm ) ); _( "Place Block" ), KiBitmap( checked_ok_xpm ) );
AddMenuItem( PopMenu, ID_POPUP_DELETE_BLOCK,
_( "Delete Block (ctrl + drag mouse)" ), KiBitmap( delete_xpm ) );
} }
else else
{ {
......
...@@ -71,7 +71,7 @@ enum DSN_SYNTAX_T { ...@@ -71,7 +71,7 @@ enum DSN_SYNTAX_T {
/** /**
* Class DLEXER * Class DSNLEXER
* implements a lexical analyzer for the SPECCTRA DSN file format. It * implements a lexical analyzer for the SPECCTRA DSN file format. It
* reads lexical tokens from the current LINE_READER through the NextTok() * reads lexical tokens from the current LINE_READER through the NextTok()
* function. * function.
...@@ -215,6 +215,16 @@ public: ...@@ -215,6 +215,16 @@ public:
virtual ~DSNLEXER(); 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 * Function SetSpecctraMode
* changes the behavior of this lexer into or out of "specctra mode". If * changes the behavior of this lexer into or out of "specctra mode". If
......
...@@ -580,7 +580,10 @@ void D_PAD:: TransformShapeWithClearanceToPolygon( CPOLYGONS_LIST& aCornerBuffer ...@@ -580,7 +580,10 @@ void D_PAD:: TransformShapeWithClearanceToPolygon( CPOLYGONS_LIST& aCornerBuffer
ClipperLib::Paths shapeWithClearance; ClipperLib::Paths shapeWithClearance;
for( int ii = 0; ii < 4; ii++ ) for( int ii = 0; ii < 4; ii++ )
{
corners[ii] += PadShapePos;
outline << ClipperLib::IntPoint( corners[ii].x, corners[ii].y ); outline << ClipperLib::IntPoint( corners[ii].x, corners[ii].y );
}
ClipperLib::ClipperOffset offset_engine; ClipperLib::ClipperOffset offset_engine;
// Prepare an offset (inflate) transform, with edges connected by arcs // Prepare an offset (inflate) transform, with edges connected by arcs
...@@ -600,19 +603,7 @@ void D_PAD:: TransformShapeWithClearanceToPolygon( CPOLYGONS_LIST& aCornerBuffer ...@@ -600,19 +603,7 @@ void D_PAD:: TransformShapeWithClearanceToPolygon( CPOLYGONS_LIST& aCornerBuffer
offset_engine.Execute( shapeWithClearance, rounding_radius ); offset_engine.Execute( shapeWithClearance, rounding_radius );
// get new outline (only one polygon is expected) // get new outline (only one polygon is expected)
// For info, ClipperLib uses long long to handle integer coordinates aCornerBuffer.ImportFrom( shapeWithClearance );
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();
} }
break; break;
} }
...@@ -1008,7 +999,6 @@ void CreateThermalReliefPadPolygon( CPOLYGONS_LIST& aCornerBuffer, ...@@ -1008,7 +999,6 @@ void CreateThermalReliefPadPolygon( CPOLYGONS_LIST& aCornerBuffer,
double angle = aPad.GetOrientation(); double angle = aPad.GetOrientation();
int rounding_radius = KiROUND( aThermalGap * aCorrectionFactor ); // Corner rounding radius int rounding_radius = KiROUND( aThermalGap * aCorrectionFactor ); // Corner rounding radius
double angle_pg; // Polygon increment angle
for( int i = 0; i < aCircleToSegmentsCount / 4 + 1; i++ ) for( int i = 0; i < aCircleToSegmentsCount / 4 + 1; i++ )
{ {
...@@ -1016,7 +1006,7 @@ void CreateThermalReliefPadPolygon( CPOLYGONS_LIST& aCornerBuffer, ...@@ -1016,7 +1006,7 @@ void CreateThermalReliefPadPolygon( CPOLYGONS_LIST& aCornerBuffer,
// Start at half increment offset // Start at half increment offset
RotatePoint( &corner_position, 1800.0 / aCircleToSegmentsCount ); RotatePoint( &corner_position, 1800.0 / aCircleToSegmentsCount );
angle_pg = i * delta; double angle_pg = i * delta;
RotatePoint( &corner_position, angle_pg ); // Rounding vector rotation RotatePoint( &corner_position, angle_pg ); // Rounding vector rotation
corner_position -= aPad.GetSize() / 2; // Rounding vector + Pad corner offset corner_position -= aPad.GetSize() / 2; // Rounding vector + Pad corner offset
......
...@@ -898,3 +898,14 @@ wxString ZONE_CONTAINER::GetSelectMenuText() const ...@@ -898,3 +898,14 @@ wxString ZONE_CONTAINER::GetSelectMenuText() const
return msg; 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 );
}
...@@ -305,6 +305,14 @@ public: ...@@ -305,6 +305,14 @@ public:
*/ */
void CopyPolygonsFromKiPolygonListToFilledPolysList( KI_POLYGON_SET& aKiPolyList ); 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 * Function CopyPolygonsFromFilledPolysListToKiPolygonList
* Copy polygons from m_FilledPolysList to aKiPolyList * Copy polygons from m_FilledPolysList to aKiPolyList
......
...@@ -1938,14 +1938,39 @@ void EAGLE_PLUGIN::packageWire( MODULE* aModule, CPTREE& aTree ) const ...@@ -1938,14 +1938,39 @@ void EAGLE_PLUGIN::packageWire( MODULE* aModule, CPTREE& aTree ) const
wxPoint end( kicad_x( w.x2 ), kicad_y( w.y2 ) ); wxPoint end( kicad_x( w.x2 ), kicad_y( w.y2 ) );
int width = kicad( w.width ); int width = kicad( w.width );
EDGE_MODULE* dwg = new EDGE_MODULE( aModule, S_SEGMENT ); EDGE_MODULE* dwg;
aModule->GraphicalItems().PushBack( dwg ); if( !w.curve )
{
dwg = new EDGE_MODULE( aModule, S_SEGMENT );
dwg->SetStart0( start ); dwg->SetStart0( start );
dwg->SetEnd0( end ); 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->SetLayer( layer );
dwg->SetWidth( width ); dwg->SetWidth( width );
aModule->GraphicalItems().PushBack( dwg );
} }
} }
......
...@@ -541,6 +541,9 @@ void PCB_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) ...@@ -541,6 +541,9 @@ void PCB_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event )
break; break;
case ID_POPUP_PCB_DELETE_ZONE_CONTAINER: 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: case ID_POPUP_PCB_DELETE_ZONE_CUTOUT:
m_canvas->MoveCursorToCrossHair(); m_canvas->MoveCursorToCrossHair();
{ {
......
...@@ -41,9 +41,7 @@ ...@@ -41,9 +41,7 @@
#include <class_module.h> #include <class_module.h>
/** /* Event handler for tracks and vias size selection (and some options)
* Function Tracks_and_Vias_Size_Event
* Event handler for tracks and vias size selection (and some options)
* relative to toolbars and popup events * relative to toolbars and popup events
*/ */
void PCB_EDIT_FRAME::Tracks_and_Vias_Size_Event( wxCommandEvent& event ) void PCB_EDIT_FRAME::Tracks_and_Vias_Size_Event( wxCommandEvent& event )
...@@ -51,7 +49,7 @@ void PCB_EDIT_FRAME::Tracks_and_Vias_Size_Event( wxCommandEvent& event ) ...@@ -51,7 +49,7 @@ void PCB_EDIT_FRAME::Tracks_and_Vias_Size_Event( wxCommandEvent& event )
int ii; int ii;
int id = event.GetId(); int id = event.GetId();
/* Note: none of these events require aborting the current command (if any) /* Note: none of these events require aborting the current command (if any)
* (like move, edit or block command) * (like move, edit or block command)
* so we do not test for a current command in progress and call * so we do not test for a current command in progress and call
* m_canvas->m_endMouseCaptureCallback( m_canvas, &dc ); * m_canvas->m_endMouseCaptureCallback( m_canvas, &dc );
...@@ -142,5 +140,7 @@ void PCB_EDIT_FRAME::Tracks_and_Vias_Size_Event( wxCommandEvent& event ) ...@@ -142,5 +140,7 @@ void PCB_EDIT_FRAME::Tracks_and_Vias_Size_Event( wxCommandEvent& event )
}*/ }*/
//+hp //+hp
//Refresh canvas, that we can see changes instantly. I use this because it dont,t throw mouse up-left corner. //Refresh canvas, that we can see changes instantly. I use this because it dont,t throw mouse up-left corner.
if( m_canvas->IsMouseCaptured() )
m_canvas->Refresh(); m_canvas->Refresh();
} }
...@@ -126,6 +126,10 @@ static EDA_HOTKEY HkCanvasOpenGL( wxT( "Switch to OpenGL Canvas" ), ...@@ -126,6 +126,10 @@ static EDA_HOTKEY HkCanvasOpenGL( wxT( "Switch to OpenGL Canvas" ),
static EDA_HOTKEY HkCanvasCairo( wxT( "Switch to Cairo Canvas" ), static EDA_HOTKEY HkCanvasCairo( wxT( "Switch to Cairo Canvas" ),
HK_CANVAS_CAIRO, WXK_F12 ); 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 */ /* Fit on Screen */
#if !defined( __WXMAC__ ) #if !defined( __WXMAC__ )
static EDA_HOTKEY HkZoomAuto( wxT( "Zoom Auto" ), HK_ZOOM_AUTO, WXK_HOME ); static EDA_HOTKEY HkZoomAuto( wxT( "Zoom Auto" ), HK_ZOOM_AUTO, WXK_HOME );
...@@ -289,6 +293,7 @@ EDA_HOTKEY* board_edit_Hotkey_List[] = ...@@ -289,6 +293,7 @@ EDA_HOTKEY* board_edit_Hotkey_List[] =
&HkRecordMacros8, &HkCallMacros8, &HkRecordMacros9, &HkCallMacros9, &HkRecordMacros8, &HkCallMacros8, &HkRecordMacros9, &HkCallMacros9,
&HkSwitchHighContrastMode, &HkSwitchHighContrastMode,
&HkCanvasDefault, &HkCanvasCairo, &HkCanvasOpenGL, &HkCanvasDefault, &HkCanvasCairo, &HkCanvasOpenGL,
&HkZoneFillOrRefill, &HkZoneRemoveFilled,
NULL NULL
}; };
......
...@@ -114,7 +114,9 @@ enum hotkey_id_commnand { ...@@ -114,7 +114,9 @@ enum hotkey_id_commnand {
HK_CANVAS_OPENGL, HK_CANVAS_OPENGL,
HK_CANVAS_CAIRO, HK_CANVAS_CAIRO,
HK_LEFT_CLICK, 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 // Full list of hotkey descriptors for board editor and footprint editor
......
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
#include <pcbnew.h> #include <pcbnew.h>
#include <pcbnew_id.h> #include <pcbnew_id.h>
#include <hotkeys.h> #include <hotkeys.h>
#include <class_zone.h>
/* How to add a new hotkey: /* How to add a new hotkey:
* see hotkeys.cpp * see hotkeys.cpp
...@@ -566,6 +567,13 @@ bool PCB_EDIT_FRAME::OnHotKey( wxDC* aDC, int aHotkeyCode, const wxPoint& aPosit ...@@ -566,6 +567,13 @@ bool PCB_EDIT_FRAME::OnHotKey( wxDC* aDC, int aHotkeyCode, const wxPoint& aPosit
case HK_CANVAS_DEFAULT: case HK_CANVAS_DEFAULT:
evt_type = ID_MENU_CANVAS_DEFAULT; evt_type = ID_MENU_CANVAS_DEFAULT;
break; 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 ) if( evt_type != 0 )
......
...@@ -319,10 +319,14 @@ bool PCB_EDIT_FRAME::OnRightClick( const wxPoint& aMousePos, wxMenu* aPopMenu ) ...@@ -319,10 +319,14 @@ bool PCB_EDIT_FRAME::OnRightClick( const wxPoint& aMousePos, wxMenu* aPopMenu )
if( GetBoard()->m_ZoneDescriptorList.size() > 0 ) if( GetBoard()->m_ZoneDescriptorList.size() > 0 )
{ {
aPopMenu->AppendSeparator(); 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, 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, 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(); aPopMenu->AppendSeparator();
} }
......
...@@ -1135,12 +1135,14 @@ void PCB_PARSER::parseSetup() throw( IO_ERROR, PARSE_ERROR ) ...@@ -1135,12 +1135,14 @@ void PCB_PARSER::parseSetup() throw( IO_ERROR, PARSE_ERROR )
{ {
PCB_PLOT_PARAMS plotParams; PCB_PLOT_PARAMS plotParams;
PCB_PLOT_PARAMS_PARSER parser( reader ); 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 ); 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(). m_board->SetPlotOptions( plotParams );
NextTok();
} }
break; break;
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/ */
#include <wx/wx.h> //#include <wx/wx.h>
#include <pcb_plot_params_parser.h> #include <pcb_plot_params_parser.h>
#include <pcb_plot_params.h> #include <pcb_plot_params.h>
#include <layers_id_colors_and_visibility.h> #include <layers_id_colors_and_visibility.h>
......
...@@ -773,12 +773,25 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, ...@@ -773,12 +773,25 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter,
zone->TransformOutlinesShapeWithClearanceToPolygon( bufferPolys, zone->TransformOutlinesShapeWithClearanceToPolygon( bufferPolys,
inflate, true ); 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: // 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 // having a thickness < aMinThickness
// 2 - deflate resulting areas by aMinThickness/2 // 2 - deflate resulting polygons by aMinThickness/2
KI_POLYGON_SET areasToMerge; KI_POLYGON_SET areasToMerge;
bufferPolys.ExportTo( areasToMerge ); bufferPolys.ExportTo( areasToMerge );
KI_POLYGON_SET initialAreas; KI_POLYGON_SET initialAreas;
...@@ -788,29 +801,44 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, ...@@ -788,29 +801,44 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter,
// = aMinThickness/2, shapes too close ( dist < aMinThickness ) // = aMinThickness/2, shapes too close ( dist < aMinThickness )
// will be merged, because they are overlapping // will be merged, because they are overlapping
KI_POLYGON_SET areas; KI_POLYGON_SET areas;
areas |= areasToMerge; areas |= areasToMerge; // Populates with merged polygons
// Deflate: remove the extra margin, to create the actual shapes // Deflate: remove the extra margin, to create the actual shapes
// Here I am using polygon:resize, because this function creates better shapes // Here I am using polygon:resize, because this function creates better shapes
// than deflate algo. // than deflate algo.
// Use here deflate with arc creation and 18 segments per circle to create arcs // Use here deflate made by Clipper, because:
// In boost polygon (at least v 1.54 and previous) in very rare cases resize crashes // Clipper is (by far) faster and better, event using arcs to deflate shapes
// with 16 segments (perhaps related to 45 degrees pads). So using 18 segments // boost::polygon < 1.56 polygon resize function sometimes crashes when deflating using arcs
// is a workaround to try to avoid these crashes // boost::polygon >=1.56 polygon resize function just does not work
areas = resize( areas, -inflate , true, 18 ); // 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
// Resize slightly changes shapes. So *ensure* initial shapes are kept CPOLYGONS_LIST tmp;
tmp.ImportFrom( areas );
// 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; 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 ); zone.CopyPolygonsFromKiPolygonListToFilledPolysList( areas );
itemplotter.PlotFilledAreas( &zone ); itemplotter.PlotFilledAreas( &zone );
} }
......
...@@ -29,7 +29,6 @@ ...@@ -29,7 +29,6 @@
*/ */
#include <fctsys.h> #include <fctsys.h>
//#include <pgm_base.h>
#include <kiface_i.h> #include <kiface_i.h>
#include <class_drawpanel.h> #include <class_drawpanel.h>
#include <confirm.h> #include <confirm.h>
......
...@@ -13,7 +13,7 @@ from sys import argv,exit ...@@ -13,7 +13,7 @@ from sys import argv,exit
if len(argv)<2: if len(argv)<2:
print "usage:" print "usage:"
print " fixswigimports.py file.py" print " fix_swig_imports.py file.py"
print "" print ""
print " will fix the swig import code for working inside KiCad" print " will fix the swig import code for working inside KiCad"
print " where it happended that the external _pcbnew.so/dll was" print " where it happended that the external _pcbnew.so/dll was"
...@@ -52,7 +52,7 @@ if doneOk: ...@@ -52,7 +52,7 @@ if doneOk:
print "swig_import_helper fixed for",filename print "swig_import_helper fixed for",filename
else: else:
print "Error: the swig import helper was not fixed, check",filename 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) exit(2)
......
bom_?.py are some python scripts which read a generic xml netlist from eeschema, bom_?.py are some python scripts which read a generic xml netlist from eeschema,
and create a bom. 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 and parse this generic xml netlist and create the corresponding data
used to build the bom. used to build the bom.
...@@ -12,3 +12,27 @@ python bom_example?.py <netlist name> <bom list netname> ...@@ -12,3 +12,27 @@ python bom_example?.py <netlist name> <bom list netname>
See Eeschema doc, chapter 14 for info about the generic xml netlist format, 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. 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
...@@ -4,6 +4,15 @@ ...@@ -4,6 +4,15 @@
# Example: Sorted and Grouped HTML BOM with more advanced grouping # 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 from __future__ import print_function
# Import the KiCad python helper module and the csv formatter # Import the KiCad python helper module and the csv formatter
...@@ -74,8 +83,9 @@ net = kicad_netlist_reader.netlist(sys.argv[1]) ...@@ -74,8 +83,9 @@ net = kicad_netlist_reader.netlist(sys.argv[1])
try: try:
f = open(sys.argv[2], 'w') f = open(sys.argv[2], 'w')
except IOError: except IOError:
e = "Can't open output file for writing: " + sys.argv[2]
print(__file__, ":", e, file=sys.stderr) print(__file__, ":", e, file=sys.stderr)
f = stdout f = sys.stdout
# Output a set of rows for a header providing general information # Output a set of rows for a header providing general information
html = html.replace('<!--SOURCE-->', net.getSource()) html = html.replace('<!--SOURCE-->', net.getSource())
......
# #
# Example python script to generate a BOM from a KiCad generic netlist # 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 from __future__ import print_function
...@@ -20,8 +26,9 @@ net = kicad_netlist_reader.netlist(sys.argv[1]) ...@@ -20,8 +26,9 @@ net = kicad_netlist_reader.netlist(sys.argv[1])
try: try:
f = open(sys.argv[2], 'w') f = open(sys.argv[2], 'w')
except IOError: except IOError:
print(__file__, ":", e, file=sys.stderr) e = "Can't open output file for writing: " + sys.argv[2]
f = stdout print(__file__, ":", e, sys.stderr)
f = sys.stdout
# Create a new csv writer object to use as the output formatter, although we # Create a new csv writer object to use as the output formatter, although we
# are created a tab delimited list instead! # are created a tab delimited list instead!
......
...@@ -4,6 +4,15 @@ ...@@ -4,6 +4,15 @@
# Example: Ungrouped (One component per row) CSV output # 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 from __future__ import print_function
# Import the KiCad python helper module # Import the KiCad python helper module
...@@ -20,8 +29,9 @@ net = kicad_netlist_reader.netlist(sys.argv[1]) ...@@ -20,8 +29,9 @@ net = kicad_netlist_reader.netlist(sys.argv[1])
try: try:
f = open(sys.argv[2], 'w') f = open(sys.argv[2], 'w')
except IOError: except IOError:
print(__file__, ":", e, file=sys.stderr) e = "Can't open output file for writing: " + sys.argv[2]
f = stdout print( __file__, ":", e, sys.stderr )
f = sys.stdout
# Create a new csv writer object to use as the output formatter # Create a new csv writer object to use as the output formatter
out = csv.writer(f, lineterminator='\n', delimiter=',', quotechar="\"", quoting=csv.QUOTE_ALL) out = csv.writer(f, lineterminator='\n', delimiter=',', quotechar="\"", quoting=csv.QUOTE_ALL)
......
...@@ -27,7 +27,7 @@ try: ...@@ -27,7 +27,7 @@ try:
f = open(sys.argv[2], 'w') f = open(sys.argv[2], 'w')
except IOError: except IOError:
e = "Can't open output file for writing: " + sys.argv[2] 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 f = sys.stdout
# subset the components to those wanted in the BOM, controlled # subset the components to those wanted in the BOM, controlled
...@@ -46,7 +46,7 @@ columnset = compfields | partfields # union ...@@ -46,7 +46,7 @@ columnset = compfields | partfields # union
columns = ['Item', 'Qty', 'Reference(s)', 'Value', 'LibPart', 'Footprint', 'Datasheet'] + sorted(list(columnset)) columns = ['Item', 'Qty', 'Reference(s)', 'Value', 'LibPart', 'Footprint', 'Datasheet'] + sorted(list(columnset))
# Create a new csv writer object to use as the output formatter # 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: # override csv.writer's writerow() to support utf8 encoding:
def writerow( acsvwriter, columns ): def writerow( acsvwriter, columns ):
......
#
# 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")])
...@@ -4,6 +4,15 @@ ...@@ -4,6 +4,15 @@
# Example: Sorted and Grouped HTML BOM with more advanced grouping # 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 from __future__ import print_function
# Import the KiCad python helper module and the csv formatter # Import the KiCad python helper module and the csv formatter
...@@ -74,8 +83,9 @@ net = kicad_netlist_reader.netlist(sys.argv[1]) ...@@ -74,8 +83,9 @@ net = kicad_netlist_reader.netlist(sys.argv[1])
try: try:
f = open(sys.argv[2], 'w') f = open(sys.argv[2], 'w')
except IOError: except IOError:
print(__file__, ":", e, file=sys.stderr) e = "Can't open output file for writing: " + sys.argv[2]
f = stdout print( __file__, ":", e, sys.stderr )
f = sys.stdout
components = net.getInterestingComponents() components = net.getInterestingComponents()
......
...@@ -3,6 +3,13 @@ ...@@ -3,6 +3,13 @@
# #
# Example: Sorted and Grouped HTML BOM # 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 from __future__ import print_function
...@@ -39,8 +46,9 @@ net = kicad_netlist_reader.netlist(sys.argv[1]) ...@@ -39,8 +46,9 @@ net = kicad_netlist_reader.netlist(sys.argv[1])
try: try:
f = open(sys.argv[2], 'w') f = open(sys.argv[2], 'w')
except IOError: except IOError:
e = "Can't open output file for writing: " + sys.argv[2]
print(__file__, ":", e, file=sys.stderr) print(__file__, ":", e, file=sys.stderr)
f = stdout f = sys.stdout
components = net.getInterestingComponents() components = net.getInterestingComponents()
...@@ -51,7 +59,8 @@ html = html.replace('<!--TOOL-->', net.getTool()) ...@@ -51,7 +59,8 @@ html = html.replace('<!--TOOL-->', net.getTool())
html = html.replace('<!--COMPCOUNT-->', "<b>Component Count:</b>" + \ html = html.replace('<!--COMPCOUNT-->', "<b>Component Count:</b>" + \
str(len(components))) str(len(components)))
row = "<tr><th style='width:640px'>Ref</th>" + "<th>Qnty</th>" row = "<tr><th style='width:640px'>Ref</th>"
row += "<th>Qnty</th>"
row += "<th>Value</th>" + "<th>Part</th>" + "<th>Datasheet</th>" row += "<th>Value</th>" + "<th>Part</th>" + "<th>Datasheet</th>"
row += "<th>Description</th>" + "<th>Vendor</th></tr>" row += "<th>Description</th>" + "<th>Vendor</th></tr>"
...@@ -74,10 +83,11 @@ for group in grouped: ...@@ -74,10 +83,11 @@ for group in grouped:
c = component c = component
row = "<tr><td>" + refs +"</td><td>" + str(len(group)) row = "<tr><td>" + refs +"</td><td>" + str(len(group))
row += "</td><td>" + c.getValue() + "</td><td>" + c.getLibName() + ":" row += "</td><td>" + c.getValue()
row += c.getPartName() + "</td><td>" + c.getDatasheet() + "</td><td>" row += "</td><td>" + c.getLibName() + ":" + c.getPartName()
row += c.getDescription() + "</td><td>" + c.getField("Vendor") row += "</td><td>" + c.getDatasheet()
row += "</td></tr>" row += "</td><td>" + c.getDescription()
row += "</td><td>" + c.getField("Vendor")+ "</td></tr>"
html = html.replace('<!--TABLEROW-->', row + "<!--TABLEROW-->") html = html.replace('<!--TABLEROW-->', row + "<!--TABLEROW-->")
......
...@@ -7,6 +7,15 @@ ...@@ -7,6 +7,15 @@
# is due to be deprecated in 3.0+ soon # 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 from __future__ import print_function
import sys import sys
import xml.sax as sax import xml.sax as sax
......
...@@ -21,7 +21,8 @@ net = kicad_netlist_reader.netlist(sys.argv[1]) ...@@ -21,7 +21,8 @@ net = kicad_netlist_reader.netlist(sys.argv[1])
try: try:
f = open(sys.argv[2], 'w') f = open(sys.argv[2], 'w')
except IOError: except IOError:
print( __file__, ":", e, file=sys.stderr) e = "Can't open output file for writing: " + sys.argv[2]
f = stdout print( __file__, ":", e, sys.stderr)
f = sys.stdout
print(net.formatXML(), file=f) print(net.formatXML(), file=f)
...@@ -64,8 +64,9 @@ net = kicad_netlist_reader.netlist(sys.argv[1]) ...@@ -64,8 +64,9 @@ net = kicad_netlist_reader.netlist(sys.argv[1])
try: try:
f = open(sys.argv[2], 'w') f = open(sys.argv[2], 'w')
except IOError: except IOError:
e = "Can't open output file for writing: " + sys.argv[2]
print(__file__, ":", e, file=sys.stderr) print(__file__, ":", e, file=sys.stderr)
f = stdout f = sys.stdout
for c in net.components: for c in net.components:
c.checkvalue() c.checkvalue()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment