Eeschema plugin to import Eagle XML schematics
This commit is contained in:
commit
b3cbfdb7ba
|
@ -42,6 +42,7 @@ Cheng Sheng <chengsheng[at]google-dot-com> Google Inc.
|
|||
Kristoffer Ödmark <kristoffer.odmark90[at]gmail-dot-com>
|
||||
Oliver Walters <oliver.henry.walters[at]gmail-dot-com>
|
||||
Jon Evans <jon[at]craftyjon-dot-com>
|
||||
Russell Oliver <roliver8143[at]gmail-dot-com>
|
||||
|
||||
See also CHANGELOG.txt for contributors.
|
||||
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
Eagle Plugin Implementation Notes. 2017 Russell Oliver
|
||||
|
||||
Below is some notes on the correspondence between Eagle schematics and symbols libraries and the
|
||||
KiCad equivalent.
|
||||
|
||||
Eagle libraries are a many to many listing of symbols and footprints connected by a device set and
|
||||
device definitions. They are embedded in the schematic and board files if there are used, and
|
||||
therefore the schematic symbols and footprints can be recovered from either file.
|
||||
|
||||
An Eagle device set definition is the information needed to represent a physical part at the
|
||||
schematic level including the functional gates of the device. Each gate is lists the symbol to be
|
||||
displayed for that gate. This is equivalent to a KiCad symbol unit. Since the symbol is defined
|
||||
outside of the device set, multiple devices sets in the library can use the same symbol for a gate.
|
||||
Lower to a device set, is the device definition. This establishes the link between the schematic
|
||||
symbols and a physical part through the 'connect' elements. These map the symbol pins for each gate
|
||||
to the physical pins provided by the package (footprint) definition. An Eagle Symbol outlines the
|
||||
layout of graphical of items including pins. Pins for multi gate symbols are generally labelled
|
||||
per their function, i.e. input / output. An Eagle symbol pin is not numbered but merely labelled. A
|
||||
connect element gives the pad number for each pin found in that gate. Therefore the equivalent
|
||||
KiCad pin number is read from the connect element pad number. Since an Eagle gate is equivalent to
|
||||
a KiCad symbol unit, the graphical items for that unit will be copied from the Eagle symbol for
|
||||
that gate and will be unique for that unit. This will yield duplication of the graphical elements
|
||||
if the same symbol is used for multiple gates but the conversion will be complete.
|
||||
|
||||
An Eagle sheet contains a list of instances, which are equivalent to KiCad schematic component
|
||||
entries. An instance describes the part, the gate used and its location on the sheet. This is
|
||||
translated into the equivalent KiCad symbol with the given unit number.
|
||||
|
||||
Eagle 'plain' items describe graphical items with no electrical connection, such as note text,
|
||||
lines etc. Of importance is the use of wire elements to describe both electrical connections and
|
||||
graphical items. A wire element will act as an electrical connection when defined within a net and
|
||||
segment. Anywhere else it is a graphical line. The layer for the wire element will change the
|
||||
displayed colour for the wire. Connections between regular wires and busses occur when a wire ends
|
||||
on a bus segment. When translated to KiCad a bus connection symbol is created. Within an Eagle
|
||||
schematic there can be multiple sheets in a flat hierarchy. For each sheet, there is a list of
|
||||
electrically connected nets. Each net is broken up into graphically connected segments, defined by
|
||||
a list of wires and labels. Labels remain associate with wires of that net segment, even if they
|
||||
are not located on a wire element. This necessitates the movement of such a label to the nearest
|
||||
wire segment within KiCad.
|
|
@ -26,13 +26,71 @@
|
|||
|
||||
#include <eagle_parser.h>
|
||||
|
||||
#include <wx/xml/xml.h>
|
||||
#include <wx/string.h>
|
||||
#include <wx/filename.h>
|
||||
#include <functional>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <cstdio>
|
||||
|
||||
#include <convert_to_biu.h>
|
||||
constexpr auto DEFAULT_ALIGNMENT = ETEXT::BOTTOM_LEFT;
|
||||
|
||||
|
||||
ECOORD::ECOORD( const wxString& aValue, enum ECOORD::UNIT aUnit )
|
||||
{
|
||||
// this array is used to adjust the fraction part value basing on the number of digits in the fraction
|
||||
constexpr int DIVIDERS[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000 };
|
||||
constexpr unsigned int DIVIDERS_MAX_IDX = sizeof( DIVIDERS ) / sizeof( DIVIDERS[0] ) - 1;
|
||||
|
||||
int integer, fraction, pre_fraction, post_fraction;
|
||||
|
||||
// the following check is needed to handle correctly negative fractions where the integer part == 0
|
||||
bool negative = ( aValue[0] == '-' );
|
||||
|
||||
// %n is used to find out how many digits contains the fraction part, e.g. 0.001 contains 3 digits
|
||||
int ret = sscanf( aValue.c_str(), "%d.%n%d%n", &integer, &pre_fraction, &fraction, &post_fraction );
|
||||
|
||||
if( ret == 0 )
|
||||
throw XML_PARSER_ERROR( "Invalid coordinate" );
|
||||
|
||||
// process the integer part
|
||||
value = ToNanoMeters( integer, aUnit );
|
||||
|
||||
// process the fraction part
|
||||
if( ret == 2 )
|
||||
{
|
||||
int digits = post_fraction - pre_fraction;
|
||||
|
||||
// adjust the number of digits if necessary as we cannot handle anything smaller than nanometers (rounding)
|
||||
if( (unsigned) digits > DIVIDERS_MAX_IDX )
|
||||
{
|
||||
int diff = digits - DIVIDERS_MAX_IDX;
|
||||
digits = DIVIDERS_MAX_IDX;
|
||||
fraction /= DIVIDERS[diff];
|
||||
}
|
||||
|
||||
int frac_value = ToNanoMeters( fraction, aUnit ) / DIVIDERS[digits];
|
||||
|
||||
// keep the sign in mind
|
||||
value = negative ? value - frac_value : value + frac_value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
long long int ECOORD::ToNanoMeters( int aValue, enum UNIT aUnit )
|
||||
{
|
||||
long long int ret;
|
||||
|
||||
switch( aUnit )
|
||||
{
|
||||
case NM: ret = aValue; break;
|
||||
case MM: ret = (long long) aValue * 1000000; break;
|
||||
case INCH: ret = (long long) aValue * 25400000; break;
|
||||
case MIL: ret = (long long) aValue * 25400; break;
|
||||
}
|
||||
|
||||
wxASSERT( ( ret > 0 ) == ( aValue > 0 ) ); // check for overflow
|
||||
return ret;
|
||||
}
|
||||
|
||||
using std::string;
|
||||
|
||||
// Template specializations below parse wxString to the used types:
|
||||
// - string
|
||||
|
@ -40,12 +98,12 @@ using std::string;
|
|||
// - int
|
||||
// - bool
|
||||
// - EROT
|
||||
|
||||
// - ECOORD
|
||||
|
||||
template<>
|
||||
string Convert<string>( const wxString& aValue )
|
||||
{
|
||||
return aValue.ToStdString();
|
||||
return string( aValue.ToUTF8() );
|
||||
}
|
||||
|
||||
|
||||
|
@ -102,6 +160,15 @@ EROT Convert<EROT>( const wxString& aRot )
|
|||
return value;
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
ECOORD Convert<ECOORD>( const wxString& aCoord )
|
||||
{
|
||||
// Eagle uses millimeters as the default unit
|
||||
return ECOORD( aCoord, ECOORD::UNIT::MM );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Function parseRequiredAttribute
|
||||
* parsese the aAttribute of the XML node aNode.
|
||||
|
@ -111,7 +178,7 @@ EROT Convert<EROT>( const wxString& aRot )
|
|||
* @return T - the attributed parsed as the specified type.
|
||||
*/
|
||||
template<typename T>
|
||||
T parseRequiredAttribute( wxXmlNode* aNode, string aAttribute )
|
||||
T parseRequiredAttribute( wxXmlNode* aNode, const string& aAttribute )
|
||||
{
|
||||
wxString value;
|
||||
|
||||
|
@ -130,12 +197,101 @@ T parseRequiredAttribute( wxXmlNode* aNode, string aAttribute )
|
|||
* found.
|
||||
*/
|
||||
template<typename T>
|
||||
OPTIONAL_XML_ATTRIBUTE<T> parseOptionalAttribute( wxXmlNode* aNode, string aAttribute )
|
||||
OPTIONAL_XML_ATTRIBUTE<T> parseOptionalAttribute( wxXmlNode* aNode, const string& aAttribute )
|
||||
{
|
||||
return OPTIONAL_XML_ATTRIBUTE<T>( aNode->GetAttribute( aAttribute ) );
|
||||
}
|
||||
|
||||
|
||||
NODE_MAP MapChildren( wxXmlNode* aCurrentNode )
|
||||
{
|
||||
// Map node_name -> node_pointer
|
||||
NODE_MAP nodesMap;
|
||||
|
||||
// Loop through all children mapping them in nodesMap
|
||||
if( aCurrentNode )
|
||||
aCurrentNode = aCurrentNode->GetChildren();
|
||||
|
||||
while( aCurrentNode )
|
||||
{
|
||||
// Create a new pair in the map
|
||||
// key: current node name
|
||||
// value: current node pointer
|
||||
nodesMap[aCurrentNode->GetName().ToStdString()] = aCurrentNode;
|
||||
|
||||
// Get next child
|
||||
aCurrentNode = aCurrentNode->GetNext();
|
||||
}
|
||||
|
||||
return nodesMap;
|
||||
}
|
||||
|
||||
|
||||
unsigned long EagleTimeStamp( wxXmlNode* aTree )
|
||||
{
|
||||
// in this case from a unique tree memory location
|
||||
return (unsigned long)(void*) aTree;
|
||||
}
|
||||
|
||||
|
||||
time_t EagleModuleTstamp( const string& aName, const string& aValue, int aUnit )
|
||||
{
|
||||
std::size_t h1 = std::hash<string>{}( aName );
|
||||
std::size_t h2 = std::hash<string>{}( aValue );
|
||||
std::size_t h3 = std::hash<int>{}( aUnit );
|
||||
|
||||
return h1 ^ (h2 << 1) ^ (h3 << 2);
|
||||
}
|
||||
|
||||
|
||||
wxPoint ConvertArcCenter( const wxPoint& aStart, const wxPoint& aEnd, double aAngle )
|
||||
{
|
||||
// Eagle give us start and end.
|
||||
// S_ARC wants start to give the center, and end to give the start.
|
||||
double dx = aEnd.x - aStart.x, dy = aEnd.y - aStart.y;
|
||||
wxPoint mid = ( aStart + aEnd ) / 2;
|
||||
|
||||
double dlen = sqrt( dx*dx + dy*dy );
|
||||
wxASSERT( dlen != 0 );
|
||||
wxASSERT( aAngle != 0 );
|
||||
double dist = dlen / ( 2 * tan( DEG2RAD( aAngle ) / 2 ) );
|
||||
|
||||
wxPoint center(
|
||||
mid.x + dist * ( dy / dlen ),
|
||||
mid.y - dist * ( dx / dlen )
|
||||
);
|
||||
|
||||
return center;
|
||||
}
|
||||
|
||||
|
||||
static int parseAlignment( const wxString& aAlignment )
|
||||
{
|
||||
// (bottom-left | bottom-center | bottom-right | center-left |
|
||||
// center | center-right | top-left | top-center | top-right)
|
||||
if( aAlignment == "center" )
|
||||
return ETEXT::CENTER;
|
||||
else if( aAlignment == "center-right" )
|
||||
return ETEXT::CENTER_RIGHT;
|
||||
else if( aAlignment == "top-left" )
|
||||
return ETEXT::TOP_LEFT;
|
||||
else if( aAlignment == "top-center" )
|
||||
return ETEXT::TOP_CENTER;
|
||||
else if( aAlignment == "top-right" )
|
||||
return ETEXT::TOP_RIGHT;
|
||||
else if( aAlignment == "bottom-left" )
|
||||
return ETEXT::BOTTOM_LEFT;
|
||||
else if( aAlignment == "bottom-center" )
|
||||
return ETEXT::BOTTOM_CENTER;
|
||||
else if( aAlignment == "bottom-right" )
|
||||
return ETEXT::BOTTOM_RIGHT;
|
||||
else if( aAlignment == "center-left" )
|
||||
return ETEXT::CENTER_LEFT;
|
||||
|
||||
return DEFAULT_ALIGNMENT;
|
||||
}
|
||||
|
||||
|
||||
EWIRE::EWIRE( wxXmlNode* aWire )
|
||||
{
|
||||
/*
|
||||
|
@ -154,11 +310,11 @@ EWIRE::EWIRE( wxXmlNode* aWire )
|
|||
>
|
||||
*/
|
||||
|
||||
x1 = parseRequiredAttribute<double>( aWire, "x1" );
|
||||
y1 = parseRequiredAttribute<double>( aWire, "y1" );
|
||||
x2 = parseRequiredAttribute<double>( aWire, "x2" );
|
||||
y2 = parseRequiredAttribute<double>( aWire, "y2" );
|
||||
width = parseRequiredAttribute<double>( aWire, "width" );
|
||||
x1 = parseRequiredAttribute<ECOORD>( aWire, "x1" );
|
||||
y1 = parseRequiredAttribute<ECOORD>( aWire, "y1" );
|
||||
x2 = parseRequiredAttribute<ECOORD>( aWire, "x2" );
|
||||
y2 = parseRequiredAttribute<ECOORD>( aWire, "y2" );
|
||||
width = parseRequiredAttribute<ECOORD>( aWire, "width" );
|
||||
layer = parseRequiredAttribute<int>( aWire, "layer" );
|
||||
curve = parseOptionalAttribute<double>( aWire, "curve" );
|
||||
|
||||
|
@ -182,6 +338,47 @@ EWIRE::EWIRE( wxXmlNode* aWire )
|
|||
}
|
||||
|
||||
|
||||
EJUNCTION::EJUNCTION( wxXmlNode* aJunction )
|
||||
{
|
||||
/*
|
||||
<!ELEMENT junction EMPTY>
|
||||
<!ATTLIST junction
|
||||
x %Coord; #REQUIRED
|
||||
y %Coord; #REQUIRED
|
||||
>
|
||||
*/
|
||||
|
||||
x = parseRequiredAttribute<ECOORD>( aJunction, "x" );
|
||||
y = parseRequiredAttribute<ECOORD>( aJunction, "y" );
|
||||
}
|
||||
|
||||
|
||||
ELABEL::ELABEL( wxXmlNode* aLabel, const wxString& aNetName )
|
||||
{
|
||||
/*
|
||||
<!ELEMENT label EMPTY>
|
||||
<!ATTLIST label
|
||||
x %Coord; #REQUIRED
|
||||
y %Coord; #REQUIRED
|
||||
size %Dimension; #REQUIRED
|
||||
layer %Layer; #REQUIRED
|
||||
font %TextFont; "proportional"
|
||||
ratio %Int; "8"
|
||||
rot %Rotation; "R0"
|
||||
xref %Bool; "no"
|
||||
>
|
||||
*/
|
||||
|
||||
x = parseRequiredAttribute<ECOORD>( aLabel, "x" );
|
||||
y = parseRequiredAttribute<ECOORD>( aLabel, "y" );
|
||||
size = parseRequiredAttribute<ECOORD>( aLabel, "size" );
|
||||
layer = parseRequiredAttribute<int>( aLabel, "layer" );
|
||||
rot = parseOptionalAttribute<EROT>( aLabel, "rot" );
|
||||
xref = parseOptionalAttribute<string>( aLabel, "xref" );
|
||||
netname = aNetName;
|
||||
}
|
||||
|
||||
|
||||
EVIA::EVIA( wxXmlNode* aVia )
|
||||
{
|
||||
/*
|
||||
|
@ -197,15 +394,15 @@ EVIA::EVIA( wxXmlNode* aVia )
|
|||
>
|
||||
*/
|
||||
|
||||
x = parseRequiredAttribute<double>( aVia, "x" );
|
||||
y = parseRequiredAttribute<double>( aVia, "y" );
|
||||
x = parseRequiredAttribute<ECOORD>( aVia, "x" );
|
||||
y = parseRequiredAttribute<ECOORD>( aVia, "y" );
|
||||
|
||||
string ext = parseRequiredAttribute<string>( aVia, "extent" );
|
||||
|
||||
sscanf( ext.c_str(), "%d-%d", &layer_front_most, &layer_back_most );
|
||||
|
||||
drill = parseRequiredAttribute<double>( aVia, "drill" );
|
||||
diam = parseOptionalAttribute<double>( aVia, "diameter" );
|
||||
drill = parseRequiredAttribute<ECOORD>( aVia, "drill" );
|
||||
diam = parseOptionalAttribute<ECOORD>( aVia, "diameter" );
|
||||
shape = parseOptionalAttribute<string>( aVia, "shape" );
|
||||
}
|
||||
|
||||
|
@ -223,10 +420,10 @@ ECIRCLE::ECIRCLE( wxXmlNode* aCircle )
|
|||
>
|
||||
*/
|
||||
|
||||
x = parseRequiredAttribute<double>( aCircle, "x" );
|
||||
y = parseRequiredAttribute<double>( aCircle, "y" );
|
||||
radius = parseRequiredAttribute<double>( aCircle, "radius" );
|
||||
width = parseRequiredAttribute<double>( aCircle, "width" );
|
||||
x = parseRequiredAttribute<ECOORD>( aCircle, "x" );
|
||||
y = parseRequiredAttribute<ECOORD>( aCircle, "y" );
|
||||
radius = parseRequiredAttribute<ECOORD>( aCircle, "radius" );
|
||||
width = parseRequiredAttribute<ECOORD>( aCircle, "width" );
|
||||
layer = parseRequiredAttribute<int>( aCircle, "layer" );
|
||||
}
|
||||
|
||||
|
@ -245,10 +442,10 @@ ERECT::ERECT( wxXmlNode* aRect )
|
|||
>
|
||||
*/
|
||||
|
||||
x1 = parseRequiredAttribute<double>( aRect, "x1" );
|
||||
y1 = parseRequiredAttribute<double>( aRect, "y1" );
|
||||
x2 = parseRequiredAttribute<double>( aRect, "x2" );
|
||||
y2 = parseRequiredAttribute<double>( aRect, "y2" );
|
||||
x1 = parseRequiredAttribute<ECOORD>( aRect, "x1" );
|
||||
y1 = parseRequiredAttribute<ECOORD>( aRect, "y1" );
|
||||
x2 = parseRequiredAttribute<ECOORD>( aRect, "x2" );
|
||||
y2 = parseRequiredAttribute<ECOORD>( aRect, "y2" );
|
||||
layer = parseRequiredAttribute<int>( aRect, "layer" );
|
||||
rot = parseOptionalAttribute<EROT>( aRect, "rot" );
|
||||
}
|
||||
|
@ -276,9 +473,9 @@ EATTR::EATTR( wxXmlNode* aTree )
|
|||
name = parseRequiredAttribute<string>( aTree, "name" );
|
||||
value = parseOptionalAttribute<string>( aTree, "value" );
|
||||
|
||||
x = parseOptionalAttribute<double>( aTree, "x" );
|
||||
y = parseOptionalAttribute<double>( aTree, "y" );
|
||||
size = parseOptionalAttribute<double>( aTree, "size" );
|
||||
x = parseOptionalAttribute<ECOORD>( aTree, "x" );
|
||||
y = parseOptionalAttribute<ECOORD>( aTree, "y" );
|
||||
size = parseOptionalAttribute<ECOORD>( aTree, "size" );
|
||||
|
||||
// KiCad cannot currently put a TEXTE_MODULE on a different layer than the MODULE
|
||||
// Eagle can it seems.
|
||||
|
@ -297,6 +494,10 @@ EATTR::EATTR( wxXmlNode* aTree )
|
|||
display = EATTR::NAME;
|
||||
else if( stemp == "both" )
|
||||
display = EATTR::BOTH;
|
||||
|
||||
stemp = parseOptionalAttribute<string>( aTree, "align" );
|
||||
|
||||
align = stemp ? parseAlignment( *stemp ) : DEFAULT_ALIGNMENT;
|
||||
}
|
||||
|
||||
|
||||
|
@ -316,20 +517,14 @@ EDIMENSION::EDIMENSION( wxXmlNode* aDimension )
|
|||
>
|
||||
*/
|
||||
|
||||
x1 = parseRequiredAttribute<double>( aDimension, "x1" );
|
||||
y1 = parseRequiredAttribute<double>( aDimension, "y1" );
|
||||
x2 = parseRequiredAttribute<double>( aDimension, "x2" );
|
||||
y2 = parseRequiredAttribute<double>( aDimension, "y2" );
|
||||
x3 = parseRequiredAttribute<double>( aDimension, "x3" );
|
||||
y3 = parseRequiredAttribute<double>( aDimension, "y3" );
|
||||
x1 = parseRequiredAttribute<ECOORD>( aDimension, "x1" );
|
||||
y1 = parseRequiredAttribute<ECOORD>( aDimension, "y1" );
|
||||
x2 = parseRequiredAttribute<ECOORD>( aDimension, "x2" );
|
||||
y2 = parseRequiredAttribute<ECOORD>( aDimension, "y2" );
|
||||
x3 = parseRequiredAttribute<ECOORD>( aDimension, "x3" );
|
||||
y3 = parseRequiredAttribute<ECOORD>( aDimension, "y3" );
|
||||
layer = parseRequiredAttribute<int>( aDimension, "layer" );
|
||||
|
||||
opt_string dimType = parseOptionalAttribute<string>( aDimension, "dtype" );
|
||||
|
||||
if( !dimType )
|
||||
{
|
||||
// default type is parallel
|
||||
}
|
||||
dimensionType = parseOptionalAttribute<string>( aDimension, "dtype" );
|
||||
}
|
||||
|
||||
|
||||
|
@ -350,9 +545,9 @@ ETEXT::ETEXT( wxXmlNode* aText )
|
|||
*/
|
||||
|
||||
text = aText->GetNodeContent();
|
||||
x = parseRequiredAttribute<double>( aText, "x" );
|
||||
y = parseRequiredAttribute<double>( aText, "y" );
|
||||
size = parseRequiredAttribute<double>( aText, "size" );
|
||||
x = parseRequiredAttribute<ECOORD>( aText, "x" );
|
||||
y = parseRequiredAttribute<ECOORD>( aText, "y" );
|
||||
size = parseRequiredAttribute<ECOORD>( aText, "size" );
|
||||
layer = parseRequiredAttribute<int>( aText, "layer" );
|
||||
|
||||
font = parseOptionalAttribute<string>( aText, "font" );
|
||||
|
@ -361,26 +556,38 @@ ETEXT::ETEXT( wxXmlNode* aText )
|
|||
|
||||
opt_string stemp = parseOptionalAttribute<string>( aText, "align" );
|
||||
|
||||
// (bottom-left | bottom-center | bottom-right | center-left |
|
||||
// center | center-right | top-left | top-center | top-right)
|
||||
if( stemp == "center" )
|
||||
align = ETEXT::CENTER;
|
||||
else if( stemp == "center-right" )
|
||||
align = ETEXT::CENTER_RIGHT;
|
||||
else if( stemp == "top-left" )
|
||||
align = ETEXT::TOP_LEFT;
|
||||
else if( stemp == "top-center" )
|
||||
align = ETEXT::TOP_CENTER;
|
||||
else if( stemp == "top-right" )
|
||||
align = ETEXT::TOP_RIGHT;
|
||||
else if( stemp == "bottom-left" )
|
||||
align = ETEXT::BOTTOM_LEFT;
|
||||
else if( stemp == "bottom-center" )
|
||||
align = ETEXT::BOTTOM_CENTER;
|
||||
else if( stemp == "bottom-right" )
|
||||
align = ETEXT::BOTTOM_RIGHT;
|
||||
else if( stemp == "center-left" )
|
||||
align = ETEXT::CENTER_LEFT;
|
||||
align = stemp ? parseAlignment( *stemp ) : DEFAULT_ALIGNMENT;
|
||||
}
|
||||
|
||||
|
||||
wxSize ETEXT::ConvertSize() const
|
||||
{
|
||||
wxSize textsize;
|
||||
|
||||
if( font )
|
||||
{
|
||||
const wxString& fontName = font.CGet();
|
||||
|
||||
if( fontName == "vector" )
|
||||
{
|
||||
textsize = wxSize( size.ToSchUnits(), size.ToSchUnits() );
|
||||
}
|
||||
else if( fontName == "fixed" )
|
||||
{
|
||||
textsize = wxSize( size.ToSchUnits(), size.ToSchUnits() * 0.80 );
|
||||
}
|
||||
else
|
||||
{
|
||||
wxASSERT( false );
|
||||
textsize = wxSize( size.ToSchUnits(), size.ToSchUnits() );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
textsize = wxSize( size.ToSchUnits() * 0.85, size.ToSchUnits() );
|
||||
}
|
||||
|
||||
return textsize;
|
||||
}
|
||||
|
||||
|
||||
|
@ -404,12 +611,12 @@ EPAD::EPAD( wxXmlNode* aPad )
|
|||
|
||||
// #REQUIRED says DTD, throw exception if not found
|
||||
name = parseRequiredAttribute<string>( aPad, "name" );
|
||||
x = parseRequiredAttribute<double>( aPad, "x" );
|
||||
y = parseRequiredAttribute<double>( aPad, "y" );
|
||||
drill = parseRequiredAttribute<double>( aPad, "drill" );
|
||||
x = parseRequiredAttribute<ECOORD>( aPad, "x" );
|
||||
y = parseRequiredAttribute<ECOORD>( aPad, "y" );
|
||||
drill = parseRequiredAttribute<ECOORD>( aPad, "drill" );
|
||||
|
||||
// Optional attributes
|
||||
diameter = parseOptionalAttribute<double>( aPad, "diameter" );
|
||||
diameter = parseOptionalAttribute<ECOORD>( aPad, "diameter" );
|
||||
|
||||
opt_string s = parseOptionalAttribute<string>( aPad, "shape" );
|
||||
|
||||
|
@ -452,10 +659,10 @@ ESMD::ESMD( wxXmlNode* aSMD )
|
|||
|
||||
// DTD #REQUIRED, throw exception if not found
|
||||
name = parseRequiredAttribute<string>( aSMD, "name" );
|
||||
x = parseRequiredAttribute<double>( aSMD, "x" );
|
||||
y = parseRequiredAttribute<double>( aSMD, "y" );
|
||||
dx = parseRequiredAttribute<double>( aSMD, "dx" );
|
||||
dy = parseRequiredAttribute<double>( aSMD, "dy" );
|
||||
x = parseRequiredAttribute<ECOORD>( aSMD, "x" );
|
||||
y = parseRequiredAttribute<ECOORD>( aSMD, "y" );
|
||||
dx = parseRequiredAttribute<ECOORD>( aSMD, "dx" );
|
||||
dy = parseRequiredAttribute<ECOORD>( aSMD, "dy" );
|
||||
layer = parseRequiredAttribute<int>( aSMD, "layer" );
|
||||
|
||||
roundness = parseOptionalAttribute<int>( aSMD, "roundness" );
|
||||
|
@ -467,6 +674,37 @@ ESMD::ESMD( wxXmlNode* aSMD )
|
|||
}
|
||||
|
||||
|
||||
EPIN::EPIN( wxXmlNode* aPin )
|
||||
{
|
||||
/*
|
||||
<!ELEMENT pin EMPTY>
|
||||
<!ATTLIST pin
|
||||
name %String; #REQUIRED
|
||||
x %Coord; #REQUIRED
|
||||
y %Coord; #REQUIRED
|
||||
visible %PinVisible; "both"
|
||||
length %PinLength; "long"
|
||||
direction %PinDirection; "io"
|
||||
function %PinFunction; "none"
|
||||
swaplevel %Int; "0"
|
||||
rot %Rotation; "R0"
|
||||
>
|
||||
*/
|
||||
|
||||
// DTD #REQUIRED, throw exception if not found
|
||||
name = parseRequiredAttribute<string>( aPin, "name" );
|
||||
x = parseRequiredAttribute<ECOORD>( aPin, "x" );
|
||||
y = parseRequiredAttribute<ECOORD>( aPin, "y" );
|
||||
|
||||
visible = parseOptionalAttribute<string>( aPin, "visible" );
|
||||
length = parseOptionalAttribute<string>( aPin, "length" );
|
||||
direction = parseOptionalAttribute<string>( aPin, "direction" );
|
||||
function = parseOptionalAttribute<string>( aPin, "function" );
|
||||
swaplevel = parseOptionalAttribute<int>( aPin, "swaplevel" );
|
||||
rot = parseOptionalAttribute<EROT>( aPin, "rot" );
|
||||
}
|
||||
|
||||
|
||||
EVERTEX::EVERTEX( wxXmlNode* aVertex )
|
||||
{
|
||||
/*
|
||||
|
@ -478,8 +716,8 @@ EVERTEX::EVERTEX( wxXmlNode* aVertex )
|
|||
>
|
||||
*/
|
||||
|
||||
x = parseRequiredAttribute<double>( aVertex, "x" );
|
||||
y = parseRequiredAttribute<double>( aVertex, "y" );
|
||||
x = parseRequiredAttribute<ECOORD>( aVertex, "x" );
|
||||
y = parseRequiredAttribute<ECOORD>( aVertex, "y" );
|
||||
}
|
||||
|
||||
|
||||
|
@ -498,11 +736,11 @@ EPOLYGON::EPOLYGON( wxXmlNode* aPolygon )
|
|||
>
|
||||
*/
|
||||
|
||||
width = parseRequiredAttribute<double>( aPolygon, "width" );
|
||||
width = parseRequiredAttribute<ECOORD>( aPolygon, "width" );
|
||||
layer = parseRequiredAttribute<int>( aPolygon, "layer" );
|
||||
|
||||
spacing = parseOptionalAttribute<double>( aPolygon, "spacing" );
|
||||
isolate = parseOptionalAttribute<double>( aPolygon, "isolate" );
|
||||
spacing = parseOptionalAttribute<ECOORD>( aPolygon, "spacing" );
|
||||
isolate = parseOptionalAttribute<ECOORD>( aPolygon, "isolate" );
|
||||
opt_string s = parseOptionalAttribute<string>( aPolygon, "pour" );
|
||||
|
||||
// default pour to solid fill
|
||||
|
@ -532,9 +770,9 @@ EHOLE::EHOLE( wxXmlNode* aHole )
|
|||
*/
|
||||
|
||||
// #REQUIRED:
|
||||
x = parseRequiredAttribute<double>( aHole, "x" );
|
||||
y = parseRequiredAttribute<double>( aHole, "y" );
|
||||
drill = parseRequiredAttribute<double>( aHole, "drill" );
|
||||
x = parseRequiredAttribute<ECOORD>( aHole, "x" );
|
||||
y = parseRequiredAttribute<ECOORD>( aHole, "y" );
|
||||
drill = parseRequiredAttribute<ECOORD>( aHole, "drill" );
|
||||
}
|
||||
|
||||
|
||||
|
@ -562,8 +800,8 @@ EELEMENT::EELEMENT( wxXmlNode* aElement )
|
|||
package = parseRequiredAttribute<string>( aElement, "package" );
|
||||
ReplaceIllegalFileNameChars( &package );
|
||||
|
||||
x = parseRequiredAttribute<double>( aElement, "x" );
|
||||
y = parseRequiredAttribute<double>( aElement, "y" );
|
||||
x = parseRequiredAttribute<ECOORD>( aElement, "x" );
|
||||
y = parseRequiredAttribute<ECOORD>( aElement, "y" );
|
||||
|
||||
// optional
|
||||
locked = parseOptionalAttribute<bool>( aElement, "locked" );
|
||||
|
@ -595,56 +833,169 @@ ELAYER::ELAYER( wxXmlNode* aLayer )
|
|||
}
|
||||
|
||||
|
||||
NODE_MAP MapChildren( wxXmlNode* currentNode )
|
||||
EPART::EPART( wxXmlNode* aPart )
|
||||
{
|
||||
// Map node_name -> node_pointer
|
||||
NODE_MAP nodesMap;
|
||||
/*
|
||||
* <!ELEMENT part (attribute*, variant*)>
|
||||
* <!ATTLIST part
|
||||
* name %String; #REQUIRED
|
||||
* library %String; #REQUIRED
|
||||
* deviceset %String; #REQUIRED
|
||||
* device %String; #REQUIRED
|
||||
* technology %String; ""
|
||||
* value %String; #IMPLIED
|
||||
* >
|
||||
*/
|
||||
// #REQUIRED
|
||||
name = parseRequiredAttribute<string>( aPart, "name" );
|
||||
library = parseRequiredAttribute<string>( aPart, "library" );
|
||||
deviceset = parseRequiredAttribute<string>( aPart, "deviceset" );
|
||||
device = parseRequiredAttribute<string>( aPart, "device" );
|
||||
technology = parseOptionalAttribute<string>( aPart, "technology" );
|
||||
value = parseOptionalAttribute<string>( aPart, "value" );
|
||||
}
|
||||
|
||||
// Loop through all children mapping them in nodesMap
|
||||
currentNode = currentNode->GetChildren();
|
||||
while( currentNode )
|
||||
{
|
||||
// Create a new pair in the map
|
||||
// key: current node name
|
||||
// value: current node pointer
|
||||
nodesMap[currentNode->GetName().ToStdString()] = currentNode;
|
||||
|
||||
// Get next child
|
||||
currentNode = currentNode->GetNext();
|
||||
EINSTANCE::EINSTANCE( wxXmlNode* aInstance )
|
||||
{
|
||||
/*
|
||||
* <!ELEMENT instance (attribute)*>
|
||||
* <!ATTLIST instance
|
||||
* part %String; #REQUIRED
|
||||
* gate %String; #REQUIRED
|
||||
* x %Coord; #REQUIRED
|
||||
* y %Coord; #REQUIRED
|
||||
* smashed %Bool; "no"
|
||||
* rot %Rotation; "R0"
|
||||
* >
|
||||
*/
|
||||
part = parseRequiredAttribute<string>( aInstance, "part" );
|
||||
gate = parseRequiredAttribute<string>( aInstance, "gate" );
|
||||
|
||||
x = parseRequiredAttribute<ECOORD>( aInstance, "x" );
|
||||
y = parseRequiredAttribute<ECOORD>( aInstance, "y" );
|
||||
|
||||
// optional
|
||||
smashed = parseOptionalAttribute<bool>( aInstance, "smashed" );
|
||||
rot = parseOptionalAttribute<EROT>( aInstance, "rot" );
|
||||
}
|
||||
|
||||
|
||||
EGATE::EGATE( wxXmlNode* aGate )
|
||||
{
|
||||
/*
|
||||
* <!ELEMENT gate EMPTY>
|
||||
* <!ATTLIST gate
|
||||
* name %String; #REQUIRED
|
||||
* symbol %String; #REQUIRED
|
||||
* x %Coord; #REQUIRED
|
||||
* y %Coord; #REQUIRED
|
||||
* addlevel %GateAddLevel; "next"
|
||||
* swaplevel %Int; "0"
|
||||
* >
|
||||
*/
|
||||
|
||||
name = parseRequiredAttribute<string>( aGate, "name" );
|
||||
symbol = parseRequiredAttribute<string>( aGate, "symbol" );
|
||||
|
||||
x = parseRequiredAttribute<ECOORD>( aGate, "x" );
|
||||
y = parseRequiredAttribute<ECOORD>( aGate, "y" );
|
||||
|
||||
opt_string stemp = parseOptionalAttribute<string>( aGate, "addlevel" );
|
||||
|
||||
// (off | value | name | both)
|
||||
if( stemp == "must" )
|
||||
addlevel = EGATE::MUST;
|
||||
else if( stemp == "can" )
|
||||
addlevel = EGATE::CAN;
|
||||
else if( stemp == "next" )
|
||||
addlevel = EGATE::NEXT;
|
||||
else if( stemp == "request" )
|
||||
addlevel = EGATE::REQUEST;
|
||||
else if( stemp == "always" )
|
||||
addlevel = EGATE::ALWAYS;
|
||||
else
|
||||
addlevel = EGATE::NEXT;
|
||||
}
|
||||
|
||||
|
||||
ECONNECT::ECONNECT( wxXmlNode* aConnect )
|
||||
{
|
||||
/*
|
||||
* <!ELEMENT connect EMPTY>
|
||||
* <!ATTLIST connect
|
||||
* gate %String; #REQUIRED
|
||||
* pin %String; #REQUIRED
|
||||
* pad %String; #REQUIRED
|
||||
* route %ContactRoute; "all"
|
||||
* >
|
||||
*/
|
||||
gate = parseRequiredAttribute<string>( aConnect, "gate" );
|
||||
pin = parseRequiredAttribute<string>( aConnect, "pin" );
|
||||
pad = parseRequiredAttribute<string>( aConnect, "pad" );
|
||||
|
||||
//TODO:
|
||||
//int contactroute;
|
||||
|
||||
};
|
||||
|
||||
|
||||
EDEVICE::EDEVICE( wxXmlNode* aDevice )
|
||||
{
|
||||
/*
|
||||
<!ELEMENT device (connects?, technologies?)>
|
||||
<!ATTLIST device
|
||||
name %String; ""
|
||||
package %String; #IMPLIED
|
||||
>
|
||||
*/
|
||||
name = parseRequiredAttribute<string>( aDevice, "name" );
|
||||
package = parseOptionalAttribute<string>( aDevice, "package" );
|
||||
|
||||
NODE_MAP aDeviceChildren = MapChildren(aDevice);
|
||||
wxXmlNode* connectNode = getChildrenNodes(aDeviceChildren, "connects");
|
||||
|
||||
while(connectNode){
|
||||
connects.push_back(ECONNECT(connectNode));
|
||||
connectNode = connectNode->GetNext();
|
||||
}
|
||||
|
||||
return nodesMap;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
string makeKey( const string& aFirst, const string& aSecond )
|
||||
EDEVICE_SET::EDEVICE_SET( wxXmlNode* aDeviceSet )
|
||||
{
|
||||
string key = aFirst + '\x02' + aSecond;
|
||||
return key;
|
||||
}
|
||||
|
||||
|
||||
unsigned long timeStamp( wxXmlNode* aTree )
|
||||
{
|
||||
// in this case from a unique tree memory location
|
||||
return (unsigned long)(void*) aTree;
|
||||
}
|
||||
|
||||
|
||||
wxPoint kicad_arc_center( const wxPoint& aStart, const wxPoint& aEnd, double aAngle )
|
||||
{
|
||||
// Eagle give us start and end.
|
||||
// S_ARC wants start to give the center, and end to give the start.
|
||||
double dx = aEnd.x - aStart.x, dy = aEnd.y - aStart.y;
|
||||
wxPoint mid = ( aStart + aEnd ) / 2;
|
||||
|
||||
double dlen = sqrt( dx * dx + dy * dy );
|
||||
double dist = dlen / ( 2 * tan( DEG2RAD( aAngle ) / 2 ) );
|
||||
|
||||
wxPoint center(
|
||||
mid.x + dist * ( dy / dlen ),
|
||||
mid.y - dist * ( dx / dlen )
|
||||
);
|
||||
|
||||
return center;
|
||||
/*
|
||||
<!ELEMENT deviceset (description?, gates, devices)>
|
||||
<!ATTLIST deviceset
|
||||
name %String; #REQUIRED
|
||||
prefix %String; ""
|
||||
uservalue %Bool; "no"
|
||||
>
|
||||
*/
|
||||
|
||||
name = parseRequiredAttribute<string>(aDeviceSet, "name");
|
||||
prefix = parseOptionalAttribute<string>( aDeviceSet, "prefix" );
|
||||
uservalue = parseOptionalAttribute<bool>( aDeviceSet, "uservalue" );
|
||||
|
||||
/* Russell: Parsing of devices and gates moved to sch_eagle_plugin.cpp
|
||||
*
|
||||
//TODO: description
|
||||
|
||||
NODE_MAP aDeviceSetChildren = MapChildren(aDeviceSet);
|
||||
wxXmlNode* deviceNode = getChildrenNodes(aDeviceSetChildren, "device");
|
||||
|
||||
while(deviceNode){
|
||||
devices.push_back(EDEVICE(deviceNode));
|
||||
deviceNode->GetNext();
|
||||
}
|
||||
|
||||
wxXmlNode* gateNode = getChildrenNodes(aDeviceSetChildren, "gate");
|
||||
|
||||
while(gateNode){
|
||||
gates.push_back(EGATE(gateNode));
|
||||
gateNode->GetNext();
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
|
|
@ -35,20 +35,7 @@
|
|||
#include <class_drawpanel.h> // EDA_DRAW_PANEL
|
||||
|
||||
#include <basic_gal.h>
|
||||
|
||||
// Conversion to application internal units defined at build time.
|
||||
#if defined( PCBNEW )
|
||||
#include <class_board_item.h> // for FMT_IU
|
||||
#elif defined( EESCHEMA )
|
||||
#include <sch_item_struct.h> // for FMT_IU
|
||||
#elif defined( GERBVIEW )
|
||||
#elif defined( PL_EDITOR )
|
||||
#include <base_units.h>
|
||||
#define FMT_IU Double2Str
|
||||
#else
|
||||
#error "Cannot resolve units formatting due to no definition of EESCHEMA or PCBNEW."
|
||||
#endif
|
||||
|
||||
#include <unit_format.h>
|
||||
#include <convert_to_biu.h>
|
||||
|
||||
EDA_TEXT::EDA_TEXT( const wxString& text ) :
|
||||
|
|
|
@ -52,7 +52,7 @@ void FP_LIB_TABLE_ROW::SetType( const wxString& aType )
|
|||
type = IO_MGR::EnumFromStr( aType );
|
||||
|
||||
if( IO_MGR::PCB_FILE_T( -1 ) == type )
|
||||
type = IO_MGR::KICAD;
|
||||
type = IO_MGR::KICAD_SEXP;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -72,6 +72,8 @@ const wxString SchematicSymbolFileWildcard( _( "KiCad drawing symbol file (*.sym
|
|||
const wxString SchematicLibraryFileWildcard( _( "KiCad component library file (*.lib)|*.lib" ) );
|
||||
const wxString ProjectFileWildcard( _( "KiCad project files (*.pro)|*.pro" ) );
|
||||
const wxString SchematicFileWildcard( _( "KiCad schematic files (*.sch)|*.sch" ) );
|
||||
const wxString EagleSchematicFileWildcard( _( "Eagle XML schematic file (*.sch)|*.sch" ) );
|
||||
const wxString EagleFilesWildcard( _( "Eagle XML files (*.sch *.brd)|*.sch;*.brd" ) );
|
||||
const wxString NetlistFileWildcard( _( "KiCad netlist files (*.net)|*.net" ) );
|
||||
const wxString GerberFileWildcard( _( "Gerber files (*.pho)|*.pho" ) );
|
||||
const wxString LegacyPcbFileWildcard( _( "KiCad printed circuit board files (*.brd)|*.brd" ) );
|
||||
|
|
|
@ -168,6 +168,7 @@ set( EESCHEMA_SRCS
|
|||
sch_bus_entry.cpp
|
||||
sch_collectors.cpp
|
||||
sch_component.cpp
|
||||
sch_eagle_plugin.cpp
|
||||
sch_field.cpp
|
||||
sch_io_mgr.cpp
|
||||
sch_item_struct.cpp
|
||||
|
@ -299,7 +300,7 @@ target_link_libraries( eeschema
|
|||
)
|
||||
|
||||
# the DSO (KIFACE) housing the main eeschema code:
|
||||
add_library( eeschema_kiface MODULE
|
||||
add_library( eeschema_kiface SHARED
|
||||
${EESCHEMA_SRCS}
|
||||
${EESCHEMA_COMMON_SRCS}
|
||||
)
|
||||
|
@ -437,3 +438,4 @@ add_custom_target(
|
|||
add_dependencies( eeschema_kiface dialog_bom_cfg_lexer_source_files )
|
||||
|
||||
add_subdirectory( plugins )
|
||||
add_subdirectory( qa )
|
||||
|
|
|
@ -433,7 +433,7 @@ void DIALOG_BOM::OnRunPlugin( wxCommandEvent& event )
|
|||
m_parent->SetExecFlags( wxEXEC_SHOW_CONSOLE );
|
||||
#endif
|
||||
|
||||
m_parent->CreateNetlist( -1, fullfilename, 0, &reporter );
|
||||
m_parent->CreateNetlist( -1, fullfilename, 0, &reporter, false );
|
||||
|
||||
m_Messages->SetValue( reportmsg );
|
||||
}
|
||||
|
|
|
@ -611,7 +611,7 @@ void NETLIST_DIALOG::GenNetlist( wxCommandEvent& event )
|
|||
else
|
||||
m_Parent->SetNetListerCommand( wxEmptyString );
|
||||
|
||||
m_Parent->CreateNetlist( currPage->m_IdNetType, fullpath, netlist_opt );
|
||||
m_Parent->CreateNetlist( currPage->m_IdNetType, fullpath, netlist_opt, NULL, false );
|
||||
|
||||
WriteCurrentNetlistSetup();
|
||||
|
||||
|
@ -689,7 +689,7 @@ void NETLIST_DIALOG::RunSimulator( wxCommandEvent& event )
|
|||
netlist_opt |= NET_ADJUST_PASSIVE_VALS;
|
||||
|
||||
if( ! m_Parent->CreateNetlist( currPage->m_IdNetType, fn.GetFullPath(),
|
||||
netlist_opt ) )
|
||||
netlist_opt, NULL, false ) )
|
||||
return;
|
||||
|
||||
ExecuteFile( this, ExecFile, CommandLine );
|
||||
|
@ -878,4 +878,3 @@ int InvokeDialogNetList( SCH_EDIT_FRAME* aCaller )
|
|||
|
||||
return dlg.ShowModal();
|
||||
}
|
||||
|
||||
|
|
|
@ -60,6 +60,7 @@ enum id_eeschema_frm
|
|||
{
|
||||
ID_UPDATE_ONE_SHEET = ID_END_LIST,
|
||||
ID_SAVE_ONE_SHEET_UNDER_NEW_NAME,
|
||||
ID_IMPORT_NON_KICAD_SCH,
|
||||
|
||||
/* Schematic editor main menubar IDs. */
|
||||
ID_RESCUE_CACHED,
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#include <project_rescue.h>
|
||||
#include <eeschema_config.h>
|
||||
#include <sch_legacy_plugin.h>
|
||||
#include <sch_eagle_plugin.h>
|
||||
|
||||
|
||||
//#define USE_SCH_LEGACY_IO_PLUGIN
|
||||
|
@ -190,8 +191,6 @@ bool SCH_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
|
|||
{
|
||||
// implement the pseudo code from KIWAY_PLAYER.h:
|
||||
|
||||
SCH_SCREENS screenList;
|
||||
|
||||
// This is for python:
|
||||
if( aFileSet.size() != 1 )
|
||||
{
|
||||
|
@ -216,34 +215,8 @@ bool SCH_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
|
|||
return false;
|
||||
}
|
||||
|
||||
// Save any currently open and modified project files.
|
||||
for( SCH_SCREEN* screen = screenList.GetFirst(); screen; screen = screenList.GetNext() )
|
||||
{
|
||||
if( screen->IsModify() )
|
||||
{
|
||||
int response = YesNoCancelDialog( this, _(
|
||||
"The current schematic has been modified. Do you wish to save the changes?" ),
|
||||
wxEmptyString,
|
||||
_( "Save and Load" ),
|
||||
_( "Load Without Saving" )
|
||||
);
|
||||
|
||||
if( response == wxID_CANCEL )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if( response == wxID_YES )
|
||||
{
|
||||
wxCommandEvent dummy;
|
||||
OnSaveProject( dummy );
|
||||
}
|
||||
else
|
||||
{
|
||||
// response == wxID_NO, fall thru
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( !AskToSaveChanges() )
|
||||
return false;
|
||||
|
||||
wxFileName pro = fullFileName;
|
||||
pro.SetExt( ProjectFileExtension );
|
||||
|
@ -314,7 +287,6 @@ bool SCH_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
|
|||
{
|
||||
delete g_RootSheet; // Delete the current project.
|
||||
g_RootSheet = NULL; // Force CreateScreens() to build new empty project on load failure.
|
||||
|
||||
SCH_PLUGIN::SCH_PLUGIN_RELEASER pi( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_LEGACY ) );
|
||||
|
||||
try
|
||||
|
@ -399,7 +371,7 @@ bool SCH_EDIT_FRAME::AppendOneEEProject()
|
|||
// open file chooser dialog
|
||||
wxString path = wxPathOnly( Prj().GetProjectFullName() );
|
||||
|
||||
wxFileDialog dlg( this, _( "Import Schematic" ), path,
|
||||
wxFileDialog dlg( this, _( "Append Schematic" ), path,
|
||||
wxEmptyString, SchematicFileWildcard,
|
||||
wxFD_OPEN | wxFD_FILE_MUST_EXIST );
|
||||
|
||||
|
@ -533,6 +505,25 @@ void SCH_EDIT_FRAME::OnAppendProject( wxCommandEvent& event )
|
|||
}
|
||||
|
||||
|
||||
void SCH_EDIT_FRAME::OnImportProject( wxCommandEvent& aEvent )
|
||||
{
|
||||
if( !AskToSaveChanges() )
|
||||
return;
|
||||
|
||||
wxString path = wxPathOnly( Prj().GetProjectFullName() );
|
||||
|
||||
wxFileDialog dlg( this, _( "Import Schematic" ), path,
|
||||
wxEmptyString, EagleSchematicFileWildcard,
|
||||
wxFD_OPEN | wxFD_FILE_MUST_EXIST );
|
||||
|
||||
if( dlg.ShowModal() == wxID_CANCEL )
|
||||
return;
|
||||
|
||||
// For now there is only one import plugin
|
||||
ImportFile( dlg.GetPath(), SCH_IO_MGR::SCH_EAGLE );
|
||||
}
|
||||
|
||||
|
||||
void SCH_EDIT_FRAME::OnSaveProject( wxCommandEvent& aEvent )
|
||||
{
|
||||
SCH_SCREEN* screen;
|
||||
|
@ -606,3 +597,118 @@ bool SCH_EDIT_FRAME::doAutoSave()
|
|||
|
||||
return autoSaveOk;
|
||||
}
|
||||
|
||||
|
||||
bool SCH_EDIT_FRAME::ImportFile( const wxString& aFileName, int aFileType )
|
||||
{
|
||||
wxString fullFileName( aFileName );
|
||||
|
||||
SCH_PLUGIN::SCH_PLUGIN_RELEASER pi;
|
||||
wxString projectpath;
|
||||
wxFileName newfilename;
|
||||
SCH_SHEET_LIST sheetList( g_RootSheet );
|
||||
SCH_SCREENS schematic;
|
||||
|
||||
switch( (SCH_IO_MGR::SCH_FILE_T) aFileType )
|
||||
{
|
||||
case SCH_IO_MGR::SCH_EAGLE:
|
||||
// We insist on caller sending us an absolute path, if it does not, we say it's a bug.
|
||||
wxASSERT_MSG( wxFileName( fullFileName ).IsAbsolute(),
|
||||
wxT( "Import eagle schematic caller didn't send full filename" ) );
|
||||
|
||||
if( !LockFile( fullFileName ) )
|
||||
{
|
||||
wxString msg = wxString::Format( _( "Schematic file '%s' is already open." ),
|
||||
GetChars( fullFileName ) );
|
||||
DisplayError( this, msg );
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
pi.set( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_EAGLE ) );
|
||||
g_RootSheet = pi->Load( fullFileName, &Kiway() );
|
||||
|
||||
projectpath = Kiway().Prj().GetProjectPath();
|
||||
newfilename = Prj().AbsolutePath( Prj().GetProjectName() );
|
||||
newfilename.SetExt( SchematicFileExtension );
|
||||
|
||||
m_CurrentSheet->clear();
|
||||
m_CurrentSheet->push_back( g_RootSheet );
|
||||
SetScreen( m_CurrentSheet->LastScreen() );
|
||||
|
||||
g_RootSheet->SetFileName( newfilename.GetFullPath() );
|
||||
GetScreen()->SetFileName( newfilename.GetFullPath() );
|
||||
GetScreen()->SetModify();
|
||||
|
||||
UpdateFileHistory( fullFileName );
|
||||
schematic.UpdateSymbolLinks(); // Update all symbol library links for all sheets.
|
||||
GetScreen()->TestDanglingEnds(); // Only perform the dangling end test on root sheet.
|
||||
|
||||
GetScreen()->SetGrid( ID_POPUP_GRID_LEVEL_1000 + m_LastGridSizeId );
|
||||
Zoom_Automatique( false );
|
||||
SetSheetNumberAndCount();
|
||||
m_canvas->Refresh( true );
|
||||
UpdateTitle();
|
||||
}
|
||||
catch( const IO_ERROR& ioe )
|
||||
{
|
||||
// Do not leave g_RootSheet == NULL because it is expected to be
|
||||
// a valid sheet. Therefore create a dummy empty root sheet and screen.
|
||||
CreateScreens();
|
||||
Zoom_Automatique( false );
|
||||
|
||||
wxString msg;
|
||||
msg.Printf( _( "Error loading schematic file '%s'.\n%s" ),
|
||||
GetChars( fullFileName ), GetChars( ioe.What() ) );
|
||||
DisplayError( this, msg );
|
||||
|
||||
msg.Printf( _( "Failed to load '%s'" ), GetChars( fullFileName ) );
|
||||
AppendMsgPanel( wxEmptyString, msg, CYAN );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool SCH_EDIT_FRAME::AskToSaveChanges()
|
||||
{
|
||||
SCH_SCREENS screenList;
|
||||
|
||||
// Save any currently open and modified project files.
|
||||
for( SCH_SCREEN* screen = screenList.GetFirst(); screen; screen = screenList.GetNext() )
|
||||
{
|
||||
if( screen->IsModify() )
|
||||
{
|
||||
int response = YesNoCancelDialog( m_parent, _(
|
||||
"The current schematic has been modified. Do you wish to save the changes?" ),
|
||||
wxEmptyString,
|
||||
_( "Save and Load" ),
|
||||
_( "Load Without Saving" )
|
||||
);
|
||||
|
||||
if( response == wxID_CANCEL )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if( response == wxID_YES )
|
||||
{
|
||||
wxCommandEvent dummy;
|
||||
OnSaveProject( dummy );
|
||||
}
|
||||
// else wxID_NO, so do not save
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -745,7 +745,7 @@ void LIB_ARC::calcEdit( const wxPoint& aPosition )
|
|||
}
|
||||
|
||||
m_Pos = newCenterPoint;
|
||||
calcRadiusAngles();
|
||||
CalcRadiusAngles();
|
||||
}
|
||||
else if( m_Flags == IS_NEW )
|
||||
{
|
||||
|
@ -781,7 +781,7 @@ void LIB_ARC::calcEdit( const wxPoint& aPosition )
|
|||
cY += m_ArcStart.y;
|
||||
m_Pos.x = cX;
|
||||
m_Pos.y = cY;
|
||||
calcRadiusAngles();
|
||||
CalcRadiusAngles();
|
||||
|
||||
SetEraseLastDrawItem();
|
||||
}
|
||||
|
@ -792,7 +792,7 @@ void LIB_ARC::calcEdit( const wxPoint& aPosition )
|
|||
}
|
||||
|
||||
|
||||
void LIB_ARC::calcRadiusAngles()
|
||||
void LIB_ARC::CalcRadiusAngles()
|
||||
{
|
||||
wxPoint centerStartVector = twoPointVector( m_Pos, m_ArcStart );
|
||||
wxPoint centerEndVector = twoPointVector( m_Pos, m_ArcEnd );
|
||||
|
|
|
@ -78,10 +78,6 @@ class LIB_ARC : public LIB_ITEM
|
|||
*/
|
||||
void calcEdit( const wxPoint& aPosition ) override;
|
||||
|
||||
/**
|
||||
* Calculate the radius and angle of an arc using the start, end, and center points.
|
||||
*/
|
||||
void calcRadiusAngles();
|
||||
|
||||
public:
|
||||
LIB_ARC( LIB_PART * aParent );
|
||||
|
@ -153,6 +149,12 @@ public:
|
|||
|
||||
void SetEnd( const wxPoint& aPoint ) { m_ArcEnd = aPoint; }
|
||||
|
||||
/**
|
||||
* Calculate the radius and angle of an arc using the start, end, and center points.
|
||||
*/
|
||||
void CalcRadiusAngles();
|
||||
|
||||
|
||||
wxString GetSelectMenuText() const override;
|
||||
|
||||
BITMAP_DEF GetMenuImage() const override;
|
||||
|
|
|
@ -130,7 +130,8 @@ static const wxString getPinOrientationName( unsigned aPinOrientationCode )
|
|||
|
||||
static int InternalPinDecoSize( const LIB_PIN &aPin )
|
||||
{
|
||||
return aPin.GetNameTextSize() / 2;
|
||||
|
||||
return aPin.GetNameTextSize() != 0 ? aPin.GetNameTextSize() / 2 : aPin.GetNumberTextSize() / 2;
|
||||
}
|
||||
|
||||
/// Utility for getting the size of the 'external' pin decorators (as a radius)
|
||||
|
|
|
@ -37,6 +37,7 @@ class SCH_COMPONENT;
|
|||
|
||||
#include "pin_shape.h"
|
||||
#include "pin_type.h"
|
||||
#include "class_libentry.h"
|
||||
|
||||
// Circle diameter drawn at the active end of pins:
|
||||
#define TARGET_PIN_RADIUS 12
|
||||
|
@ -362,7 +363,13 @@ public:
|
|||
* Return whether this pin forms an implicit power connection: i.e., is hidden
|
||||
* and of type POWER_IN.
|
||||
*/
|
||||
bool IsPowerConnection() const { return !IsVisible() && GetType() == PIN_POWER_IN; }
|
||||
bool IsPowerConnection() const {
|
||||
|
||||
return (
|
||||
( !IsVisible() && GetType() == PIN_POWER_IN )
|
||||
||
|
||||
( (LIB_PART*)GetParent()->IsPower() && GetType() == PIN_POWER_IN )
|
||||
) ; }
|
||||
|
||||
int GetPenSize() const override;
|
||||
|
||||
|
|
|
@ -338,10 +338,15 @@ void prepareFilesMenu( wxMenu* aParentMenu, bool aIsOutsideProject )
|
|||
}
|
||||
|
||||
AddMenuItem( aParentMenu,
|
||||
ID_APPEND_PROJECT, _( "Imp&ort Schematic Sheet Content" ),
|
||||
_( "Import schematic sheet content from other project in current sheet" ),
|
||||
ID_APPEND_PROJECT, _( "App&end Schematic Sheet" ),
|
||||
_( "Import schematic sheet content from another project to current sheet" ),
|
||||
KiBitmap( open_document_xpm ) );
|
||||
|
||||
AddMenuItem( aParentMenu,
|
||||
ID_IMPORT_NON_KICAD_SCH, _( "&Import Non-Kicad Schematic File" ),
|
||||
_( "Import schematic file from other applications" ),
|
||||
KiBitmap( open_document_xpm ) ); // TODO needs a different icon
|
||||
|
||||
aParentMenu->AppendSeparator();
|
||||
|
||||
text = AddHotkeyName( _( "&Save Schematic Project" ),
|
||||
|
|
|
@ -110,15 +110,26 @@ void SCH_EDIT_FRAME::sendNetlist()
|
|||
|
||||
|
||||
bool SCH_EDIT_FRAME::CreateNetlist( int aFormat, const wxString& aFullFileName,
|
||||
unsigned aNetlistOptions, REPORTER* aReporter )
|
||||
unsigned aNetlistOptions, REPORTER* aReporter, bool aSilent )
|
||||
{
|
||||
if( !prepareForNetlist() )
|
||||
return false;
|
||||
if( !aSilent ) // checks for errors and invokes annotation dialog as neccessary
|
||||
{
|
||||
if( !prepareForNetlist() )
|
||||
return false;
|
||||
}
|
||||
else // performs similar function as prepareForNetlist but without a dialog.
|
||||
{
|
||||
SCH_SCREENS schematic;
|
||||
schematic.UpdateSymbolLinks();
|
||||
SCH_SHEET_LIST sheets( g_RootSheet );
|
||||
sheets.AnnotatePowerSymbols( Prj().SchLibs() );
|
||||
schematic.SchematicCleanUp();
|
||||
}
|
||||
|
||||
std::unique_ptr<NETLIST_OBJECT_LIST> connectedItemsList( BuildNetListBase() );
|
||||
|
||||
bool success = WriteNetListFile( connectedItemsList.release(), aFormat,
|
||||
aFullFileName, aNetlistOptions, aReporter );
|
||||
aFullFileName, aNetlistOptions, aReporter );
|
||||
|
||||
return success;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
#
|
||||
# This program source code file is part of KiCad, a free EDA CAD application.
|
||||
#
|
||||
# Copyright (C) 2017 CERN
|
||||
# @author Alejandro García Montoro <alejandro.garciamontoro@gmail.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, you may find one here:
|
||||
# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
# or you may search the http://www.gnu.org website for the version 2 license,
|
||||
# or you may write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
find_package( Boost COMPONENTS unit_test_framework REQUIRED )
|
||||
|
||||
include_directories( BEFORE ${INC_BEFORE} )
|
||||
include_directories(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${INC_AFTER}
|
||||
)
|
||||
|
||||
add_executable( qa_eagle_plugin
|
||||
test_module.cpp
|
||||
test_basic.cpp
|
||||
)
|
||||
|
||||
add_dependencies( qa_eagle_plugin common eeschema_kiface )
|
||||
|
||||
target_link_libraries( qa_eagle_plugin
|
||||
common
|
||||
eeschema_kiface
|
||||
${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}
|
||||
${wxWidgets_LIBRARIES}
|
||||
)
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2017 CERN
|
||||
* @author Alejandro García Montoro <alejandro.garciamontoro@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <boost/test/test_case_template.hpp>
|
||||
#include <sch_io_mgr.h>
|
||||
#include <kiway.h>
|
||||
|
||||
#include <data/fixtures_eagle_plugin.h>
|
||||
|
||||
/**
|
||||
* Checks that the SCH_IO manager finds the Eagle plugin
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE( FindPlugin )
|
||||
{
|
||||
BOOST_CHECK( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_EAGLE ) != NULL );
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE( Load )
|
||||
{
|
||||
SCH_PLUGIN* pi = SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_EAGLE );
|
||||
|
||||
pi->Load("/home/alejandro/Proyectos/kicad/kicad-alejandro/eeschema/qa/data/eagle_schematics/empty.sch",
|
||||
NULL);
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2017 CERN
|
||||
* @author Alejandro García Montoro <alejandro.garciamontoro@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* Main file for the schematic eagle plugin tests to be compiled
|
||||
*/
|
||||
|
||||
#define BOOST_TEST_DYN_LINK
|
||||
#define BOOST_TEST_MODULE "Schematic Eagle plugin"
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,189 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2017 CERN
|
||||
* @author Alejandro García Montoro <alejandro.garciamontoro@gmail.com>
|
||||
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||
* @author Russell Oliver <roliver8143@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 3
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _SCH_EAGLE_PLUGIN_H_
|
||||
#define _SCH_EAGLE_PLUGIN_H_
|
||||
|
||||
#include <wx/xml/xml.h>
|
||||
|
||||
#include <sch_line.h>
|
||||
#include <sch_io_mgr.h>
|
||||
#include <eagle_parser.h>
|
||||
#include <lib_draw_item.h>
|
||||
#include <dlist.h>
|
||||
|
||||
#include <boost/ptr_container/ptr_map.hpp>
|
||||
|
||||
class EDA_TEXT;
|
||||
class KIWAY;
|
||||
class LINE_READER;
|
||||
class SCH_SCREEN;
|
||||
class SCH_SHEET;
|
||||
class SCH_BITMAP;
|
||||
class SCH_JUNCTION;
|
||||
class SCH_NO_CONNECT;
|
||||
class SCH_LINE;
|
||||
class SCH_BUS_ENTRY_BASE;
|
||||
class SCH_TEXT;
|
||||
class SCH_GLOBALLABEL;
|
||||
class SCH_COMPONENT;
|
||||
class SCH_FIELD;
|
||||
class PROPERTIES;
|
||||
class SCH_EAGLE_PLUGIN_CACHE;
|
||||
class LIB_PART;
|
||||
class PART_LIB;
|
||||
class LIB_ALIAS;
|
||||
class LIB_CIRCLE;
|
||||
class LIB_FIELD;
|
||||
class LIB_RECTANGLE;
|
||||
class LIB_POLYLINE;
|
||||
class LIB_PIN;
|
||||
class LIB_TEXT;
|
||||
|
||||
|
||||
typedef struct EAGLE_LIBRARY
|
||||
{
|
||||
std::string name;
|
||||
boost::ptr_map<std::string, LIB_PART> KiCadSymbols;
|
||||
std::unordered_map<std::string, wxXmlNode*> SymbolNodes;
|
||||
std::unordered_map<std::string, int> GateUnit;
|
||||
std::unordered_map<std::string, std::string> package;
|
||||
} EAGLE_LIBRARY;
|
||||
|
||||
typedef boost::ptr_map<std::string, EPART> EPART_LIST;
|
||||
|
||||
|
||||
/**
|
||||
* Class SCH_EAGLE_PLUGIN
|
||||
* is a #SCH_PLUGIN derivation for loading 6.x+ Eagle schematic files.
|
||||
*
|
||||
* As with all SCH_PLUGINs there is no UI dependencies i.e. windowing calls allowed.
|
||||
*/
|
||||
class SCH_EAGLE_PLUGIN : public SCH_PLUGIN
|
||||
{
|
||||
public:
|
||||
SCH_EAGLE_PLUGIN();
|
||||
~SCH_EAGLE_PLUGIN();
|
||||
|
||||
const wxString GetName() const override;
|
||||
|
||||
const wxString GetFileExtension() const override;
|
||||
|
||||
int GetModifyHash() const override;
|
||||
|
||||
SCH_SHEET* Load( const wxString& aFileName, KIWAY* aKiway, SCH_SHEET* aAppendToMe = NULL,
|
||||
const PROPERTIES* aProperties = NULL ) override;
|
||||
|
||||
bool CheckHeader( const wxString& aFileName ) override;
|
||||
|
||||
|
||||
// unimplemented functions. Will trigger a not_implemented IO error.
|
||||
//void SaveLibrary( const wxString& aFileName, const PROPERTIES* aProperties = NULL ) override;
|
||||
|
||||
//void Save( const wxString& aFileName, SCH_SCREEN* aSchematic, KIWAY* aKiway,
|
||||
// const PROPERTIES* aProperties = NULL ) override;
|
||||
|
||||
//size_t GetSymbolLibCount( const wxString& aLibraryPath,
|
||||
// const PROPERTIES* aProperties = NULL ) override;
|
||||
|
||||
//void EnumerateSymbolLib( wxArrayString& aAliasNameList, const wxString& aLibraryPath,
|
||||
// const PROPERTIES* aProperties = NULL ) override;
|
||||
|
||||
//LIB_ALIAS* LoadSymbol( const wxString& aLibraryPath, const wxString& aAliasName,
|
||||
// const PROPERTIES* aProperties = NULL ) override;
|
||||
|
||||
//void SaveSymbol( const wxString& aLibraryPath, const LIB_PART* aSymbol,
|
||||
// const PROPERTIES* aProperties = NULL ) override;
|
||||
|
||||
//void DeleteAlias( const wxString& aLibraryPath, const wxString& aAliasName,
|
||||
// const PROPERTIES* aProperties = NULL ) override;
|
||||
|
||||
//void DeleteSymbol( const wxString& aLibraryPath, const wxString& aAliasName,
|
||||
// const PROPERTIES* aProperties = NULL ) override;
|
||||
|
||||
//void CreateSymbolLib( const wxString& aLibraryPath,
|
||||
// const PROPERTIES* aProperties = NULL ) override;
|
||||
|
||||
// bool DeleteSymbolLib( const wxString& aLibraryPath,
|
||||
// const PROPERTIES* aProperties = NULL ) override;
|
||||
|
||||
//bool IsSymbolLibWritable( const wxString& aLibraryPath ) override;
|
||||
|
||||
//void SymbolLibOptions( PROPERTIES* aListToAppendTo ) const override;
|
||||
|
||||
private:
|
||||
void loadDrawing( wxXmlNode* aDrawingNode );
|
||||
void loadLayerDefs( wxXmlNode* aLayers );
|
||||
void loadSchematic( wxXmlNode* aSchematicNode );
|
||||
void loadSheet( wxXmlNode* aSheetNode, int sheetcount );
|
||||
void loadInstance( wxXmlNode* aInstanceNode );
|
||||
EAGLE_LIBRARY* loadLibrary( wxXmlNode* aLibraryNode, EAGLE_LIBRARY* aEagleLib );
|
||||
void countNets( wxXmlNode* aSchematicNode );
|
||||
|
||||
/// Moves any labels on the wire to the new end point of the wire.
|
||||
void moveLabels( SCH_ITEM* aWire, const wxPoint& aNewEndPoint );
|
||||
|
||||
/// This function finds best way to place a bus entry symbol for when an Eagle wire segment
|
||||
/// ends on an Eagle bus segment.
|
||||
void addBusEntries();
|
||||
|
||||
///> Translates Eagle special characters to their counterparts in KiCad.
|
||||
static wxString escapeName( const wxString& aNetName );
|
||||
|
||||
/// Return the matching layer or return LAYER_NOTES
|
||||
SCH_LAYER_ID kiCadLayer( int aEagleLayer );
|
||||
|
||||
wxPoint findNearestLinePoint( const wxPoint& aPoint, const DLIST<SCH_LINE>& aLines );
|
||||
|
||||
void loadSegments( wxXmlNode* aSegmentsNode, const wxString& aNetName,
|
||||
const wxString& aNetClass );
|
||||
SCH_LINE* loadWire( wxXmlNode* aWireNode );
|
||||
SCH_TEXT* loadLabel( wxXmlNode* aLabelNode, const wxString& aNetName, const DLIST< SCH_LINE >& segmentWires);
|
||||
SCH_JUNCTION* loadJunction( wxXmlNode* aJunction );
|
||||
SCH_TEXT* loadPlainText( wxXmlNode* aSchText );
|
||||
|
||||
bool loadSymbol( wxXmlNode* aSymbolNode, std::unique_ptr<LIB_PART>& aPart, EDEVICE* aDevice, int aGateNumber, string aGateName );
|
||||
LIB_CIRCLE* loadSymbolCircle( std::unique_ptr<LIB_PART>& aPart, wxXmlNode* aCircleNode, int aGateNumber );
|
||||
LIB_RECTANGLE* loadSymbolRectangle( std::unique_ptr<LIB_PART>& aPart, wxXmlNode* aRectNode, int aGateNumber );
|
||||
LIB_POLYLINE* loadSymbolPolyLine( std::unique_ptr<LIB_PART>& aPart, wxXmlNode* aPolygonNode, int aGateNumber );
|
||||
LIB_ITEM* loadSymbolWire( std::unique_ptr<LIB_PART>& aPart, wxXmlNode* aWireNode, int aGateNumber );
|
||||
LIB_PIN* loadPin( std::unique_ptr<LIB_PART>& aPart, wxXmlNode*, EPIN* epin, int aGateNumber );
|
||||
LIB_TEXT* loadSymbolText( std::unique_ptr<LIB_PART>& aPart, wxXmlNode* aLibText, int aGateNumber );
|
||||
|
||||
void loadTextAttributes( EDA_TEXT* aText, const ETEXT& aAttribs ) const;
|
||||
void loadFieldAttributes( LIB_FIELD* aField, const LIB_TEXT* aText ) const;
|
||||
|
||||
KIWAY* m_kiway; ///< For creating sub sheets.
|
||||
SCH_SHEET* m_rootSheet; ///< The root sheet of the schematic being loaded..
|
||||
SCH_SHEET* m_currentSheet; ///< The current sheet of the schematic being loaded..
|
||||
wxString m_version; ///< Eagle file version.
|
||||
wxFileName m_filename;
|
||||
PART_LIB* m_partlib; ///< symbol library for imported file.
|
||||
|
||||
EPART_MAP m_partlist;
|
||||
std::map<std::string, EAGLE_LIBRARY> m_eagleLibs;
|
||||
|
||||
std::map<std::string, int> m_netCounts;
|
||||
std::map<int, SCH_LAYER_ID> m_layerMap;
|
||||
};
|
||||
|
||||
#endif // _SCH_EAGLE_PLUGIN_H_
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
#include <sch_io_mgr.h>
|
||||
#include <sch_legacy_plugin.h>
|
||||
#include <sch_eagle_plugin.h>
|
||||
|
||||
#include <wildcards_and_files_ext.h>
|
||||
|
||||
|
@ -54,6 +55,8 @@ SCH_PLUGIN* SCH_IO_MGR::FindPlugin( SCH_FILE_T aFileType )
|
|||
{
|
||||
case SCH_LEGACY:
|
||||
return new SCH_LEGACY_PLUGIN();
|
||||
case SCH_EAGLE:
|
||||
return new SCH_EAGLE_PLUGIN();
|
||||
case SCH_KICAD:
|
||||
return NULL;
|
||||
}
|
||||
|
@ -85,6 +88,9 @@ const wxString SCH_IO_MGR::ShowType( SCH_FILE_T aType )
|
|||
|
||||
case SCH_LEGACY:
|
||||
return wxString( wxT( "Legacy" ) );
|
||||
|
||||
case SCH_EAGLE:
|
||||
return wxString( wxT( "EAGLE" ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -97,6 +103,8 @@ SCH_IO_MGR::SCH_FILE_T SCH_IO_MGR::EnumFromStr( const wxString& aType )
|
|||
|
||||
if( aType == wxT( "Legacy" ) )
|
||||
return SCH_LEGACY;
|
||||
else if( aType == wxT( "EAGLE" ) )
|
||||
return SCH_EAGLE;
|
||||
|
||||
// wxASSERT( blow up here )
|
||||
|
||||
|
@ -162,3 +170,6 @@ void SCH_IO_MGR::Save( SCH_FILE_T aFileType, const wxString& aFileName,
|
|||
|
||||
THROW_IO_ERROR( wxString::Format( FMT_NOTFOUND, ShowType( aFileType ).GetData() ) );
|
||||
}
|
||||
|
||||
|
||||
DECLARE_ENUM_VECTOR( SCH_IO_MGR, SCH_FILE_T );
|
||||
|
|
|
@ -24,7 +24,9 @@
|
|||
*/
|
||||
|
||||
#include <richio.h>
|
||||
#include <import_export.h>
|
||||
#include <map>
|
||||
#include <enum_vector.h>
|
||||
|
||||
|
||||
class SCH_SHEET;
|
||||
|
@ -49,15 +51,16 @@ public:
|
|||
* A set of file types that the #SCH_IO_MGR knows about, and for which there
|
||||
* has been a plugin written.
|
||||
*/
|
||||
enum SCH_FILE_T
|
||||
DEFINE_ENUM_VECTOR( SCH_FILE_T,
|
||||
{
|
||||
SCH_LEGACY, ///< Legacy Eeschema file formats prior to s-expression.
|
||||
SCH_KICAD, ///< The s-expression version of the schematic file formats.
|
||||
SCH_EAGLE, ///< Autodesk Eagle file format
|
||||
// Add your schematic type here.
|
||||
|
||||
// ALTIUM,
|
||||
// etc.
|
||||
};
|
||||
} );
|
||||
|
||||
/**
|
||||
* Return a #SCH_PLUGIN which the caller can use to import, export, save, or load
|
||||
|
@ -72,6 +75,7 @@ public:
|
|||
* @return the plugin corresponding to aFileType or NULL if not found.
|
||||
* Caller owns the returned object, and must call PluginRelease when done using it.
|
||||
*/
|
||||
APIEXPORT
|
||||
static SCH_PLUGIN* FindPlugin( SCH_FILE_T aFileType );
|
||||
|
||||
/**
|
||||
|
@ -481,6 +485,14 @@ public:
|
|||
*/
|
||||
virtual void SymbolLibOptions( PROPERTIES* aListToAppendTo ) const;
|
||||
|
||||
/**
|
||||
* Function CheckHeader
|
||||
* returns true if the first line in @a aFileName begins with the expected header
|
||||
* @param aFileName is the name of the file to use as input
|
||||
*
|
||||
*/
|
||||
virtual bool CheckHeader( const wxString& aFileName );
|
||||
|
||||
//-----</PUBLIC SCH_PLUGIN API>------------------------------------------------
|
||||
|
||||
|
||||
|
|
|
@ -51,8 +51,6 @@ typedef SCH_ITEMS::iterator SCH_ITEMS_ITR;
|
|||
typedef std::vector< SCH_ITEMS_ITR > SCH_ITEMS_ITRS;
|
||||
|
||||
|
||||
#define FMT_IU SCH_ITEM::FormatInternalUnits
|
||||
#define FMT_ANGLE SCH_ITEM::FormatAngle
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -3604,5 +3604,19 @@ void SCH_LEGACY_PLUGIN::SaveLibrary( const wxString& aLibraryPath, const PROPERT
|
|||
}
|
||||
|
||||
|
||||
bool SCH_LEGACY_PLUGIN::CheckHeader( const wxString& aFileName )
|
||||
{
|
||||
// Open file and check first line
|
||||
wxTextFile tempFile;
|
||||
|
||||
tempFile.Open( aFileName );
|
||||
wxString firstline;
|
||||
// read the first line
|
||||
firstline = tempFile.GetFirstLine();
|
||||
tempFile.Close();
|
||||
|
||||
return firstline.StartsWith( "EESchema" );
|
||||
}
|
||||
|
||||
const char* SCH_LEGACY_PLUGIN::PropBuffering = "buffering";
|
||||
const char* SCH_LEGACY_PLUGIN::PropNoDocFile = "no_doc_file";
|
||||
|
|
|
@ -124,6 +124,8 @@ public:
|
|||
const PROPERTIES* aProperties = NULL ) override;
|
||||
void SaveLibrary( const wxString& aLibraryPath, const PROPERTIES* aProperties = NULL ) override;
|
||||
|
||||
bool CheckHeader( const wxString& aFileName ) override;
|
||||
|
||||
private:
|
||||
void loadHierarchy( SCH_SHEET* aSheet );
|
||||
void loadHeader( FILE_LINE_READER& aReader, SCH_SCREEN* aScreen );
|
||||
|
|
|
@ -598,3 +598,9 @@ void SCH_LINE::SetPosition( const wxPoint& aPosition )
|
|||
m_end = m_end - ( m_start - aPosition );
|
||||
m_start = aPosition;
|
||||
}
|
||||
|
||||
|
||||
wxPoint SCH_LINE::MidPoint()
|
||||
{
|
||||
return wxPoint( ( m_start.x + m_end.x ) / 2, ( m_start.y + m_end.y ) / 2 );
|
||||
}
|
||||
|
|
|
@ -143,6 +143,8 @@ public:
|
|||
|
||||
void Plot( PLOTTER* aPlotter ) override;
|
||||
|
||||
wxPoint MidPoint();
|
||||
|
||||
EDA_ITEM* Clone() const override;
|
||||
|
||||
#if defined(DEBUG)
|
||||
|
|
|
@ -188,3 +188,11 @@ void SCH_PLUGIN::SymbolLibOptions( PROPERTIES* aListToAppendTo ) const
|
|||
) );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
bool SCH_PLUGIN::CheckHeader( const wxString& aFileName )
|
||||
{
|
||||
// not pure virtual so that plugins only have to implement subset of the SCH_PLUGIN interface.
|
||||
not_implemented( this, __FUNCTION__ );
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -223,6 +223,7 @@ BEGIN_EVENT_TABLE( SCH_EDIT_FRAME, EDA_DRAW_FRAME )
|
|||
EVT_MENU_RANGE( wxID_FILE1, wxID_FILE9, SCH_EDIT_FRAME::OnLoadFile )
|
||||
|
||||
EVT_MENU( ID_APPEND_PROJECT, SCH_EDIT_FRAME::OnAppendProject )
|
||||
EVT_MENU( ID_IMPORT_NON_KICAD_SCH, SCH_EDIT_FRAME::OnImportProject )
|
||||
|
||||
EVT_TOOL( ID_NEW_PROJECT, SCH_EDIT_FRAME::OnNewProject )
|
||||
EVT_TOOL( ID_LOAD_PROJECT, SCH_EDIT_FRAME::OnLoadProject )
|
||||
|
|
|
@ -532,7 +532,8 @@ public:
|
|||
bool CreateNetlist( int aFormat,
|
||||
const wxString& aFullFileName,
|
||||
unsigned aNetlistOptions,
|
||||
REPORTER* aReporter = NULL );
|
||||
REPORTER* aReporter = NULL,
|
||||
bool silent = false ) override;
|
||||
|
||||
/**
|
||||
* Function WriteNetListFile
|
||||
|
@ -784,6 +785,21 @@ public:
|
|||
|
||||
bool IsSearchCacheObsolete( const SCH_FIND_REPLACE_DATA& aSearchCriteria );
|
||||
|
||||
/**
|
||||
* Function ImportFile
|
||||
* load the given filename but sets the path to the current project path.
|
||||
* @param full filepath of file to be imported.
|
||||
* @param aFileType SCH_FILE_T value for filetype
|
||||
*/
|
||||
bool ImportFile( const wxString& aFileName, int aFileType ) override;
|
||||
|
||||
/**
|
||||
* Checks whether any of the screens has unsaved changes and asks the user
|
||||
* whether to save or drop them.
|
||||
* @return True if user decided to save or drop changes, false if the
|
||||
* operation should be cancelled.
|
||||
*/
|
||||
bool AskToSaveChanges();
|
||||
|
||||
private:
|
||||
|
||||
|
@ -868,6 +884,7 @@ private:
|
|||
void OnNewProject( wxCommandEvent& event );
|
||||
void OnLoadProject( wxCommandEvent& event );
|
||||
void OnAppendProject( wxCommandEvent& event );
|
||||
void OnImportProject( wxCommandEvent& event );
|
||||
void OnOpenPcbnew( wxCommandEvent& event );
|
||||
void OnOpenPcbModuleEditor( wxCommandEvent& event );
|
||||
void OnOpenCvpcb( wxCommandEvent& event );
|
||||
|
|
|
@ -35,9 +35,6 @@
|
|||
#include <gr_basic.h>
|
||||
#include <layers_id_colors_and_visibility.h>
|
||||
|
||||
/// Abbrevation for fomatting internal units to a string.
|
||||
#define FMT_IU BOARD_ITEM::FormatInternalUnits
|
||||
#define FMT_ANGLE BOARD_ITEM::FormatAngle
|
||||
|
||||
class BOARD;
|
||||
class BOARD_ITEM_CONTAINER;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
|
||||
* Copyright (C) 2012-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2017 CERN.
|
||||
* Copyright (C) 2017 CERN
|
||||
* @author Alejandro García Montoro <alejandro.garciamontoro@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
|
@ -44,9 +44,20 @@
|
|||
using std::string;
|
||||
|
||||
class MODULE;
|
||||
struct EINSTANCE;
|
||||
struct EPART;
|
||||
struct ETEXT;
|
||||
|
||||
typedef std::unordered_map< string, wxXmlNode* > NODE_MAP;
|
||||
typedef std::map< string, MODULE* > MODULE_MAP;
|
||||
typedef std::unordered_map<string, wxXmlNode*> NODE_MAP;
|
||||
typedef std::map<string, MODULE*> MODULE_MAP;
|
||||
typedef std::map<string, EINSTANCE*> EINSTANCE_MAP;
|
||||
typedef std::map<string, std::unique_ptr<EPART>> EPART_MAP;
|
||||
|
||||
static inline wxXmlNode* getChildrenNodes( NODE_MAP& aMap, const string& aName )
|
||||
{
|
||||
auto it = aMap.find( aName );
|
||||
return it == aMap.end() ? nullptr : it->second->GetChildren();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
|
@ -98,7 +109,7 @@ struct TRIPLET
|
|||
*/
|
||||
class XPATH
|
||||
{
|
||||
std::vector<TRIPLET> p;
|
||||
std::vector<TRIPLET> p;
|
||||
|
||||
public:
|
||||
void push( const char* aPathSegment, const char* aAttribute="" )
|
||||
|
@ -336,14 +347,34 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Function MapChildren
|
||||
* provides an easy access to the children of an XML node via their names.
|
||||
* @param currentNode is a pointer to a wxXmlNode, whose children will be mapped.
|
||||
* @return NODE_MAP - a map linking the name of each children to the children itself (via a
|
||||
* wxXmlNode*)
|
||||
*/
|
||||
NODE_MAP MapChildren( wxXmlNode* aCurrentNode );
|
||||
|
||||
/// Make a unique time stamp
|
||||
unsigned long EagleTimeStamp( wxXmlNode* aTree );
|
||||
|
||||
/// Computes module timestamp basing on its name, value and unit
|
||||
time_t EagleModuleTstamp( const string& aName, const string& aValue, int aUnit );
|
||||
|
||||
/// Convert an Eagle curve end to a KiCad center for S_ARC
|
||||
wxPoint ConvertArcCenter( const wxPoint& aStart, const wxPoint& aEnd, double aAngle );
|
||||
|
||||
// Pre-declare for typedefs
|
||||
struct EROT;
|
||||
|
||||
struct ECOORD;
|
||||
typedef OPTIONAL_XML_ATTRIBUTE<string> opt_string;
|
||||
typedef OPTIONAL_XML_ATTRIBUTE<int> opt_int;
|
||||
typedef OPTIONAL_XML_ATTRIBUTE<double> opt_double;
|
||||
typedef OPTIONAL_XML_ATTRIBUTE<bool> opt_bool;
|
||||
typedef OPTIONAL_XML_ATTRIBUTE<EROT> opt_erot;
|
||||
typedef OPTIONAL_XML_ATTRIBUTE<ECOORD> opt_ecoord;
|
||||
|
||||
|
||||
// All of the 'E'STRUCTS below merely hold Eagle XML information verbatim, in binary.
|
||||
|
@ -352,14 +383,78 @@ typedef OPTIONAL_XML_ATTRIBUTE<EROT> opt_erot;
|
|||
// forms of information in these 'E'STRUCTS. They are only binary forms
|
||||
// of the Eagle information in the corresponding Eagle XML nodes.
|
||||
|
||||
// Eagle coordinates
|
||||
struct ECOORD
|
||||
{
|
||||
enum UNIT
|
||||
{
|
||||
NM, ///< nanometers
|
||||
MM, ///< millimeters
|
||||
INCH, ///< inches
|
||||
MIL, ///< mils/thous
|
||||
};
|
||||
|
||||
///> Value expressed in nanometers
|
||||
long long int value;
|
||||
|
||||
///> Unit used for the value field
|
||||
static constexpr UNIT ECOORD_UNIT = NM;
|
||||
|
||||
ECOORD()
|
||||
: value( 0 )
|
||||
{
|
||||
}
|
||||
|
||||
ECOORD( int aValue, enum UNIT aUnit )
|
||||
: value( ToNanoMeters( aValue, aUnit ) )
|
||||
{
|
||||
}
|
||||
|
||||
ECOORD( const wxString& aValue, enum UNIT aUnit );
|
||||
|
||||
int ToSchUnits() const
|
||||
{
|
||||
// mils
|
||||
return value / 25400;
|
||||
}
|
||||
|
||||
int ToPcbUnits() const
|
||||
{
|
||||
// nanometers
|
||||
return value;
|
||||
}
|
||||
|
||||
float ToMm() const
|
||||
{
|
||||
return value / 1000000.0;
|
||||
}
|
||||
|
||||
ECOORD operator+( const ECOORD& aOther ) const
|
||||
{
|
||||
return ECOORD( value + aOther.value, ECOORD_UNIT );
|
||||
}
|
||||
|
||||
ECOORD operator-( const ECOORD& aOther ) const
|
||||
{
|
||||
return ECOORD( value - aOther.value, ECOORD_UNIT );
|
||||
}
|
||||
|
||||
bool operator==( const ECOORD& aOther ) const
|
||||
{
|
||||
return value == aOther.value;
|
||||
}
|
||||
|
||||
static long long int ToNanoMeters( int aValue, enum UNIT aUnit );
|
||||
};
|
||||
|
||||
|
||||
/// Eagle net
|
||||
struct ENET
|
||||
{
|
||||
int netcode;
|
||||
std::string netname;
|
||||
int netcode;
|
||||
string netname;
|
||||
|
||||
ENET( int aNetCode, const std::string& aNetName ) :
|
||||
ENET( int aNetCode, const string& aNetName ) :
|
||||
netcode( aNetCode ),
|
||||
netname( aNetName )
|
||||
{}
|
||||
|
@ -394,11 +489,11 @@ struct EROT
|
|||
/// Eagle wire
|
||||
struct EWIRE
|
||||
{
|
||||
double x1;
|
||||
double y1;
|
||||
double x2;
|
||||
double y2;
|
||||
double width;
|
||||
ECOORD x1;
|
||||
ECOORD y1;
|
||||
ECOORD x2;
|
||||
ECOORD y2;
|
||||
ECOORD width;
|
||||
LAYER_NUM layer;
|
||||
|
||||
// for style: (continuous | longdash | shortdash | dashdot)
|
||||
|
@ -422,15 +517,40 @@ struct EWIRE
|
|||
};
|
||||
|
||||
|
||||
/// Eagle Junction
|
||||
struct EJUNCTION
|
||||
{
|
||||
ECOORD x;
|
||||
ECOORD y;
|
||||
|
||||
EJUNCTION( wxXmlNode* aJunction);
|
||||
};
|
||||
|
||||
|
||||
/// Eagle label
|
||||
struct ELABEL
|
||||
{
|
||||
ECOORD x;
|
||||
ECOORD y;
|
||||
ECOORD size;
|
||||
LAYER_NUM layer;
|
||||
opt_erot rot;
|
||||
opt_string xref;
|
||||
wxString netname;
|
||||
|
||||
ELABEL( wxXmlNode* aLabel, const wxString& aNetName );
|
||||
};
|
||||
|
||||
|
||||
/// Eagle via
|
||||
struct EVIA
|
||||
{
|
||||
double x;
|
||||
double y;
|
||||
ECOORD x;
|
||||
ECOORD y;
|
||||
int layer_front_most; /// < extent
|
||||
int layer_back_most; /// < inclusive
|
||||
double drill;
|
||||
opt_double diam;
|
||||
ECOORD drill;
|
||||
opt_ecoord diam;
|
||||
opt_string shape;
|
||||
|
||||
EVIA( wxXmlNode* aVia );
|
||||
|
@ -440,10 +560,10 @@ struct EVIA
|
|||
/// Eagle circle
|
||||
struct ECIRCLE
|
||||
{
|
||||
double x;
|
||||
double y;
|
||||
double radius;
|
||||
double width;
|
||||
ECOORD x;
|
||||
ECOORD y;
|
||||
ECOORD radius;
|
||||
ECOORD width;
|
||||
LAYER_NUM layer;
|
||||
|
||||
ECIRCLE( wxXmlNode* aCircle );
|
||||
|
@ -453,10 +573,10 @@ struct ECIRCLE
|
|||
/// Eagle XML rectangle in binary
|
||||
struct ERECT
|
||||
{
|
||||
double x1;
|
||||
double y1;
|
||||
double x2;
|
||||
double y2;
|
||||
ECOORD x1;
|
||||
ECOORD y1;
|
||||
ECOORD x2;
|
||||
ECOORD y2;
|
||||
int layer;
|
||||
opt_erot rot;
|
||||
|
||||
|
@ -474,9 +594,9 @@ struct EATTR
|
|||
{
|
||||
string name;
|
||||
opt_string value;
|
||||
opt_double x;
|
||||
opt_double y;
|
||||
opt_double size;
|
||||
opt_ecoord x;
|
||||
opt_ecoord y;
|
||||
opt_ecoord size;
|
||||
opt_int layer;
|
||||
opt_double ratio;
|
||||
opt_erot rot;
|
||||
|
@ -488,6 +608,7 @@ struct EATTR
|
|||
BOTH,
|
||||
};
|
||||
opt_int display;
|
||||
opt_int align;
|
||||
|
||||
EATTR( wxXmlNode* aTree );
|
||||
EATTR() {}
|
||||
|
@ -497,12 +618,12 @@ struct EATTR
|
|||
/// Eagle dimension element
|
||||
struct EDIMENSION
|
||||
{
|
||||
double x1;
|
||||
double y1;
|
||||
double x2;
|
||||
double y2;
|
||||
double x3;
|
||||
double y3;
|
||||
ECOORD x1;
|
||||
ECOORD y1;
|
||||
ECOORD x2;
|
||||
ECOORD y2;
|
||||
ECOORD x3;
|
||||
ECOORD y3;
|
||||
int layer;
|
||||
|
||||
opt_string dimensionType;
|
||||
|
@ -515,9 +636,9 @@ struct EDIMENSION
|
|||
struct ETEXT
|
||||
{
|
||||
string text;
|
||||
double x;
|
||||
double y;
|
||||
double size;
|
||||
ECOORD x;
|
||||
ECOORD y;
|
||||
ECOORD size;
|
||||
int layer;
|
||||
opt_string font;
|
||||
opt_double ratio;
|
||||
|
@ -537,9 +658,12 @@ struct ETEXT
|
|||
BOTTOM_RIGHT = -TOP_LEFT,
|
||||
};
|
||||
|
||||
opt_int align;
|
||||
opt_int align;
|
||||
|
||||
ETEXT( wxXmlNode* aText );
|
||||
|
||||
/// Calculate text size based on font type and size
|
||||
wxSize ConvertSize() const;
|
||||
};
|
||||
|
||||
|
||||
|
@ -547,10 +671,10 @@ struct ETEXT
|
|||
struct EPAD
|
||||
{
|
||||
string name;
|
||||
double x;
|
||||
double y;
|
||||
double drill;
|
||||
opt_double diameter;
|
||||
ECOORD x;
|
||||
ECOORD y;
|
||||
ECOORD drill;
|
||||
opt_ecoord diameter;
|
||||
|
||||
// for shape: (square | round | octagon | long | offset)
|
||||
enum {
|
||||
|
@ -574,10 +698,10 @@ struct EPAD
|
|||
struct ESMD
|
||||
{
|
||||
string name;
|
||||
double x;
|
||||
double y;
|
||||
double dx;
|
||||
double dy;
|
||||
ECOORD x;
|
||||
ECOORD y;
|
||||
ECOORD dx;
|
||||
ECOORD dy;
|
||||
int layer;
|
||||
opt_int roundness;
|
||||
opt_erot rot;
|
||||
|
@ -589,11 +713,29 @@ struct ESMD
|
|||
};
|
||||
|
||||
|
||||
/// Eagle pin element
|
||||
struct EPIN
|
||||
{
|
||||
string name;
|
||||
ECOORD x;
|
||||
ECOORD y;
|
||||
|
||||
opt_string visible;
|
||||
opt_string length;
|
||||
opt_string direction;
|
||||
opt_string function;
|
||||
opt_int swaplevel;
|
||||
opt_erot rot;
|
||||
|
||||
EPIN( wxXmlNode* aPin );
|
||||
};
|
||||
|
||||
|
||||
/// Eagle vertex
|
||||
struct EVERTEX
|
||||
{
|
||||
double x;
|
||||
double y;
|
||||
ECOORD x;
|
||||
ECOORD y;
|
||||
|
||||
EVERTEX( wxXmlNode* aVertex );
|
||||
};
|
||||
|
@ -602,9 +744,9 @@ struct EVERTEX
|
|||
/// Eagle polygon, without vertices which are parsed as needed
|
||||
struct EPOLYGON
|
||||
{
|
||||
double width;
|
||||
ECOORD width;
|
||||
int layer;
|
||||
opt_double spacing;
|
||||
opt_ecoord spacing;
|
||||
|
||||
// KiCad priority is opposite of Eagle rank, that is:
|
||||
// - Eagle Low rank drawn first
|
||||
|
@ -619,7 +761,7 @@ struct EPOLYGON
|
|||
CUTOUT,
|
||||
};
|
||||
int pour;
|
||||
opt_double isolate;
|
||||
opt_ecoord isolate;
|
||||
opt_bool orphans;
|
||||
opt_bool thermals;
|
||||
opt_int rank;
|
||||
|
@ -631,9 +773,9 @@ struct EPOLYGON
|
|||
/// Eagle hole element
|
||||
struct EHOLE
|
||||
{
|
||||
double x;
|
||||
double y;
|
||||
double drill;
|
||||
ECOORD x;
|
||||
ECOORD y;
|
||||
ECOORD drill;
|
||||
|
||||
EHOLE( wxXmlNode* aHole );
|
||||
};
|
||||
|
@ -646,8 +788,8 @@ struct EELEMENT
|
|||
string library;
|
||||
string package;
|
||||
string value;
|
||||
double x;
|
||||
double y;
|
||||
ECOORD x;
|
||||
ECOORD y;
|
||||
opt_bool locked;
|
||||
opt_bool smashed;
|
||||
opt_erot rot;
|
||||
|
@ -738,23 +880,151 @@ struct EAGLE_LAYER
|
|||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Function MapChildren
|
||||
* provides an easy access to the children of an XML node via their names.
|
||||
* @param currentNode is a pointer to a wxXmlNode, whose children will be mapped.
|
||||
* @return NODE_MAP - a map linking the name of each children to the children itself (via a
|
||||
* wxXmlNode*)
|
||||
*/
|
||||
NODE_MAP MapChildren( wxXmlNode* currentNode );
|
||||
|
||||
/// Assemble a two part key as a simple concatenation of aFirst and aSecond parts,
|
||||
/// using a separator.
|
||||
string makeKey( const string& aFirst, const string& aSecond );
|
||||
struct EPART
|
||||
{
|
||||
/*
|
||||
* <!ELEMENT part (attribute*, variant*)>
|
||||
* <!ATTLIST part
|
||||
* name %String; #REQUIRED
|
||||
* library %String; #REQUIRED
|
||||
* deviceset %String; #REQUIRED
|
||||
* device %String; #REQUIRED
|
||||
* technology %String; ""
|
||||
* value %String; #IMPLIED
|
||||
* >
|
||||
*/
|
||||
|
||||
/// Make a unique time stamp
|
||||
unsigned long timeStamp( wxXmlNode* aTree );
|
||||
string name;
|
||||
string library;
|
||||
string deviceset;
|
||||
string device;
|
||||
opt_string technology;
|
||||
opt_string value;
|
||||
|
||||
EPART( wxXmlNode* aPart );
|
||||
};
|
||||
|
||||
|
||||
struct EINSTANCE
|
||||
{
|
||||
/*
|
||||
* <!ELEMENT instance (attribute)*>
|
||||
* <!ATTLIST instance
|
||||
* part %String; #REQUIRED
|
||||
* gate %String; #REQUIRED
|
||||
* x %Coord; #REQUIRED
|
||||
* y %Coord; #REQUIRED
|
||||
* smashed %Bool; "no"
|
||||
* rot %Rotation; "R0"
|
||||
* >
|
||||
*/
|
||||
|
||||
string part;
|
||||
string gate;
|
||||
ECOORD x;
|
||||
ECOORD y;
|
||||
opt_bool smashed;
|
||||
opt_erot rot;
|
||||
|
||||
EINSTANCE( wxXmlNode* aInstance );
|
||||
};
|
||||
|
||||
|
||||
struct EGATE
|
||||
{
|
||||
/*
|
||||
* <!ELEMENT gate EMPTY>
|
||||
* <!ATTLIST gate
|
||||
* name %String; #REQUIRED
|
||||
* symbol %String; #REQUIRED
|
||||
* x %Coord; #REQUIRED
|
||||
* y %Coord; #REQUIRED
|
||||
* addlevel %GateAddLevel; "next"
|
||||
* swaplevel %Int; "0"
|
||||
* >
|
||||
*/
|
||||
|
||||
string name;
|
||||
string symbol;
|
||||
|
||||
ECOORD x;
|
||||
ECOORD y;
|
||||
|
||||
opt_int addlevel;
|
||||
opt_int swaplevel;
|
||||
|
||||
enum
|
||||
{
|
||||
MUST,
|
||||
CAN,
|
||||
NEXT,
|
||||
REQUEST,
|
||||
ALWAYS
|
||||
};
|
||||
|
||||
EGATE( wxXmlNode* aGate );
|
||||
};
|
||||
|
||||
|
||||
struct ECONNECT
|
||||
{
|
||||
/*
|
||||
* <!ELEMENT connect EMPTY>
|
||||
* <!ATTLIST connect
|
||||
* gate %String; #REQUIRED
|
||||
* pin %String; #REQUIRED
|
||||
* pad %String; #REQUIRED
|
||||
* route %ContactRoute; "all"
|
||||
* >
|
||||
*/
|
||||
string gate;
|
||||
string pin;
|
||||
string pad;
|
||||
int contactroute;
|
||||
|
||||
ECONNECT( wxXmlNode* aConnect );
|
||||
};
|
||||
|
||||
|
||||
struct EDEVICE
|
||||
{
|
||||
/*
|
||||
<!ELEMENT device (connects?, technologies?)>
|
||||
<!ATTLIST device
|
||||
name %String; ""
|
||||
package %String; #IMPLIED
|
||||
>
|
||||
*/
|
||||
string name;
|
||||
opt_string package;
|
||||
|
||||
std::vector<ECONNECT> connects;
|
||||
|
||||
EDEVICE( wxXmlNode* aDevice );
|
||||
};
|
||||
|
||||
|
||||
struct EDEVICE_SET
|
||||
{
|
||||
/*
|
||||
<!ELEMENT deviceset (description?, gates, devices)>
|
||||
<!ATTLIST deviceset
|
||||
name %String; #REQUIRED
|
||||
prefix %String; ""
|
||||
uservalue %Bool; "no"
|
||||
>
|
||||
*/
|
||||
|
||||
string name;
|
||||
opt_string prefix;
|
||||
opt_bool uservalue;
|
||||
//std::vector<EDEVICE> devices;
|
||||
//std::vector<EGATE> gates;
|
||||
|
||||
|
||||
EDEVICE_SET( wxXmlNode* aDeviceSet );
|
||||
};
|
||||
|
||||
/// Convert an Eagle curve end to a KiCad center for S_ARC
|
||||
wxPoint kicad_arc_center( const wxPoint& aStart, const wxPoint& aEnd, double aAngle );
|
||||
|
||||
#endif // _EAGLE_PARSER_H_
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2017 CERN
|
||||
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 3
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef DEFINE_ENUM_VECTOR
|
||||
|
||||
/**
|
||||
* Macro to create const vectors containing enum values to enable easy iteration.
|
||||
*
|
||||
* Usage:
|
||||
* [header]
|
||||
* class A {
|
||||
* DEFINE_ENUM_VECTOR( COLORS, { RED, GREEN, BLUE } );
|
||||
* };
|
||||
*
|
||||
* [source]
|
||||
* for( auto color : A::COLORS_vector ) {
|
||||
* // do sth with color
|
||||
* }
|
||||
*
|
||||
* DECLARE_ENUM_VECTOR( COLORS );
|
||||
*/
|
||||
#define DEFINE_ENUM_VECTOR(enum_name, ...) \
|
||||
enum enum_name __VA_ARGS__; \
|
||||
static constexpr enum_name enum_name##_vector[] = __VA_ARGS__;
|
||||
|
||||
#define DECLARE_ENUM_VECTOR(class_name, enum_name) \
|
||||
constexpr class_name::enum_name class_name::enum_name##_vector[];
|
||||
|
||||
#endif
|
|
@ -54,7 +54,7 @@ public:
|
|||
}
|
||||
|
||||
FP_LIB_TABLE_ROW() :
|
||||
type( IO_MGR::KICAD )
|
||||
type( IO_MGR::KICAD_SEXP )
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -179,6 +179,49 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function ImportFile
|
||||
* load the given filename but sets the path to the current project path.
|
||||
* @param full filepath of file to be imported.
|
||||
* @param aFileType enum value for filetype
|
||||
*/
|
||||
VTBL_ENTRY bool ImportFile( const wxString& aFileName, int aFileType )
|
||||
{
|
||||
// overload me for your wxFrame type.
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function ReadPcbNetlist
|
||||
* provides access to PcbNew's function ReadPcbNetlist.
|
||||
*/
|
||||
VTBL_ENTRY void ReadPcbNetlist( const wxString& aNetlistFileName,
|
||||
const wxString& aCmpFileName,
|
||||
REPORTER* aReporter,
|
||||
bool aChangeFootprint,
|
||||
bool aDeleteBadTracks,
|
||||
bool aDeleteExtraFootprints,
|
||||
bool aSelectByTimestamp,
|
||||
bool aDeleteSinglePadNets,
|
||||
bool aIsDryRun )
|
||||
{
|
||||
};
|
||||
|
||||
/**
|
||||
* Function ReadPcbNetlist
|
||||
* provides access to Eeschema's function CreateNetlist.
|
||||
*/
|
||||
VTBL_ENTRY bool CreateNetlist( int aFormat,
|
||||
const wxString& aFullFileName,
|
||||
unsigned aNetlistOptions,
|
||||
REPORTER* aReporter = NULL,
|
||||
bool silent = false )
|
||||
{
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Function ShowModal
|
||||
* puts up this wxFrame as if it were a modal dialog, with all other instantiated
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2017 KiCad Developers, see change_log.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef UNIT_FORMAT_H
|
||||
#define UNIT_FORMAT_H
|
||||
|
||||
// Conversion to application internal units defined at build time.
|
||||
#if defined( PCBNEW )
|
||||
#include <class_board_item.h>
|
||||
#define FMT_IU BOARD_ITEM::FormatInternalUnits
|
||||
#define FMT_ANGLE BOARD_ITEM::FormatAngle
|
||||
#elif defined( EESCHEMA )
|
||||
#include <sch_item_struct.h>
|
||||
#define FMT_IU SCH_ITEM::FormatInternalUnits
|
||||
#define FMT_ANGLE SCH_ITEM::FormatAngle
|
||||
#elif defined( GERBVIEW )
|
||||
#elif defined( PL_EDITOR )
|
||||
#include <base_units.h>
|
||||
#define FMT_IU Double2Str
|
||||
#else
|
||||
#error "Cannot resolve units formatting due to no definition of EESCHEMA or PCBNEW."
|
||||
#endif
|
||||
|
||||
#endif /* UNIT_FORMAT_H */
|
|
@ -88,6 +88,8 @@ extern const wxString CsvFileWildcard;
|
|||
extern const wxString LegacyPcbFileWildcard;
|
||||
extern const wxString PcbFileWildcard;
|
||||
extern const wxString EaglePcbFileWildcard;
|
||||
extern const wxString EagleSchematicFileWildcard;
|
||||
extern const wxString EagleFilesWildcard;
|
||||
extern const wxString PCadPcbFileWildcard;
|
||||
extern const wxString PdfFileWildcard;
|
||||
extern const wxString PSFileWildcard;
|
||||
|
|
|
@ -7,6 +7,8 @@ add_definitions( -DKICAD )
|
|||
|
||||
include_directories( BEFORE ${INC_BEFORE} )
|
||||
include_directories(
|
||||
../pcbnew
|
||||
../eeschema
|
||||
${INC_AFTER}
|
||||
)
|
||||
|
||||
|
@ -25,6 +27,7 @@ set( KICAD_SRCS
|
|||
prjconfig.cpp
|
||||
project_template.cpp
|
||||
tree_project_frame.cpp
|
||||
import_project.cpp
|
||||
)
|
||||
|
||||
if( MINGW )
|
||||
|
|
|
@ -0,0 +1,212 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2017 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* @author Russell Oliver <roliver8143@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file import_project.cpp
|
||||
* @brief routines for importing an eagle project
|
||||
*/
|
||||
|
||||
|
||||
#include <wx/filename.h>
|
||||
#include <wx/dir.h>
|
||||
#include <wx/log.h>
|
||||
#include <wx/stdpaths.h>
|
||||
#include <wx/string.h>
|
||||
|
||||
#include <common.h>
|
||||
#include <confirm.h>
|
||||
#include <hotkeys_basic.h>
|
||||
#include <kiway.h>
|
||||
#include <richio.h>
|
||||
#include <wildcards_and_files_ext.h>
|
||||
#include <systemdirsappend.h>
|
||||
#include <kiway_player.h>
|
||||
#include <stdexcept>
|
||||
#include "pgm_kicad.h"
|
||||
|
||||
#include <io_mgr.h>
|
||||
#include <sch_io_mgr.h>
|
||||
#include <wxPcbStruct.h>
|
||||
#include <schframe.h>
|
||||
#include <netlist.h>
|
||||
|
||||
class PCB_EDIT_FRAME;
|
||||
|
||||
#include "kicad.h"
|
||||
|
||||
void KICAD_MANAGER_FRAME::OnImportEagleFiles( wxCommandEvent& event )
|
||||
{
|
||||
// Close other windows.
|
||||
if( !Kiway.PlayersClose( false ) )
|
||||
return;
|
||||
|
||||
|
||||
wxString title = _( "Import Eagle Project Files" );
|
||||
int style = wxFD_OPEN | wxFD_FILE_MUST_EXIST;
|
||||
wxString default_dir = GetMruPath();
|
||||
|
||||
ClearMsg();
|
||||
|
||||
wxFileDialog schdlg( this, title, default_dir, wxEmptyString,
|
||||
EagleFilesWildcard, style );
|
||||
|
||||
if( schdlg.ShowModal() == wxID_CANCEL )
|
||||
return;
|
||||
|
||||
|
||||
wxFileName sch( schdlg.GetPath() );
|
||||
|
||||
sch.SetExt( SchematicFileExtension );
|
||||
|
||||
|
||||
wxString protitle = _( "Kicad Project Destination" );
|
||||
|
||||
wxFileDialog prodlg( this, protitle, sch.GetPath(), sch.GetName(),
|
||||
ProjectFileWildcard, wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
|
||||
|
||||
if( prodlg.ShowModal() == wxID_CANCEL )
|
||||
return;
|
||||
|
||||
wxFileName pro( prodlg.GetPath() );
|
||||
// Check if the project directory is empty
|
||||
wxDir directory( pro.GetPath() );
|
||||
|
||||
if( directory.HasFiles() )
|
||||
{
|
||||
wxString msg = _( "The selected directory is not empty. We recommend you "
|
||||
"create projects in their own clean directory.\n\nDo you "
|
||||
"want to create a new empty directory for the project?" );
|
||||
|
||||
if( IsOK( this, msg ) )
|
||||
{
|
||||
// Append a new directory with the same name of the project file
|
||||
// and try to create it
|
||||
pro.AppendDir( pro.GetName() );
|
||||
|
||||
if( !wxMkdir( pro.GetPath() ) )
|
||||
// There was a problem, undo
|
||||
pro.RemoveLastDir();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
wxFileName pcb( sch );
|
||||
wxFileName netlist( pro );
|
||||
pro.SetExt( ProjectFileExtension ); // enforce extension
|
||||
pcb.SetExt( LegacyPcbFileExtension ); // enforce extension
|
||||
netlist.SetExt( NetlistFileExtension );
|
||||
|
||||
if( !pro.IsAbsolute() )
|
||||
pro.MakeAbsolute();
|
||||
|
||||
SetProjectFileName( pro.GetFullPath() );
|
||||
|
||||
wxString prj_filename = GetProjectFileName();
|
||||
|
||||
wxString sch_filename = sch.GetFullPath();
|
||||
|
||||
if( sch.FileExists() )
|
||||
{
|
||||
SCH_EDIT_FRAME* schframe = (SCH_EDIT_FRAME*) Kiway.Player( FRAME_SCH, false );
|
||||
|
||||
if( !schframe )
|
||||
{
|
||||
try
|
||||
{
|
||||
schframe = (SCH_EDIT_FRAME*) Kiway.Player( FRAME_SCH, true );
|
||||
}
|
||||
catch( IO_ERROR err )
|
||||
{
|
||||
wxMessageBox( _( "Eeschema failed to load:\n" ) + err.What(),
|
||||
_( "KiCad Error" ), wxOK | wxICON_ERROR, this );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
schframe->ImportFile( sch_filename, SCH_IO_MGR::SCH_EAGLE );
|
||||
|
||||
if( !schframe->IsShown() ) // the frame exists, (created by the dialog field editor)
|
||||
// but no project loaded.
|
||||
{
|
||||
schframe->Show( true );
|
||||
}
|
||||
|
||||
if( schframe->IsIconized() )
|
||||
schframe->Iconize( false );
|
||||
|
||||
schframe->Raise();
|
||||
|
||||
schframe->CreateNetlist( NET_TYPE_PCBNEW, netlist.GetFullPath(), 0, NULL, true );
|
||||
}
|
||||
|
||||
if( pcb.FileExists() )
|
||||
{
|
||||
PCB_EDIT_FRAME* pcbframe = (PCB_EDIT_FRAME*) Kiway.Player( FRAME_PCB, false );
|
||||
|
||||
if( !pcbframe )
|
||||
{
|
||||
try
|
||||
{
|
||||
pcbframe = (PCB_EDIT_FRAME*) Kiway.Player( FRAME_PCB, true );
|
||||
}
|
||||
catch( IO_ERROR err )
|
||||
{
|
||||
wxMessageBox( _( "Pcbnew failed to load:\n" ) + err.What(), _( "KiCad Error" ),
|
||||
wxOK | wxICON_ERROR, this );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// a pcb frame can be already existing, but not yet used.
|
||||
// this is the case when running the footprint editor, or the footprint viewer first
|
||||
// if the frame is not visible, the board is not yet loaded
|
||||
if( !pcbframe->IsVisible() )
|
||||
{
|
||||
pcbframe->ImportFile( pcb.GetFullPath(), IO_MGR::EAGLE );
|
||||
pcbframe->Show( true );
|
||||
}
|
||||
|
||||
// On Windows, Raise() does not bring the window on screen, when iconized
|
||||
if( pcbframe->IsIconized() )
|
||||
pcbframe->Iconize( false );
|
||||
|
||||
pcbframe->Raise();
|
||||
|
||||
if( netlist.FileExists() )
|
||||
{
|
||||
pcbframe->ReadPcbNetlist( netlist.GetFullPath(),
|
||||
wxEmptyString,
|
||||
NULL,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false );
|
||||
}
|
||||
}
|
||||
|
||||
ReCreateTreePrj();
|
||||
}
|
|
@ -123,6 +123,7 @@ enum id_kicad_frm {
|
|||
ID_SAVE_AND_ZIP_FILES,
|
||||
ID_READ_ZIP_ARCHIVE,
|
||||
ID_INIT_WATCHED_PATHS,
|
||||
ID_IMPORT_EAGLE_PROJECT,
|
||||
|
||||
// Please, verify: the number of items in this list should be
|
||||
// less than ROOM_FOR_KICADMANAGER (see id.h)
|
||||
|
@ -194,6 +195,11 @@ public:
|
|||
void ReCreateMenuBar() override;
|
||||
void RecreateBaseHToolbar();
|
||||
|
||||
/**
|
||||
* Open dialog to import Eagle schematic and board files.
|
||||
*/
|
||||
void OnImportEagleFiles( wxCommandEvent& event );
|
||||
|
||||
/**
|
||||
* Displays \a aText in the text panel.
|
||||
*
|
||||
|
|
|
@ -66,6 +66,7 @@ BEGIN_EVENT_TABLE( KICAD_MANAGER_FRAME, EDA_BASE_FRAME )
|
|||
EVT_MENU( wxID_INDEX, KICAD_MANAGER_FRAME::GetKicadHelp )
|
||||
EVT_MENU( ID_HELP_GET_INVOLVED, KICAD_MANAGER_FRAME::GetKicadContribute )
|
||||
EVT_MENU( wxID_ABOUT, KICAD_MANAGER_FRAME::GetKicadAbout )
|
||||
EVT_MENU( ID_IMPORT_EAGLE_PROJECT, KICAD_MANAGER_FRAME::OnImportEagleFiles )
|
||||
|
||||
// Range menu events
|
||||
EVT_MENU_RANGE( ID_LANGUAGE_CHOICE, ID_LANGUAGE_CHOICE_END,
|
||||
|
@ -265,7 +266,21 @@ void KICAD_MANAGER_FRAME::ReCreateMenuBar()
|
|||
KiBitmap( save_project_xpm ) );
|
||||
#endif
|
||||
|
||||
// Separator
|
||||
fileMenu->AppendSeparator();
|
||||
wxMenu* importprjSubMenu = new wxMenu();
|
||||
|
||||
AddMenuItem( importprjSubMenu, ID_IMPORT_EAGLE_PROJECT, _( "Eagle CAD" ),
|
||||
_( "Import Eagle CAD XML schematic and board" ),
|
||||
KiBitmap( new_project_xpm ) );
|
||||
|
||||
|
||||
AddMenuItem( fileMenu, importprjSubMenu,
|
||||
wxID_ANY,
|
||||
_( "Import Project" ),
|
||||
_( "Import project files from other software" ),
|
||||
KiBitmap( new_project_xpm ) );
|
||||
|
||||
|
||||
fileMenu->AppendSeparator();
|
||||
|
||||
// Archive
|
||||
|
|
|
@ -33,6 +33,10 @@
|
|||
#include <class_board.h>
|
||||
#include <class_netclass.h>
|
||||
|
||||
/// Abbrevation for fomatting internal units to a string.
|
||||
#define FMT_IU BOARD_ITEM::FormatInternalUnits
|
||||
#define FMT_ANGLE BOARD_ITEM::FormatAngle
|
||||
|
||||
|
||||
// This will get mapped to "kicad_default" in the specctra_export.
|
||||
const char NETCLASS::Default[] = "Default";
|
||||
|
|
|
@ -185,7 +185,7 @@ public:
|
|||
|
||||
wxArrayString choices;
|
||||
|
||||
choices.Add( IO_MGR::ShowType( IO_MGR::KICAD ) );
|
||||
choices.Add( IO_MGR::ShowType( IO_MGR::KICAD_SEXP ) );
|
||||
choices.Add( IO_MGR::ShowType( IO_MGR::GITHUB ) );
|
||||
choices.Add( IO_MGR::ShowType( IO_MGR::LEGACY ) );
|
||||
choices.Add( IO_MGR::ShowType( IO_MGR::EAGLE ) );
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include <macros.h>
|
||||
#include <wxBasePcbFrame.h>
|
||||
#include <base_units.h>
|
||||
#include <unit_format.h>
|
||||
#include <gr_basic.h>
|
||||
|
||||
#include <class_board.h>
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include <pcbnew.h>
|
||||
#include <wxBasePcbFrame.h>
|
||||
#include <base_units.h>
|
||||
#include <unit_format.h>
|
||||
#include <board_commit.h>
|
||||
|
||||
#include <class_board.h>
|
||||
|
|
|
@ -65,7 +65,7 @@ static const struct
|
|||
IO_MGR::PCB_FILE_T m_Plugin;
|
||||
} fileFilters[FILTER_COUNT] =
|
||||
{
|
||||
{ "KiCad (folder with .kicad_mod files)", "kicad_mod", false, IO_MGR::KICAD },
|
||||
{ "KiCad (folder with .kicad_mod files)", "kicad_mod", false, IO_MGR::KICAD_SEXP },
|
||||
{ "Eagle 6.x (*.lbr)", "lbr", true, IO_MGR::EAGLE },
|
||||
{ "KiCad legacy (*.mod)", "mod", true, IO_MGR::LEGACY },
|
||||
{ "Geda (folder with *.fp files)", "fp", false, IO_MGR::GEDA_PCB },
|
||||
|
@ -206,7 +206,7 @@ wxString WIZARD_FPLIB_TABLE::LIBRARY::GetPluginName() const
|
|||
case IO_MGR::LEGACY:
|
||||
return wxT( "Legacy" );
|
||||
|
||||
case IO_MGR::KICAD:
|
||||
case IO_MGR::KICAD_SEXP:
|
||||
return wxT( "KiCad" );
|
||||
|
||||
case IO_MGR::EAGLE:
|
||||
|
@ -544,7 +544,7 @@ void WIZARD_FPLIB_TABLE::OnWizardFinished( wxWizardEvent& aEvent )
|
|||
wxString path = it->GetAbsolutePath();
|
||||
path.Replace( GetGithubURL(), getDownloadDir() );
|
||||
it->setPath( path );
|
||||
it->setPluginType( IO_MGR::KICAD );
|
||||
it->setPluginType( IO_MGR::KICAD_SEXP );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -654,7 +654,7 @@ bool WIZARD_FPLIB_TABLE::downloadGithubLibsFromList( wxArrayString& aUrlList,
|
|||
try
|
||||
{
|
||||
PLUGIN::RELEASER src( IO_MGR::PluginFind( IO_MGR::GITHUB ) );
|
||||
PLUGIN::RELEASER dst( IO_MGR::PluginFind( IO_MGR::KICAD ) );
|
||||
PLUGIN::RELEASER dst( IO_MGR::PluginFind( IO_MGR::KICAD_SEXP ) );
|
||||
|
||||
wxArrayString footprints;
|
||||
|
||||
|
|
|
@ -83,15 +83,23 @@ typedef MODULE_MAP::const_iterator MODULE_CITER;
|
|||
|
||||
/// Parse an eagle distance which is either mm, or mils if there is "mil" suffix.
|
||||
/// Return is in BIU.
|
||||
static double parseEagle( const wxString& aDistance )
|
||||
static int parseEagle( const wxString& aDistance )
|
||||
{
|
||||
double ret = strtod( aDistance.c_str(), NULL );
|
||||
if( aDistance.npos != aDistance.find( "mil" ) )
|
||||
ret = IU_PER_MILS * ret;
|
||||
else
|
||||
ret = IU_PER_MM * ret;
|
||||
ECOORD::UNIT unit = ( aDistance.npos != aDistance.find( "mil" ) )
|
||||
? ECOORD::UNIT::MIL : ECOORD::UNIT::MM;
|
||||
|
||||
return ret;
|
||||
ECOORD coord( aDistance, unit );
|
||||
|
||||
return coord.ToPcbUnits();
|
||||
}
|
||||
|
||||
|
||||
/// Assemble a two part key as a simple concatenation of aFirst and aSecond parts,
|
||||
/// using a separator.
|
||||
static string makeKey( const string& aFirst, const string& aSecond )
|
||||
{
|
||||
string key = aFirst + '\x02' + aSecond;
|
||||
return key;
|
||||
}
|
||||
|
||||
|
||||
|
@ -137,7 +145,6 @@ EAGLE_PLUGIN::EAGLE_PLUGIN() :
|
|||
m_mod_time( wxDateTime::Now() )
|
||||
{
|
||||
init( NULL );
|
||||
|
||||
clear_cu_map();
|
||||
}
|
||||
|
||||
|
@ -162,16 +169,10 @@ const wxString EAGLE_PLUGIN::GetFileExtension() const
|
|||
}
|
||||
|
||||
|
||||
int inline EAGLE_PLUGIN::kicad( double d ) const
|
||||
{
|
||||
return KiROUND( biu_per_mm * d );
|
||||
}
|
||||
|
||||
|
||||
wxSize inline EAGLE_PLUGIN::kicad_fontz( double d ) const
|
||||
wxSize inline EAGLE_PLUGIN::kicad_fontz( const ECOORD& d ) const
|
||||
{
|
||||
// texts seem to better match eagle when scaled down by 0.95
|
||||
int kz = kicad( d ) * 95 / 100;
|
||||
int kz = d.ToPcbUnits() * 95 / 100;
|
||||
return wxSize( kz, kz );
|
||||
}
|
||||
|
||||
|
@ -277,8 +278,6 @@ void EAGLE_PLUGIN::init( const PROPERTIES* aProperties )
|
|||
m_board = NULL;
|
||||
m_props = aProperties;
|
||||
|
||||
mm_per_biu = 1/IU_PER_MM;
|
||||
biu_per_mm = IU_PER_MM;
|
||||
|
||||
delete m_rules;
|
||||
m_rules = new ERULES();
|
||||
|
@ -354,19 +353,19 @@ void EAGLE_PLUGIN::loadDesignRules( wxXmlNode* aDesignRules )
|
|||
|
||||
void EAGLE_PLUGIN::loadLayerDefs( wxXmlNode* aLayers )
|
||||
{
|
||||
typedef std::vector<ELAYER> ELAYERS;
|
||||
typedef ELAYERS::const_iterator EITER;
|
||||
|
||||
ELAYERS cu; // copper layers
|
||||
ELAYERS cu; // copper layers
|
||||
|
||||
// Get the first layer and iterate
|
||||
wxXmlNode* layerNode = aLayers->GetChildren();
|
||||
|
||||
// find the subset of layers that are copper, and active
|
||||
m_eagleLayers.clear();
|
||||
|
||||
while( layerNode )
|
||||
{
|
||||
ELAYER elayer( layerNode );
|
||||
ELAYER elayer( layerNode );
|
||||
m_eagleLayers.insert( std::make_pair( elayer.number, elayer ) );
|
||||
|
||||
// find the subset of layers that are copper and active
|
||||
if( elayer.number >= 1 && elayer.number <= 16 && ( !elayer.active || *elayer.active ) )
|
||||
{
|
||||
cu.push_back( elayer );
|
||||
|
@ -457,7 +456,7 @@ void EAGLE_PLUGIN::loadPlain( wxXmlNode* aGraphics )
|
|||
}
|
||||
else
|
||||
{
|
||||
wxPoint center = kicad_arc_center( start, end, *w.curve);
|
||||
wxPoint center = ConvertArcCenter( start, end, *w.curve );
|
||||
|
||||
dseg->SetShape( S_ARC );
|
||||
dseg->SetStart( center );
|
||||
|
@ -465,7 +464,7 @@ void EAGLE_PLUGIN::loadPlain( wxXmlNode* aGraphics )
|
|||
dseg->SetAngle( *w.curve * -10.0 ); // KiCad rotates the other way
|
||||
}
|
||||
|
||||
dseg->SetTimeStamp( timeStamp( gr ) );
|
||||
dseg->SetTimeStamp( EagleTimeStamp( gr ) );
|
||||
dseg->SetLayer( layer );
|
||||
dseg->SetWidth( Millimeter2iu( DEFAULT_PCB_EDGE_THICKNESS ) );
|
||||
}
|
||||
|
@ -484,15 +483,15 @@ void EAGLE_PLUGIN::loadPlain( wxXmlNode* aGraphics )
|
|||
m_board->Add( pcbtxt, ADD_APPEND );
|
||||
|
||||
pcbtxt->SetLayer( layer );
|
||||
pcbtxt->SetTimeStamp( timeStamp( gr ) );
|
||||
pcbtxt->SetTimeStamp( EagleTimeStamp( gr ) );
|
||||
pcbtxt->SetText( FROM_UTF8( t.text.c_str() ) );
|
||||
pcbtxt->SetTextPos( wxPoint( kicad_x( t.x ), kicad_y( t.y ) ) );
|
||||
|
||||
pcbtxt->SetTextSize( kicad_fontz( t.size ) );
|
||||
|
||||
double ratio = t.ratio ? *t.ratio : 8; // DTD says 8 is default
|
||||
double ratio = t.ratio ? *t.ratio : 8; // DTD says 8 is default
|
||||
|
||||
pcbtxt->SetThickness( kicad( t.size * ratio / 100 ) );
|
||||
pcbtxt->SetThickness( t.size.ToPcbUnits() * ratio / 100 );
|
||||
|
||||
int align = t.align ? *t.align : ETEXT::BOTTOM_LEFT;
|
||||
|
||||
|
@ -592,11 +591,11 @@ void EAGLE_PLUGIN::loadPlain( wxXmlNode* aGraphics )
|
|||
m_board->Add( dseg, ADD_APPEND );
|
||||
|
||||
dseg->SetShape( S_CIRCLE );
|
||||
dseg->SetTimeStamp( timeStamp( gr ) );
|
||||
dseg->SetTimeStamp( EagleTimeStamp( gr ) );
|
||||
dseg->SetLayer( layer );
|
||||
dseg->SetStart( wxPoint( kicad_x( c.x ), kicad_y( c.y ) ) );
|
||||
dseg->SetEnd( wxPoint( kicad_x( c.x + c.radius ), kicad_y( c.y ) ) );
|
||||
dseg->SetWidth( kicad( c.width ) );
|
||||
dseg->SetWidth( c.width.ToPcbUnits() );
|
||||
}
|
||||
m_xpath->pop();
|
||||
}
|
||||
|
@ -615,7 +614,7 @@ void EAGLE_PLUGIN::loadPlain( wxXmlNode* aGraphics )
|
|||
ZONE_CONTAINER* zone = new ZONE_CONTAINER( m_board );
|
||||
m_board->Add( zone, ADD_APPEND );
|
||||
|
||||
zone->SetTimeStamp( timeStamp( gr ) );
|
||||
zone->SetTimeStamp( EagleTimeStamp( gr ) );
|
||||
zone->SetLayer( layer );
|
||||
zone->SetNetCode( NETINFO_LIST::UNCONNECTED );
|
||||
|
||||
|
@ -667,7 +666,7 @@ void EAGLE_PLUGIN::loadPlain( wxXmlNode* aGraphics )
|
|||
pad->SetPosition( padpos + module->GetPosition() );
|
||||
*/
|
||||
|
||||
wxSize sz( kicad( e.drill ), kicad( e.drill ) );
|
||||
wxSize sz( e.drill.ToPcbUnits(), e.drill.ToPcbUnits() );
|
||||
|
||||
pad->SetDrillSize( sz );
|
||||
pad->SetSize( sz );
|
||||
|
@ -694,6 +693,24 @@ void EAGLE_PLUGIN::loadPlain( wxXmlNode* aGraphics )
|
|||
DIMENSION* dimension = new DIMENSION( m_board );
|
||||
m_board->Add( dimension, ADD_APPEND );
|
||||
|
||||
if( d.dimensionType )
|
||||
{
|
||||
// Eagle dimension graphic arms may have different lengths, but they look
|
||||
// incorrect in KiCad (the graphic is tilted). Make them even lenght in such case.
|
||||
if( *d.dimensionType == "horizontal" )
|
||||
{
|
||||
int newY = ( d.y1.ToPcbUnits() + d.y2.ToPcbUnits() ) / 2;
|
||||
d.y1 = ECOORD( newY, ECOORD::UNIT::NM );
|
||||
d.y2 = ECOORD( newY, ECOORD::UNIT::NM );
|
||||
}
|
||||
else if( *d.dimensionType == "vertical" )
|
||||
{
|
||||
int newX = ( d.x1.ToPcbUnits() + d.x2.ToPcbUnits() ) / 2;
|
||||
d.x1 = ECOORD( newX, ECOORD::UNIT::NM );
|
||||
d.x2 = ECOORD( newX, ECOORD::UNIT::NM );
|
||||
}
|
||||
}
|
||||
|
||||
dimension->SetLayer( layer );
|
||||
// The origin and end are assumed to always be in this order from eagle
|
||||
dimension->SetOrigin( wxPoint( kicad_x( d.x1 ), kicad_y( d.y1 ) ) );
|
||||
|
@ -713,8 +730,8 @@ void EAGLE_PLUGIN::loadPlain( wxXmlNode* aGraphics )
|
|||
// because the "height" of the dimension is perpendicular to that axis
|
||||
// Note the check is just if two axes are close enough to each other
|
||||
// Eagle appears to have some rounding errors
|
||||
if( fabs( d.x1 - d.x2 ) < 0.05 )
|
||||
dimension->SetHeight( kicad_x( d.x1 - d.x3 ) );
|
||||
if( abs( ( d.x1 - d.x2 ).ToPcbUnits() ) < 50000 ) // 50000 nm = 0.05 mm
|
||||
dimension->SetHeight( kicad_x( d.x3 - d.x1 ) );
|
||||
else
|
||||
dimension->SetHeight( kicad_y( d.y3 - d.y1 ) );
|
||||
|
||||
|
@ -871,18 +888,21 @@ void EAGLE_PLUGIN::loadElements( wxXmlNode* aElements )
|
|||
refanceNamePresetInPackageLayout = true;
|
||||
valueNamePresetInPackageLayout = true;
|
||||
m->SetPosition( wxPoint( kicad_x( e.x ), kicad_y( e.y ) ) );
|
||||
|
||||
// Is >NAME field set in package layout ?
|
||||
if( m->GetReference().size() == 0 )
|
||||
{
|
||||
m->Reference().SetVisible( false ); // No so no show
|
||||
refanceNamePresetInPackageLayout = false;
|
||||
}
|
||||
|
||||
// Is >VALUE field set in package layout
|
||||
if( m->GetValue().size() == 0 )
|
||||
{
|
||||
m->Value().SetVisible( false ); // No so no show
|
||||
valueNamePresetInPackageLayout = false;
|
||||
}
|
||||
|
||||
m->SetReference( FROM_UTF8( e.name.c_str() ) );
|
||||
m->SetValue( FROM_UTF8( e.value.c_str() ) );
|
||||
|
||||
|
@ -890,6 +910,7 @@ void EAGLE_PLUGIN::loadElements( wxXmlNode* aElements )
|
|||
{ // Not smashed so show NAME & VALUE
|
||||
if( valueNamePresetInPackageLayout )
|
||||
m->Value().SetVisible( true ); // Only if place holder in package layout
|
||||
|
||||
if( refanceNamePresetInPackageLayout )
|
||||
m->Reference().SetVisible( true ); // Only if place holder in package layout
|
||||
}
|
||||
|
@ -1084,7 +1105,7 @@ void EAGLE_PLUGIN::orientModuleText( MODULE* m, const EELEMENT& e,
|
|||
ratio = *a.ratio;
|
||||
}
|
||||
|
||||
int lw = int( fontz.y * ratio / 100.0 );
|
||||
int lw = int( fontz.y * ratio / 100 );
|
||||
txt->SetThickness( lw );
|
||||
|
||||
int align = ETEXT::BOTTOM_LEFT; // bottom-left is eagle default
|
||||
|
@ -1163,9 +1184,9 @@ void EAGLE_PLUGIN::orientModuleText( MODULE* m, const EELEMENT& e,
|
|||
|
||||
MODULE* EAGLE_PLUGIN::makeModule( wxXmlNode* aPackage, const string& aPkgName ) const
|
||||
{
|
||||
std::unique_ptr<MODULE> m( new MODULE( m_board ) );
|
||||
std::unique_ptr<MODULE> m( new MODULE( m_board ) );
|
||||
|
||||
m->SetFPID( LIB_ID( UTF8(aPkgName) ) );
|
||||
m->SetFPID( LIB_ID( UTF8( aPkgName ) ) );
|
||||
|
||||
// Get the first package item and iterate
|
||||
wxXmlNode* packageItem = aPackage->GetChildren();
|
||||
|
@ -1213,37 +1234,46 @@ void EAGLE_PLUGIN::packageWire( MODULE* aModule, wxXmlNode* aTree ) const
|
|||
EWIRE w( aTree );
|
||||
PCB_LAYER_ID layer = kicad_layer( w.layer );
|
||||
|
||||
if( IsNonCopperLayer( layer ) ) // only valid non-copper wires, skip copper package wires
|
||||
if( IsCopperLayer( layer ) ) // skip copper "package.circle"s
|
||||
{
|
||||
wxPoint start( kicad_x( w.x1 ), kicad_y( w.y1 ) );
|
||||
wxPoint end( kicad_x( w.x2 ), kicad_y( w.y2 ) );
|
||||
int width = kicad( w.width );
|
||||
|
||||
// FIXME: the cap attribute is ignored because kicad can't create lines
|
||||
// with flat ends.
|
||||
EDGE_MODULE* dwg;
|
||||
if( !w.curve )
|
||||
{
|
||||
dwg = new EDGE_MODULE( aModule, S_SEGMENT );
|
||||
|
||||
dwg->SetStart0( start );
|
||||
dwg->SetEnd0( end );
|
||||
}
|
||||
else
|
||||
{
|
||||
dwg = new EDGE_MODULE( aModule, S_ARC );
|
||||
wxPoint center = kicad_arc_center( start, end, *w.curve);
|
||||
|
||||
dwg->SetStart0( center );
|
||||
dwg->SetEnd0( start );
|
||||
dwg->SetAngle( *w.curve * -10.0 ); // KiCad rotates the other way
|
||||
}
|
||||
|
||||
dwg->SetLayer( layer );
|
||||
dwg->SetWidth( width );
|
||||
|
||||
aModule->GraphicalItemsList().PushBack( dwg );
|
||||
wxLogMessage( wxString::Format(
|
||||
"Line on copper layer in package %s (%f mm, %f mm) (%f mm, %f mm)."
|
||||
"\nMoving to Dwgs.User layer",
|
||||
aModule->GetFPID().GetLibItemName().c_str(), w.x1.ToMm(), w.y1.ToMm(),
|
||||
w.x2.ToMm(), w.y2.ToMm() ) );
|
||||
layer = Dwgs_User;
|
||||
}
|
||||
|
||||
wxPoint start( kicad_x( w.x1 ), kicad_y( w.y1 ) );
|
||||
wxPoint end( kicad_x( w.x2 ), kicad_y( w.y2 ) );
|
||||
int width = w.width.ToPcbUnits();
|
||||
|
||||
// FIXME: the cap attribute is ignored because kicad can't create lines
|
||||
// with flat ends.
|
||||
EDGE_MODULE* dwg;
|
||||
|
||||
if( !w.curve )
|
||||
{
|
||||
dwg = new EDGE_MODULE( aModule, S_SEGMENT );
|
||||
|
||||
dwg->SetStart0( start );
|
||||
dwg->SetEnd0( end );
|
||||
}
|
||||
else
|
||||
{
|
||||
dwg = new EDGE_MODULE( aModule, S_ARC );
|
||||
wxPoint center = ConvertArcCenter( start, end, *w.curve );
|
||||
|
||||
dwg->SetStart0( center );
|
||||
dwg->SetEnd0( start );
|
||||
dwg->SetAngle( *w.curve * -10.0 ); // KiCad rotates the other way
|
||||
}
|
||||
|
||||
dwg->SetLayer( layer );
|
||||
dwg->SetWidth( width );
|
||||
dwg->SetDrawCoord();
|
||||
|
||||
aModule->GraphicalItemsList().PushBack( dwg );
|
||||
}
|
||||
|
||||
|
||||
|
@ -1267,9 +1297,7 @@ void EAGLE_PLUGIN::packagePad( MODULE* aModule, wxXmlNode* aTree ) const
|
|||
RotatePoint( &padpos, aModule->GetOrientation() );
|
||||
|
||||
pad->SetPosition( padpos + aModule->GetPosition() );
|
||||
|
||||
pad->SetDrillSize( wxSize( kicad( e.drill ), kicad( e.drill ) ) );
|
||||
|
||||
pad->SetDrillSize( wxSize( e.drill.ToPcbUnits(), e.drill.ToPcbUnits() ) );
|
||||
pad->SetLayerSet( LSET::AllCuMask().set( B_Mask ).set( F_Mask ) );
|
||||
|
||||
if( e.shape )
|
||||
|
@ -1305,7 +1333,7 @@ void EAGLE_PLUGIN::packagePad( MODULE* aModule, wxXmlNode* aTree ) const
|
|||
|
||||
if( e.diameter )
|
||||
{
|
||||
int diameter = kicad( *e.diameter );
|
||||
int diameter = e.diameter->ToPcbUnits();
|
||||
pad->SetSize( wxSize( diameter, diameter ) );
|
||||
}
|
||||
else
|
||||
|
@ -1340,6 +1368,14 @@ void EAGLE_PLUGIN::packageText( MODULE* aModule, wxXmlNode* aTree ) const
|
|||
ETEXT t( aTree );
|
||||
PCB_LAYER_ID layer = kicad_layer( t.layer );
|
||||
|
||||
if( IsCopperLayer( layer ) ) // skip copper texts
|
||||
{
|
||||
wxLogMessage( wxString::Format(
|
||||
"Unsupported text on copper layer in package %s.\nMoving to Dwgs.User layer.",
|
||||
aModule->GetFPID().GetLibItemName().c_str() ) );
|
||||
layer = Dwgs_User;
|
||||
}
|
||||
|
||||
if( layer == UNDEFINED_LAYER )
|
||||
{
|
||||
layer = Cmts_User;
|
||||
|
@ -1358,7 +1394,7 @@ void EAGLE_PLUGIN::packageText( MODULE* aModule, wxXmlNode* aTree ) const
|
|||
aModule->GraphicalItemsList().PushBack( txt );
|
||||
}
|
||||
|
||||
txt->SetTimeStamp( timeStamp( aTree ) );
|
||||
txt->SetTimeStamp( EagleTimeStamp( aTree ) );
|
||||
txt->SetText( FROM_UTF8( t.text.c_str() ) );
|
||||
|
||||
wxPoint pos( kicad_x( t.x ), kicad_y( t.y ) );
|
||||
|
@ -1371,7 +1407,7 @@ void EAGLE_PLUGIN::packageText( MODULE* aModule, wxXmlNode* aTree ) const
|
|||
|
||||
double ratio = t.ratio ? *t.ratio : 8; // DTD says 8 is default
|
||||
|
||||
txt->SetThickness( kicad( t.size * ratio / 100 ) );
|
||||
txt->SetThickness( t.size.ToPcbUnits() * ratio / 100 );
|
||||
|
||||
int align = t.align ? *t.align : ETEXT::BOTTOM_LEFT; // bottom-left is eagle default
|
||||
|
||||
|
@ -1446,31 +1482,44 @@ void EAGLE_PLUGIN::packageRectangle( MODULE* aModule, wxXmlNode* aTree ) const
|
|||
ERECT r( aTree );
|
||||
PCB_LAYER_ID layer = kicad_layer( r.layer );
|
||||
|
||||
if( IsNonCopperLayer( layer ) ) // skip copper "package.rectangle"s
|
||||
// Rectangles are not supported yet in footprints as they are not editable.
|
||||
wxLogMessage( wxString::Format( "Unsupported rectangle in package %s"
|
||||
" (%f mm, %f mm) (%f mm, %f mm), layer: %s",
|
||||
aModule->GetFPID().GetLibItemName().c_str(), r.x1.ToMm(), r.y1.ToMm(),
|
||||
r.x2.ToMm(), r.y2.ToMm(), eagle_layer_name( r.layer ) ) );
|
||||
|
||||
return;
|
||||
|
||||
if( IsCopperLayer( layer ) ) // skip copper "package.circle"s
|
||||
{
|
||||
EDGE_MODULE* dwg = new EDGE_MODULE( aModule, S_POLYGON );
|
||||
aModule->GraphicalItemsList().PushBack( dwg );
|
||||
|
||||
dwg->SetLayer( layer );
|
||||
dwg->SetWidth( 0 );
|
||||
|
||||
dwg->SetTimeStamp( timeStamp( aTree ) );
|
||||
|
||||
std::vector<wxPoint> pts;
|
||||
|
||||
wxPoint start( wxPoint( kicad_x( r.x1 ), kicad_y( r.y1 ) ) );
|
||||
wxPoint end( wxPoint( kicad_x( r.x1 ), kicad_y( r.y2 ) ) );
|
||||
|
||||
pts.push_back( start );
|
||||
pts.push_back( wxPoint( kicad_x( r.x2 ), kicad_y( r.y1 ) ) );
|
||||
pts.push_back( wxPoint( kicad_x( r.x2 ), kicad_y( r.y2 ) ) );
|
||||
pts.push_back( end );
|
||||
|
||||
dwg->SetPolyPoints( pts );
|
||||
|
||||
dwg->SetStart0( start );
|
||||
dwg->SetEnd0( end );
|
||||
wxLogMessage( wxString::Format(
|
||||
"Unsupported rectangle on copper layer in package %s.\nMoving to Dwgs.User layer.",
|
||||
aModule->GetFPID().GetLibItemName().c_str() ) );
|
||||
layer = Dwgs_User;
|
||||
}
|
||||
|
||||
EDGE_MODULE* dwg = new EDGE_MODULE( aModule, S_POLYGON );
|
||||
aModule->GraphicalItemsList().PushBack( dwg );
|
||||
|
||||
dwg->SetLayer( layer );
|
||||
dwg->SetWidth( 0 );
|
||||
|
||||
dwg->SetTimeStamp( EagleTimeStamp( aTree ) );
|
||||
|
||||
std::vector<wxPoint> pts;
|
||||
|
||||
wxPoint start( wxPoint( kicad_x( r.x1 ), kicad_y( r.y1 ) ) );
|
||||
wxPoint end( wxPoint( kicad_x( r.x1 ), kicad_y( r.y2 ) ) );
|
||||
|
||||
pts.push_back( start );
|
||||
pts.push_back( wxPoint( kicad_x( r.x2 ), kicad_y( r.y1 ) ) );
|
||||
pts.push_back( wxPoint( kicad_x( r.x2 ), kicad_y( r.y2 ) ) );
|
||||
pts.push_back( end );
|
||||
|
||||
dwg->SetPolyPoints( pts );
|
||||
|
||||
dwg->SetStart0( start );
|
||||
dwg->SetEnd0( end );
|
||||
}
|
||||
|
||||
|
||||
|
@ -1479,53 +1528,46 @@ void EAGLE_PLUGIN::packagePolygon( MODULE* aModule, wxXmlNode* aTree ) const
|
|||
EPOLYGON p( aTree );
|
||||
PCB_LAYER_ID layer = kicad_layer( p.layer );
|
||||
|
||||
if( IsNonCopperLayer( layer ) ) // skip copper "package.rectangle"s
|
||||
if( IsCopperLayer( layer ) ) // skip copper "package.circle"s
|
||||
{
|
||||
EDGE_MODULE* dwg = new EDGE_MODULE( aModule, S_POLYGON );
|
||||
aModule->GraphicalItemsList().PushBack( dwg );
|
||||
|
||||
dwg->SetWidth( 0 ); // it's filled, no need for boundary width
|
||||
|
||||
/*
|
||||
switch( layer )
|
||||
{
|
||||
case Eco1_User: layer = F_SilkS; break;
|
||||
case Eco2_User: layer = B_SilkS; break;
|
||||
|
||||
// all MODULE templates (created from eagle packages) are on front layer
|
||||
// until cloned.
|
||||
case Cmts_User: layer = F_SilkS; break;
|
||||
}
|
||||
*/
|
||||
|
||||
dwg->SetLayer( layer );
|
||||
|
||||
dwg->SetTimeStamp( timeStamp( aTree ) );
|
||||
|
||||
std::vector<wxPoint> pts;
|
||||
// TODO: I think there's no way to know a priori the number of children in wxXmlNode :()
|
||||
// pts.reserve( aTree.size() );
|
||||
|
||||
// Get the first vertex and iterate
|
||||
wxXmlNode* vertex = aTree->GetChildren();
|
||||
|
||||
while( vertex )
|
||||
{
|
||||
if( vertex->GetName() != "vertex" ) // skip <xmlattr> node
|
||||
continue;
|
||||
|
||||
EVERTEX v( vertex );
|
||||
|
||||
pts.push_back( wxPoint( kicad_x( v.x ), kicad_y( v.y ) ) );
|
||||
|
||||
vertex = vertex->GetNext();
|
||||
}
|
||||
|
||||
dwg->SetPolyPoints( pts );
|
||||
|
||||
dwg->SetStart0( *pts.begin() );
|
||||
dwg->SetEnd0( pts.back() );
|
||||
wxLogMessage( wxString::Format(
|
||||
"Unsupported polygon on copper layer in package %s.\nMoving to Dwgs.User layer.",
|
||||
aModule->GetFPID().GetLibItemName().c_str() ) );
|
||||
layer = Dwgs_User;
|
||||
}
|
||||
|
||||
EDGE_MODULE* dwg = new EDGE_MODULE( aModule, S_POLYGON );
|
||||
aModule->GraphicalItemsList().PushBack( dwg );
|
||||
|
||||
dwg->SetWidth( 0 ); // it's filled, no need for boundary width
|
||||
|
||||
dwg->SetLayer( layer );
|
||||
|
||||
dwg->SetTimeStamp( EagleTimeStamp( aTree ) );
|
||||
|
||||
std::vector<wxPoint> pts;
|
||||
// TODO: I think there's no way to know a priori the number of children in wxXmlNode :()
|
||||
// pts.reserve( aTree.size() );
|
||||
|
||||
// Get the first vertex and iterate
|
||||
wxXmlNode* vertex = aTree->GetChildren();
|
||||
|
||||
while( vertex )
|
||||
{
|
||||
if( vertex->GetName() != "vertex" ) // skip <xmlattr> node
|
||||
continue;
|
||||
|
||||
EVERTEX v( vertex );
|
||||
|
||||
pts.push_back( wxPoint( kicad_x( v.x ), kicad_y( v.y ) ) );
|
||||
|
||||
vertex = vertex->GetNext();
|
||||
}
|
||||
|
||||
dwg->SetPolyPoints( pts );
|
||||
dwg->SetStart0( *pts.begin() );
|
||||
dwg->SetEnd0( pts.back() );
|
||||
dwg->SetDrawCoord();
|
||||
}
|
||||
|
||||
|
||||
|
@ -1533,11 +1575,20 @@ void EAGLE_PLUGIN::packageCircle( MODULE* aModule, wxXmlNode* aTree ) const
|
|||
{
|
||||
ECIRCLE e( aTree );
|
||||
PCB_LAYER_ID layer = kicad_layer( e.layer );
|
||||
|
||||
if( IsCopperLayer( layer ) ) // skip copper "package.circle"s
|
||||
{
|
||||
wxLogMessage( wxString::Format(
|
||||
"Unsupported circle on copper layer in package %s.\nMoving to Dwgs.User layer.",
|
||||
aModule->GetFPID().GetLibItemName().c_str() ) );
|
||||
layer = Dwgs_User;
|
||||
}
|
||||
|
||||
EDGE_MODULE* gr = new EDGE_MODULE( aModule, S_CIRCLE );
|
||||
|
||||
aModule->GraphicalItemsList().PushBack( gr );
|
||||
|
||||
gr->SetWidth( kicad( e.width ) );
|
||||
gr->SetWidth( e.width.ToPcbUnits() );
|
||||
|
||||
switch( (int) layer )
|
||||
{
|
||||
|
@ -1551,10 +1602,10 @@ void EAGLE_PLUGIN::packageCircle( MODULE* aModule, wxXmlNode* aTree ) const
|
|||
}
|
||||
|
||||
gr->SetLayer( layer );
|
||||
gr->SetTimeStamp( timeStamp( aTree ) );
|
||||
|
||||
gr->SetTimeStamp( EagleTimeStamp( aTree ) );
|
||||
gr->SetStart0( wxPoint( kicad_x( e.x ), kicad_y( e.y ) ) );
|
||||
gr->SetEnd0( wxPoint( kicad_x( e.x + e.radius ), kicad_y( e.y ) ) );
|
||||
gr->SetDrawCoord();
|
||||
}
|
||||
|
||||
|
||||
|
@ -1579,7 +1630,7 @@ void EAGLE_PLUGIN::packageHole( MODULE* aModule, wxXmlNode* aTree ) const
|
|||
pad->SetPos0( padpos );
|
||||
pad->SetPosition( padpos + aModule->GetPosition() );
|
||||
|
||||
wxSize sz( kicad( e.drill ), kicad( e.drill ) );
|
||||
wxSize sz( e.drill.ToPcbUnits(), e.drill.ToPcbUnits() );
|
||||
|
||||
pad->SetDrillSize( sz );
|
||||
pad->SetSize( sz );
|
||||
|
@ -1616,7 +1667,7 @@ void EAGLE_PLUGIN::packageSMD( MODULE* aModule, wxXmlNode* aTree ) const
|
|||
|
||||
pad->SetPosition( padpos + aModule->GetPosition() );
|
||||
|
||||
pad->SetSize( wxSize( kicad( e.dx ), kicad( e.dy ) ) );
|
||||
pad->SetSize( wxSize( e.dx.ToPcbUnits(), e.dy.ToPcbUnits() ) );
|
||||
|
||||
pad->SetLayer( layer );
|
||||
|
||||
|
@ -1703,12 +1754,12 @@ void EAGLE_PLUGIN::loadSignals( wxXmlNode* aSignals )
|
|||
{
|
||||
TRACK* t = new TRACK( m_board );
|
||||
|
||||
t->SetTimeStamp( timeStamp( netItem ) );
|
||||
t->SetTimeStamp( EagleTimeStamp( netItem ) );
|
||||
|
||||
t->SetPosition( wxPoint( kicad_x( w.x1 ), kicad_y( w.y1 ) ) );
|
||||
t->SetEnd( wxPoint( kicad_x( w.x2 ), kicad_y( w.y2 ) ) );
|
||||
|
||||
int width = kicad( w.width );
|
||||
int width = w.width.ToPcbUnits();
|
||||
if( width < m_min_trace )
|
||||
m_min_trace = width;
|
||||
|
||||
|
@ -1738,7 +1789,7 @@ void EAGLE_PLUGIN::loadSignals( wxXmlNode* aSignals )
|
|||
IsCopperLayer( layer_back_most ) )
|
||||
{
|
||||
int kidiam;
|
||||
int drillz = kicad( v.drill );
|
||||
int drillz = v.drill.ToPcbUnits();
|
||||
VIA* via = new VIA( m_board );
|
||||
m_board->m_Track.Insert( via, NULL );
|
||||
|
||||
|
@ -1746,7 +1797,7 @@ void EAGLE_PLUGIN::loadSignals( wxXmlNode* aSignals )
|
|||
|
||||
if( v.diam )
|
||||
{
|
||||
kidiam = kicad( *v.diam );
|
||||
kidiam = v.diam->ToPcbUnits();
|
||||
via->SetWidth( kidiam );
|
||||
}
|
||||
else
|
||||
|
@ -1781,7 +1832,7 @@ void EAGLE_PLUGIN::loadSignals( wxXmlNode* aSignals )
|
|||
else
|
||||
via->SetViaType( VIA_BLIND_BURIED );
|
||||
|
||||
via->SetTimeStamp( timeStamp( netItem ) );
|
||||
via->SetTimeStamp( EagleTimeStamp( netItem ) );
|
||||
|
||||
wxPoint pos( kicad_x( v.x ), kicad_y( v.y ) );
|
||||
|
||||
|
@ -1827,7 +1878,7 @@ void EAGLE_PLUGIN::loadSignals( wxXmlNode* aSignals )
|
|||
m_board->Add( zone, ADD_APPEND );
|
||||
zones.push_back( zone );
|
||||
|
||||
zone->SetTimeStamp( timeStamp( netItem ) );
|
||||
zone->SetTimeStamp( EagleTimeStamp( netItem ) );
|
||||
zone->SetLayer( layer );
|
||||
zone->SetNetCode( netCode );
|
||||
|
||||
|
@ -1863,14 +1914,14 @@ void EAGLE_PLUGIN::loadSignals( wxXmlNode* aSignals )
|
|||
|
||||
// clearances, etc.
|
||||
zone->SetArcSegmentCount( 32 ); // @todo: should be a constructor default?
|
||||
zone->SetMinThickness( kicad( p.width ) );
|
||||
zone->SetMinThickness( p.width.ToPcbUnits() );
|
||||
|
||||
// FIXME: KiCad zones have very rounded corners compared to eagle.
|
||||
// This means that isolation amounts that work well in eagle
|
||||
// tend to make copper intrude in soldermask free areas around pads.
|
||||
if( p.isolate )
|
||||
{
|
||||
zone->SetZoneClearance( kicad( *p.isolate ) );
|
||||
zone->SetZoneClearance( p.isolate->ToPcbUnits() );
|
||||
} else
|
||||
{
|
||||
zone->SetZoneClearance( 0 );
|
||||
|
@ -1885,8 +1936,8 @@ void EAGLE_PLUGIN::loadSignals( wxXmlNode* aSignals )
|
|||
// based on what the zone is connecting to.
|
||||
// (i.e. width of spoke is half of the smaller side of an smd pad)
|
||||
// This is a basic workaround
|
||||
zone->SetThermalReliefGap( kicad( p.width + 0.05 ) );
|
||||
zone->SetThermalReliefCopperBridge( kicad( p.width + 0.05 ) );
|
||||
zone->SetThermalReliefGap( p.width.ToPcbUnits() + 50000 ); // 50000nm == 0.05mm
|
||||
zone->SetThermalReliefCopperBridge( p.width.ToPcbUnits() + 50000 );
|
||||
}
|
||||
|
||||
int rank = p.rank ? (p.max_priority - *p.rank) : p.max_priority;
|
||||
|
@ -1975,8 +2026,8 @@ PCB_LAYER_ID EAGLE_PLUGIN::kicad_layer( int aEagleLayer ) const
|
|||
case EAGLE_LAYER::HOLES:
|
||||
default:
|
||||
// some layers do not map to KiCad
|
||||
wxLogMessage( wxString::Format( "Unsupported Eagle layer %d. Use drawings layer",
|
||||
aEagleLayer ) );
|
||||
wxLogMessage( wxString::Format( "Unsupported Eagle layer '%s' (%d), converted to Dwgs.User layer",
|
||||
eagle_layer_name( aEagleLayer ), aEagleLayer ) );
|
||||
kiLayer = Dwgs_User; break;
|
||||
}
|
||||
}
|
||||
|
@ -1985,6 +2036,14 @@ PCB_LAYER_ID EAGLE_PLUGIN::kicad_layer( int aEagleLayer ) const
|
|||
}
|
||||
|
||||
|
||||
const string& EAGLE_PLUGIN::eagle_layer_name( int aLayer ) const
|
||||
{
|
||||
static const string unknown( "unknown" );
|
||||
auto it = m_eagleLayers.find( aLayer );
|
||||
return it == m_eagleLayers.end() ? unknown : it->second.name;
|
||||
}
|
||||
|
||||
|
||||
void EAGLE_PLUGIN::centerBoard()
|
||||
{
|
||||
if( m_props )
|
||||
|
|
|
@ -125,8 +125,11 @@ public:
|
|||
~EAGLE_PLUGIN();
|
||||
|
||||
private:
|
||||
typedef std::vector<ELAYER> ELAYERS;
|
||||
typedef ELAYERS::const_iterator EITER;
|
||||
|
||||
int m_cu_map[17]; ///< map eagle to kicad, cu layers only.
|
||||
std::map<int, ELAYER> m_eagleLayers; ///< Eagle layers data stored by the layer number
|
||||
|
||||
ERULES* m_rules; ///< Eagle design rules.
|
||||
XPATH* m_xpath; ///< keeps track of what we are working on within
|
||||
|
@ -148,9 +151,6 @@ private:
|
|||
int m_min_via; ///< smallest via we find on Load(), in BIU.
|
||||
int m_min_via_hole; ///< smallest via diameter hole we find on Load(), in BIU.
|
||||
|
||||
double mm_per_biu; ///< how many mm in each BIU
|
||||
double biu_per_mm; ///< how many bius in a mm
|
||||
|
||||
wxString m_lib_path;
|
||||
wxDateTime m_mod_time;
|
||||
|
||||
|
@ -160,20 +160,17 @@ private:
|
|||
void clear_cu_map();
|
||||
|
||||
/// Convert an Eagle distance to a KiCad distance.
|
||||
int kicad( double d ) const;
|
||||
int kicad_y( double y ) const { return -kicad( y ); }
|
||||
int kicad_x( double x ) const { return kicad( x ); }
|
||||
int kicad_y( const ECOORD& y ) const { return -y.ToPcbUnits(); }
|
||||
int kicad_x( const ECOORD& x ) const { return x.ToPcbUnits(); }
|
||||
|
||||
/// create a font size (fontz) from an eagle font size scalar
|
||||
wxSize kicad_fontz( double d ) const;
|
||||
wxSize kicad_fontz( const ECOORD& d ) const;
|
||||
|
||||
/// Convert an Eagle layer to a KiCad layer.
|
||||
PCB_LAYER_ID kicad_layer( int aLayer ) const;
|
||||
|
||||
/// Convert a KiCad distance to an Eagle distance.
|
||||
double eagle( BIU d ) const { return mm_per_biu * d; }
|
||||
double eagle_x( BIU x ) const { return eagle( x ); }
|
||||
double eagle_y( BIU y ) const { return eagle( y ); }
|
||||
/// Get Eagle layer name by its number
|
||||
const std::string& eagle_layer_name( int aLayer ) const;
|
||||
|
||||
/// This PLUGIN only caches one footprint library, this determines which one.
|
||||
void cacheLib( const wxString& aLibraryPath );
|
||||
|
|
|
@ -42,6 +42,8 @@
|
|||
#include <msgpanel.h>
|
||||
#include <fp_lib_table.h>
|
||||
#include <ratsnest_data.h>
|
||||
#include <kiway.h>
|
||||
#include <kiway_player.h>
|
||||
|
||||
#include <pcbnew.h>
|
||||
#include <pcbnew_id.h>
|
||||
|
@ -94,10 +96,10 @@ bool AskLoadBoardFileName( wxWindow* aParent, int* aCtl, wxString* aFileName, bo
|
|||
IO_MGR::PCB_FILE_T pluginType;
|
||||
} loaders[] =
|
||||
{
|
||||
{ PcbFileWildcard, IO_MGR::KICAD }, // Current Kicad board files
|
||||
{ LegacyPcbFileWildcard, IO_MGR::LEGACY }, // Old Kicad board files
|
||||
{ EaglePcbFileWildcard, IO_MGR::EAGLE }, // Import board files
|
||||
{ PCadPcbFileWildcard, IO_MGR::PCAD }, // Import board files
|
||||
{ PcbFileWildcard, IO_MGR::KICAD_SEXP }, // Current Kicad board files
|
||||
{ LegacyPcbFileWildcard, IO_MGR::LEGACY }, // Old Kicad board files
|
||||
{ EaglePcbFileWildcard, IO_MGR::EAGLE }, // Import board files
|
||||
{ PCadPcbFileWildcard, IO_MGR::PCAD }, // Import board files
|
||||
};
|
||||
|
||||
wxFileName fileName( *aFileName );
|
||||
|
@ -394,7 +396,7 @@ IO_MGR::PCB_FILE_T plugin_type( const wxString& aFileName, int aCtl )
|
|||
}
|
||||
else
|
||||
{
|
||||
pluginType = IO_MGR::KICAD;
|
||||
pluginType = IO_MGR::KICAD_SEXP;
|
||||
}
|
||||
|
||||
return pluginType;
|
||||
|
@ -467,7 +469,7 @@ bool PCB_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
|
|||
|
||||
IO_MGR::PCB_FILE_T pluginType = plugin_type( fullFileName, aCtl );
|
||||
|
||||
bool converted = pluginType != IO_MGR::LEGACY && pluginType != IO_MGR::KICAD;
|
||||
bool converted = pluginType != IO_MGR::LEGACY && pluginType != IO_MGR::KICAD_SEXP;
|
||||
|
||||
if( !converted )
|
||||
{
|
||||
|
@ -709,7 +711,7 @@ bool PCB_EDIT_FRAME::SavePcbFile( const wxString& aFileName, bool aCreateBackupF
|
|||
|
||||
try
|
||||
{
|
||||
PLUGIN::RELEASER pi( IO_MGR::PluginFind( IO_MGR::KICAD ) );
|
||||
PLUGIN::RELEASER pi( IO_MGR::PluginFind( IO_MGR::KICAD_SEXP ) );
|
||||
|
||||
wxASSERT( pcbFileName.IsAbsolute() );
|
||||
|
||||
|
@ -788,7 +790,7 @@ bool PCB_EDIT_FRAME::SavePcbCopy( const wxString& aFileName )
|
|||
|
||||
try
|
||||
{
|
||||
PLUGIN::RELEASER pi( IO_MGR::PluginFind( IO_MGR::KICAD ) );
|
||||
PLUGIN::RELEASER pi( IO_MGR::PluginFind( IO_MGR::KICAD_SEXP ) );
|
||||
|
||||
wxASSERT( pcbFileName.IsAbsolute() );
|
||||
|
||||
|
@ -861,3 +863,34 @@ bool PCB_EDIT_FRAME::doAutoSave()
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool PCB_EDIT_FRAME::ImportFile( const wxString& aFileName, int aFileType )
|
||||
{
|
||||
switch( (IO_MGR::PCB_FILE_T) aFileType )
|
||||
{
|
||||
case IO_MGR::EAGLE:
|
||||
if( OpenProjectFiles( std::vector<wxString>( 1, aFileName ),
|
||||
KICTL_EAGLE_BRD ) )
|
||||
{
|
||||
wxString projectpath = Kiway().Prj().GetProjectPath();
|
||||
wxFileName newfilename = Prj().AbsolutePath( Prj().GetProjectName() );
|
||||
|
||||
newfilename.SetExt( KiCadPcbFileExtension );
|
||||
|
||||
GetBoard()->SetFileName( newfilename.GetFullPath() );
|
||||
UpdateTitle();
|
||||
|
||||
ArchiveModulesOnBoard( true, newfilename.GetName() );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -65,7 +65,7 @@ PLUGIN* IO_MGR::PluginFind( PCB_FILE_T aFileType )
|
|||
case LEGACY:
|
||||
return new LEGACY_PLUGIN();
|
||||
|
||||
case KICAD:
|
||||
case KICAD_SEXP:
|
||||
return new PCB_IO();
|
||||
|
||||
case EAGLE:
|
||||
|
@ -116,7 +116,7 @@ const wxString IO_MGR::ShowType( PCB_FILE_T aType )
|
|||
case LEGACY:
|
||||
return wxString( wxT( "Legacy" ) );
|
||||
|
||||
case KICAD:
|
||||
case KICAD_SEXP:
|
||||
return wxString( wxT( "KiCad" ) );
|
||||
|
||||
case EAGLE:
|
||||
|
@ -141,7 +141,7 @@ IO_MGR::PCB_FILE_T IO_MGR::EnumFromStr( const wxString& aType )
|
|||
// library tables, so don't do change, only additions are ok.
|
||||
|
||||
if( aType == wxT( "KiCad" ) )
|
||||
return KICAD;
|
||||
return KICAD_SEXP;
|
||||
|
||||
if( aType == wxT( "Legacy" ) )
|
||||
return LEGACY;
|
||||
|
@ -181,7 +181,7 @@ const wxString IO_MGR::GetFileExtension( PCB_FILE_T aFileType )
|
|||
|
||||
IO_MGR::PCB_FILE_T IO_MGR::GuessPluginTypeFromLibPath( const wxString& aLibPath )
|
||||
{
|
||||
PCB_FILE_T ret = KICAD; // default guess, unless detected otherwise.
|
||||
PCB_FILE_T ret = KICAD_SEXP; // default guess, unless detected otherwise.
|
||||
wxFileName fn( aLibPath );
|
||||
|
||||
if( fn.GetExt() == LegacyFootprintLibPathExtension )
|
||||
|
@ -209,7 +209,7 @@ IO_MGR::PCB_FILE_T IO_MGR::GuessPluginTypeFromLibPath( const wxString& aLibPath
|
|||
else if( fn.GetExt() == KiCadFootprintLibPathExtension &&
|
||||
!aLibPath.StartsWith( wxT( "http" ) ) )
|
||||
{
|
||||
ret = KICAD;
|
||||
ret = KICAD_SEXP;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -254,4 +254,3 @@ void IO_MGR::Save( PCB_FILE_T aFileType, const wxString& aFileName, BOARD* aBoar
|
|||
|
||||
THROW_IO_ERROR( wxString::Format( FMT_NOTFOUND, ShowType( aFileType ).GetData() ) );
|
||||
}
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ public:
|
|||
enum PCB_FILE_T
|
||||
{
|
||||
LEGACY, ///< Legacy Pcbnew file formats prior to s-expression.
|
||||
KICAD, ///< S-expression Pcbnew file format.
|
||||
KICAD_SEXP, ///< S-expression Pcbnew file format.
|
||||
EAGLE,
|
||||
PCAD,
|
||||
GEDA_PCB, ///< Geda PCB file formats.
|
||||
|
|
|
@ -53,7 +53,8 @@
|
|||
|
||||
using namespace PCB_KEYS_T;
|
||||
|
||||
#define FMTIU BOARD_ITEM::FormatInternalUnits
|
||||
#define FMT_IU BOARD_ITEM::FormatInternalUnits
|
||||
#define FMT_ANGLE BOARD_ITEM::FormatAngle
|
||||
|
||||
/**
|
||||
* @ingroup trace_env_vars
|
||||
|
@ -538,105 +539,105 @@ void PCB_IO::formatSetup( BOARD* aBoard, int aNestLevel ) const
|
|||
|
||||
// Save current default track width, for compatibility with older Pcbnew version;
|
||||
m_out->Print( aNestLevel+1, "(last_trace_width %s)\n",
|
||||
FMTIU( dsnSettings.GetCurrentTrackWidth() ).c_str() );
|
||||
FMT_IU( dsnSettings.GetCurrentTrackWidth() ).c_str() );
|
||||
|
||||
// Save custom tracks width list (the first is not saved here: this is the netclass value
|
||||
for( unsigned ii = 1; ii < dsnSettings.m_TrackWidthList.size(); ii++ )
|
||||
m_out->Print( aNestLevel+1, "(user_trace_width %s)\n",
|
||||
FMTIU( dsnSettings.m_TrackWidthList[ii] ).c_str() );
|
||||
FMT_IU( dsnSettings.m_TrackWidthList[ii] ).c_str() );
|
||||
|
||||
m_out->Print( aNestLevel+1, "(trace_clearance %s)\n",
|
||||
FMTIU( dsnSettings.GetDefault()->GetClearance() ).c_str() );
|
||||
FMT_IU( dsnSettings.GetDefault()->GetClearance() ).c_str() );
|
||||
|
||||
// ZONE_SETTINGS
|
||||
m_out->Print( aNestLevel+1, "(zone_clearance %s)\n",
|
||||
FMTIU( aBoard->GetZoneSettings().m_ZoneClearance ).c_str() );
|
||||
FMT_IU( aBoard->GetZoneSettings().m_ZoneClearance ).c_str() );
|
||||
m_out->Print( aNestLevel+1, "(zone_45_only %s)\n",
|
||||
aBoard->GetZoneSettings().m_Zone_45_Only ? "yes" : "no" );
|
||||
|
||||
m_out->Print( aNestLevel+1, "(trace_min %s)\n",
|
||||
FMTIU( dsnSettings.m_TrackMinWidth ).c_str() );
|
||||
FMT_IU( dsnSettings.m_TrackMinWidth ).c_str() );
|
||||
|
||||
m_out->Print( aNestLevel+1, "(segment_width %s)\n",
|
||||
FMTIU( dsnSettings.m_DrawSegmentWidth ).c_str() );
|
||||
FMT_IU( dsnSettings.m_DrawSegmentWidth ).c_str() );
|
||||
m_out->Print( aNestLevel+1, "(edge_width %s)\n",
|
||||
FMTIU( dsnSettings.m_EdgeSegmentWidth ).c_str() );
|
||||
FMT_IU( dsnSettings.m_EdgeSegmentWidth ).c_str() );
|
||||
|
||||
// Save current default via size, for compatibility with older Pcbnew version;
|
||||
m_out->Print( aNestLevel+1, "(via_size %s)\n",
|
||||
FMTIU( dsnSettings.GetDefault()->GetViaDiameter() ).c_str() );
|
||||
FMT_IU( dsnSettings.GetDefault()->GetViaDiameter() ).c_str() );
|
||||
m_out->Print( aNestLevel+1, "(via_drill %s)\n",
|
||||
FMTIU( dsnSettings.GetDefault()->GetViaDrill() ).c_str() );
|
||||
FMT_IU( dsnSettings.GetDefault()->GetViaDrill() ).c_str() );
|
||||
m_out->Print( aNestLevel+1, "(via_min_size %s)\n",
|
||||
FMTIU( dsnSettings.m_ViasMinSize ).c_str() );
|
||||
FMT_IU( dsnSettings.m_ViasMinSize ).c_str() );
|
||||
m_out->Print( aNestLevel+1, "(via_min_drill %s)\n",
|
||||
FMTIU( dsnSettings.m_ViasMinDrill ).c_str() );
|
||||
FMT_IU( dsnSettings.m_ViasMinDrill ).c_str() );
|
||||
|
||||
// Save custom vias diameters list (the first is not saved here: this is
|
||||
// the netclass value
|
||||
for( unsigned ii = 1; ii < dsnSettings.m_ViasDimensionsList.size(); ii++ )
|
||||
m_out->Print( aNestLevel+1, "(user_via %s %s)\n",
|
||||
FMTIU( dsnSettings.m_ViasDimensionsList[ii].m_Diameter ).c_str(),
|
||||
FMTIU( dsnSettings.m_ViasDimensionsList[ii].m_Drill ).c_str() );
|
||||
FMT_IU( dsnSettings.m_ViasDimensionsList[ii].m_Diameter ).c_str(),
|
||||
FMT_IU( dsnSettings.m_ViasDimensionsList[ii].m_Drill ).c_str() );
|
||||
|
||||
// for old versions compatibility:
|
||||
if( dsnSettings.m_BlindBuriedViaAllowed )
|
||||
m_out->Print( aNestLevel+1, "(blind_buried_vias_allowed yes)\n" );
|
||||
|
||||
m_out->Print( aNestLevel+1, "(uvia_size %s)\n",
|
||||
FMTIU( dsnSettings.GetDefault()->GetuViaDiameter() ).c_str() );
|
||||
FMT_IU( dsnSettings.GetDefault()->GetuViaDiameter() ).c_str() );
|
||||
m_out->Print( aNestLevel+1, "(uvia_drill %s)\n",
|
||||
FMTIU( dsnSettings.GetDefault()->GetuViaDrill() ).c_str() );
|
||||
FMT_IU( dsnSettings.GetDefault()->GetuViaDrill() ).c_str() );
|
||||
m_out->Print( aNestLevel+1, "(uvias_allowed %s)\n",
|
||||
( dsnSettings.m_MicroViasAllowed ) ? "yes" : "no" );
|
||||
m_out->Print( aNestLevel+1, "(uvia_min_size %s)\n",
|
||||
FMTIU( dsnSettings.m_MicroViasMinSize ).c_str() );
|
||||
FMT_IU( dsnSettings.m_MicroViasMinSize ).c_str() );
|
||||
m_out->Print( aNestLevel+1, "(uvia_min_drill %s)\n",
|
||||
FMTIU( dsnSettings.m_MicroViasMinDrill ).c_str() );
|
||||
FMT_IU( dsnSettings.m_MicroViasMinDrill ).c_str() );
|
||||
|
||||
m_out->Print( aNestLevel+1, "(pcb_text_width %s)\n",
|
||||
FMTIU( dsnSettings.m_PcbTextWidth ).c_str() );
|
||||
FMT_IU( dsnSettings.m_PcbTextWidth ).c_str() );
|
||||
m_out->Print( aNestLevel+1, "(pcb_text_size %s %s)\n",
|
||||
FMTIU( dsnSettings.m_PcbTextSize.x ).c_str(),
|
||||
FMTIU( dsnSettings.m_PcbTextSize.y ).c_str() );
|
||||
FMT_IU( dsnSettings.m_PcbTextSize.x ).c_str(),
|
||||
FMT_IU( dsnSettings.m_PcbTextSize.y ).c_str() );
|
||||
|
||||
m_out->Print( aNestLevel+1, "(mod_edge_width %s)\n",
|
||||
FMTIU( dsnSettings.m_ModuleSegmentWidth ).c_str() );
|
||||
FMT_IU( dsnSettings.m_ModuleSegmentWidth ).c_str() );
|
||||
m_out->Print( aNestLevel+1, "(mod_text_size %s %s)\n",
|
||||
FMTIU( dsnSettings.m_ModuleTextSize.x ).c_str(),
|
||||
FMTIU( dsnSettings.m_ModuleTextSize.y ).c_str() );
|
||||
FMT_IU( dsnSettings.m_ModuleTextSize.x ).c_str(),
|
||||
FMT_IU( dsnSettings.m_ModuleTextSize.y ).c_str() );
|
||||
m_out->Print( aNestLevel+1, "(mod_text_width %s)\n",
|
||||
FMTIU( dsnSettings.m_ModuleTextWidth ).c_str() );
|
||||
FMT_IU( dsnSettings.m_ModuleTextWidth ).c_str() );
|
||||
|
||||
m_out->Print( aNestLevel+1, "(pad_size %s %s)\n",
|
||||
FMTIU( dsnSettings.m_Pad_Master.GetSize().x ).c_str(),
|
||||
FMTIU( dsnSettings.m_Pad_Master.GetSize().y ).c_str() );
|
||||
FMT_IU( dsnSettings.m_Pad_Master.GetSize().x ).c_str(),
|
||||
FMT_IU( dsnSettings.m_Pad_Master.GetSize().y ).c_str() );
|
||||
m_out->Print( aNestLevel+1, "(pad_drill %s)\n",
|
||||
FMTIU( dsnSettings.m_Pad_Master.GetDrillSize().x ).c_str() );
|
||||
FMT_IU( dsnSettings.m_Pad_Master.GetDrillSize().x ).c_str() );
|
||||
|
||||
m_out->Print( aNestLevel+1, "(pad_to_mask_clearance %s)\n",
|
||||
FMTIU( dsnSettings.m_SolderMaskMargin ).c_str() );
|
||||
FMT_IU( dsnSettings.m_SolderMaskMargin ).c_str() );
|
||||
|
||||
if( dsnSettings.m_SolderMaskMinWidth )
|
||||
m_out->Print( aNestLevel+1, "(solder_mask_min_width %s)\n",
|
||||
FMTIU( dsnSettings.m_SolderMaskMinWidth ).c_str() );
|
||||
FMT_IU( dsnSettings.m_SolderMaskMinWidth ).c_str() );
|
||||
|
||||
if( dsnSettings.m_SolderPasteMargin != 0 )
|
||||
m_out->Print( aNestLevel+1, "(pad_to_paste_clearance %s)\n",
|
||||
FMTIU( dsnSettings.m_SolderPasteMargin ).c_str() );
|
||||
FMT_IU( dsnSettings.m_SolderPasteMargin ).c_str() );
|
||||
|
||||
if( dsnSettings.m_SolderPasteMarginRatio != 0 )
|
||||
m_out->Print( aNestLevel+1, "(pad_to_paste_clearance_ratio %s)\n",
|
||||
Double2Str( dsnSettings.m_SolderPasteMarginRatio ).c_str() );
|
||||
|
||||
m_out->Print( aNestLevel+1, "(aux_axis_origin %s %s)\n",
|
||||
FMTIU( aBoard->GetAuxOrigin().x ).c_str(),
|
||||
FMTIU( aBoard->GetAuxOrigin().y ).c_str() );
|
||||
FMT_IU( aBoard->GetAuxOrigin().x ).c_str(),
|
||||
FMT_IU( aBoard->GetAuxOrigin().y ).c_str() );
|
||||
|
||||
if( aBoard->GetGridOrigin().x || aBoard->GetGridOrigin().y )
|
||||
m_out->Print( aNestLevel+1, "(grid_origin %s %s)\n",
|
||||
FMTIU( aBoard->GetGridOrigin().x ).c_str(),
|
||||
FMTIU( aBoard->GetGridOrigin().y ).c_str() );
|
||||
FMT_IU( aBoard->GetGridOrigin().x ).c_str(),
|
||||
FMT_IU( aBoard->GetGridOrigin().y ).c_str() );
|
||||
|
||||
m_out->Print( aNestLevel+1, "(visible_elements %X)\n",
|
||||
dsnSettings.GetVisibleElements() );
|
||||
|
@ -655,7 +656,7 @@ void PCB_IO::formatGeneral( BOARD* aBoard, int aNestLevel ) const
|
|||
m_out->Print( aNestLevel, "(general\n" );
|
||||
// Write Bounding box info
|
||||
m_out->Print( aNestLevel+1, "(thickness %s)\n",
|
||||
FMTIU( dsnSettings.GetBoardThickness() ).c_str() );
|
||||
FMT_IU( dsnSettings.GetBoardThickness() ).c_str() );
|
||||
|
||||
m_out->Print( aNestLevel+1, "(drawings %d)\n", aBoard->Drawings().Size() );
|
||||
m_out->Print( aNestLevel+1, "(tracks %d)\n", aBoard->GetNumSegmTrack() );
|
||||
|
|
|
@ -144,7 +144,7 @@ static IO_MGR::PCB_FILE_T detect_file_type( FILE* aFile, const wxFileName& aFile
|
|||
|
||||
if( !strncasecmp( line, "(module", strlen( "(module" ) ) )
|
||||
{
|
||||
file_type = IO_MGR::KICAD;
|
||||
file_type = IO_MGR::KICAD_SEXP;
|
||||
*aName = aFileName.GetName();
|
||||
}
|
||||
else if( !strncasecmp( line, FOOTPRINT_LIBRARY_HEADER, FOOTPRINT_LIBRARY_HEADER_CNT ) )
|
||||
|
@ -240,7 +240,7 @@ MODULE* try_load_footprint( const wxFileName& aFileName, IO_MGR::PCB_FILE_T aFil
|
|||
module = parse_module_with_plugin( aFileName, aFileType, aName );
|
||||
break;
|
||||
|
||||
case IO_MGR::KICAD:
|
||||
case IO_MGR::KICAD_SEXP:
|
||||
module = parse_module_kicad( aFileName );
|
||||
break;
|
||||
|
||||
|
@ -441,27 +441,47 @@ bool FOOTPRINT_EDIT_FRAME::SaveCurrentModule( const wxString* aLibPath )
|
|||
return true;
|
||||
}
|
||||
|
||||
wxString PCB_BASE_EDIT_FRAME::CreateNewLibrary()
|
||||
wxString PCB_BASE_EDIT_FRAME::CreateNewLibrary(const wxString& aLibName )
|
||||
{
|
||||
// Kicad cannot write legacy format libraries, only .pretty new format
|
||||
// because the legacy format cannot handle current features.
|
||||
// The footprint library is actually a directory
|
||||
|
||||
// prompt user for footprint library name, ending by ".pretty"
|
||||
// if a library name is not given, prompt user for footprint library name, ending by ".pretty"
|
||||
// Because there are constraints for the directory name to create,
|
||||
// (the name should have the extension ".pretty", and the folder cannot be inside
|
||||
// a footprint library), we do not use the standard wxDirDialog.
|
||||
|
||||
|
||||
wxString initialPath = wxPathOnly( Prj().GetProjectFullName() );
|
||||
DIALOG_SELECT_PRETTY_LIB dlg( this, initialPath );
|
||||
|
||||
if( dlg.ShowModal() != wxID_OK )
|
||||
return wxEmptyString;
|
||||
wxString libPath;
|
||||
|
||||
wxString libPath = dlg.GetFullPrettyLibName();
|
||||
if( aLibName.IsEmpty() )
|
||||
{
|
||||
DIALOG_SELECT_PRETTY_LIB dlg( this, initialPath );
|
||||
|
||||
// We can save fp libs only using IO_MGR::KICAD format (.pretty libraries)
|
||||
IO_MGR::PCB_FILE_T piType = IO_MGR::KICAD;
|
||||
if( dlg.ShowModal() != wxID_OK )
|
||||
return wxEmptyString;
|
||||
|
||||
libPath = dlg.GetFullPrettyLibName();
|
||||
}
|
||||
else
|
||||
{
|
||||
wxFileName fn = aLibName;
|
||||
|
||||
if( !fn.IsAbsolute() )
|
||||
fn.MakeAbsolute( initialPath );
|
||||
|
||||
// Enforce the extension:
|
||||
fn.SetExt( KiCadFootprintLibPathExtension );
|
||||
|
||||
libPath = fn.GetFullPath();
|
||||
}
|
||||
|
||||
|
||||
// We can save fp libs only using IO_MGR::KICAD_SEXP format (.pretty libraries)
|
||||
IO_MGR::PCB_FILE_T piType = IO_MGR::KICAD_SEXP;
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -570,7 +590,7 @@ bool FOOTPRINT_EDIT_FRAME::DeleteModuleFromCurrentLibrary()
|
|||
}
|
||||
|
||||
|
||||
void PCB_EDIT_FRAME::ArchiveModulesOnBoard( bool aStoreInNewLib )
|
||||
void PCB_EDIT_FRAME::ArchiveModulesOnBoard( bool aStoreInNewLib, const wxString& aLibName )
|
||||
{
|
||||
if( GetBoard()->m_Modules == NULL )
|
||||
{
|
||||
|
@ -611,12 +631,12 @@ void PCB_EDIT_FRAME::ArchiveModulesOnBoard( bool aStoreInNewLib )
|
|||
{
|
||||
// The footprints are saved in a new .pretty library.
|
||||
// If this library already exists, all previous footprints will be deleted
|
||||
wxString libPath = CreateNewLibrary();
|
||||
wxString libPath = CreateNewLibrary( aLibName );
|
||||
|
||||
if( libPath.IsEmpty() ) // Aborted
|
||||
return;
|
||||
|
||||
IO_MGR::PCB_FILE_T piType = IO_MGR::KICAD;
|
||||
IO_MGR::PCB_FILE_T piType = IO_MGR::KICAD_SEXP;
|
||||
PLUGIN::RELEASER pi( IO_MGR::PluginFind( piType ) );
|
||||
|
||||
for( MODULE* curr_fp = GetBoard()->m_Modules; curr_fp; curr_fp = curr_fp->Next() )
|
||||
|
|
|
@ -52,14 +52,16 @@ public:
|
|||
|
||||
/**
|
||||
* Function CreateNewLibrary
|
||||
* prompts user for a library path, then creates a new footprint library at that
|
||||
* location. If library exists, user is warned about that, and is given a chance
|
||||
* If a library name is given, creates a new footprint library in the project folder
|
||||
* with the given name. If no library name is given it prompts user for a library path,
|
||||
* then creates a new footprint library at that location.
|
||||
* If library exists, user is warned about that, and is given a chance
|
||||
* to abort the new creation, and in that case existing library is first deleted.
|
||||
*
|
||||
* @return wxString - the newly created library path if library was successfully
|
||||
* created, else wxEmptyString because user aborted or error.
|
||||
*/
|
||||
wxString CreateNewLibrary();
|
||||
wxString CreateNewLibrary(const wxString& aLibName = wxEmptyString);
|
||||
|
||||
/**
|
||||
* Function OnEditItemRequest
|
||||
|
|
|
@ -60,7 +60,7 @@ void ScriptingSetPcbEditFrame( PCB_EDIT_FRAME* aPcbEditFrame )
|
|||
BOARD* LoadBoard( wxString& aFileName )
|
||||
{
|
||||
if( aFileName.EndsWith( wxT( ".kicad_pcb" ) ) )
|
||||
return LoadBoard( aFileName, IO_MGR::KICAD );
|
||||
return LoadBoard( aFileName, IO_MGR::KICAD_SEXP );
|
||||
|
||||
else if( aFileName.EndsWith( wxT( ".brd" ) ) )
|
||||
return LoadBoard( aFileName, IO_MGR::LEGACY );
|
||||
|
@ -95,7 +95,7 @@ bool SaveBoard( wxString& aFileName, BOARD* aBoard, IO_MGR::PCB_FILE_T aFormat )
|
|||
|
||||
bool SaveBoard( wxString& aFileName, BOARD* aBoard )
|
||||
{
|
||||
return SaveBoard( aFileName, aBoard, IO_MGR::KICAD );
|
||||
return SaveBoard( aFileName, aBoard, IO_MGR::KICAD_SEXP );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -30,10 +30,10 @@
|
|||
#define WXPCB_STRUCT_H_
|
||||
|
||||
|
||||
#include <pcb_base_edit_frame.h>
|
||||
#include <config_params.h>
|
||||
#include <class_undoredo_container.h>
|
||||
#include <zones.h>
|
||||
#include "pcb_base_edit_frame.h"
|
||||
#include "config_params.h"
|
||||
#include "class_undoredo_container.h"
|
||||
#include "zones.h"
|
||||
|
||||
|
||||
/* Forward declarations of classes. */
|
||||
|
@ -864,6 +864,14 @@ public:
|
|||
*/
|
||||
bool AppendBoardFile( const wxString& aFullFileName, int aCtl );
|
||||
|
||||
/**
|
||||
* Function ImportFile
|
||||
* load the given filename but sets the path to the current project path.
|
||||
* @param full filepath of file to be imported.
|
||||
* @param aFileType PCB_FILE_T value for filetype
|
||||
*/
|
||||
bool ImportFile( const wxString& aFileName, int aFileType ) override;
|
||||
|
||||
/**
|
||||
* Function SavePcbFile
|
||||
* writes the board data structures to \a a aFileName
|
||||
|
@ -933,8 +941,12 @@ public:
|
|||
* This lib should be in fp lib table, and is type is .pretty
|
||||
* false: save modules in a new lib. It it is an existing lib,
|
||||
* previous footprints will be removed
|
||||
*
|
||||
* @param aLibName:
|
||||
* optional library name to create, stops dialog call.
|
||||
* must be called with aStoreInNewLib as true
|
||||
*/
|
||||
void ArchiveModulesOnBoard( bool aStoreInNewLib );
|
||||
void ArchiveModulesOnBoard( bool aStoreInNewLib, const wxString& aLibName = wxEmptyString );
|
||||
|
||||
/**
|
||||
* Function RecreateBOMFileFromBoard
|
||||
|
@ -1546,7 +1558,7 @@ public:
|
|||
bool aDeleteExtraFootprints,
|
||||
bool aSelectByTimestamp,
|
||||
bool aDeleteSinglePadNets,
|
||||
bool aIsDryRun );
|
||||
bool aIsDryRun ) override;
|
||||
|
||||
/**
|
||||
* Function RemoveMisConnectedTracks
|
Loading…
Reference in New Issue