Added component table dialog

- Allows grouping of matched components
- Bulk edit of components in a spreadsheet window
- User can choose to save / undo changes
- All changes are pushed to the undo stack in a single operation
- Export table to HTML / CSV output
This commit is contained in:
Oliver 2017-04-02 22:09:01 +10:00 committed by Wayne Stambaugh
parent 097f89dcbc
commit a39856485c
27 changed files with 5090 additions and 2 deletions

View File

@ -531,6 +531,7 @@ set( BMAPS_MID
show_no_layers
show_no_copper_layers
show_all_copper_layers
spreadsheet
svg_file
swap_layer
text_sketch

View File

@ -0,0 +1,45 @@
/* Do not modify this file, it was automatically generated by the
* PNG2cpp CMake script, using a *.png file as input.
*/
#include <bitmaps.h>
static const unsigned char png[] = {
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52,
0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x1a, 0x08, 0x06, 0x00, 0x00, 0x00, 0xa9, 0x4a, 0x4c,
0xce, 0x00, 0x00, 0x01, 0xbd, 0x49, 0x44, 0x41, 0x54, 0x48, 0xc7, 0x63, 0x60, 0xa0, 0x17, 0x10,
0x92, 0x90, 0x08, 0xe3, 0xd5, 0x32, 0x7b, 0xcd, 0xa7, 0x6b, 0xfd, 0x9e, 0x47, 0xdd, 0xe4, 0x23,
0x8f, 0x86, 0xc9, 0x47, 0x10, 0x1b, 0x19, 0x73, 0xab, 0xe8, 0x7d, 0x22, 0x46, 0x8c, 0x57, 0xc3,
0xf4, 0x23, 0xc8, 0x0c, 0x14, 0x31, 0x4d, 0xb3, 0xd7, 0x82, 0x32, 0x4a, 0x51, 0x0c, 0xc2, 0xb2,
0x4a, 0x77, 0x18, 0x5a, 0xf6, 0xff, 0x67, 0x68, 0x3d, 0xf0, 0x9f, 0x21, 0xa9, 0xef, 0x3f, 0x43,
0x72, 0x3f, 0x84, 0x8d, 0x8c, 0x1d, 0x62, 0x89, 0x13, 0x4b, 0x9d, 0xf4, 0x9f, 0x21, 0xa1, 0x1b,
0x55, 0x0c, 0x68, 0x36, 0xaf, 0x9a, 0xc1, 0x13, 0x06, 0x61, 0x79, 0xd5, 0xfb, 0x70, 0x41, 0x5a,
0x58, 0x04, 0xc4, 0x7c, 0x1a, 0x26, 0xcf, 0xe9, 0x67, 0x11, 0x9f, 0xb8, 0xf4, 0x33, 0xb0, 0x26,
0x10, 0xd6, 0x77, 0xfd, 0xaf, 0xe7, 0xec, 0xfb, 0xdf, 0x39, 0x26, 0x03, 0x05, 0x2b, 0xe8, 0x18,
0x11, 0x25, 0x66, 0xec, 0xe6, 0xff, 0xdf, 0xc0, 0xc9, 0x1b, 0x43, 0x9c, 0x4f, 0x4c, 0xfa, 0x29,
0x86, 0x8f, 0x16, 0x2e, 0x5f, 0xf5, 0xff, 0xd9, 0xb3, 0x67, 0x28, 0x38, 0x3f, 0x3f, 0x9f, 0x28,
0xb1, 0xf5, 0xeb, 0xd7, 0xff, 0x5f, 0xb6, 0x6c, 0x19, 0x86, 0xb8, 0x84, 0x84, 0xc4, 0xcd, 0x61,
0x68, 0x91, 0x90, 0x9c, 0xd2, 0x03, 0x86, 0x8a, 0x75, 0xff, 0xc1, 0x38, 0xa2, 0xe1, 0xff, 0xa4,
0xe9, 0xb3, 0xfe, 0x5f, 0xb8, 0x70, 0x01, 0x05, 0xa7, 0xa4, 0xa4, 0x10, 0x25, 0x36, 0x6f, 0xde,
0xbc, 0xff, 0xd3, 0xa6, 0x4d, 0xc3, 0x10, 0x17, 0x13, 0x13, 0xbb, 0xc5, 0x20, 0x20, 0x21, 0xfb,
0x94, 0xc1, 0x37, 0xff, 0x3f, 0x18, 0x5b, 0x06, 0xfd, 0x8f, 0x4d, 0x48, 0xfa, 0xdf, 0xda, 0xda,
0x8a, 0x82, 0x1d, 0x1c, 0x1c, 0x88, 0x12, 0x4b, 0x4d, 0x4d, 0xfd, 0x9f, 0x90, 0x90, 0x80, 0x21,
0x2e, 0x24, 0x24, 0xf4, 0x60, 0x34, 0x31, 0x90, 0x6f, 0x91, 0x80, 0xa4, 0xdc, 0x13, 0x86, 0x90,
0xaa, 0xff, 0x60, 0x6c, 0x17, 0xf5, 0x3f, 0x2d, 0x2b, 0xe7, 0xff, 0xa4, 0x49, 0x93, 0x50, 0xb0,
0x9b, 0x9b, 0x1b, 0x51, 0x62, 0x20, 0xcb, 0x33, 0x33, 0x33, 0x31, 0xc4, 0x45, 0x44, 0x44, 0xee,
0x31, 0x08, 0xc9, 0x28, 0x3d, 0x64, 0x28, 0x5c, 0xfc, 0x1f, 0x8c, 0x83, 0x2b, 0xfe, 0x77, 0xf4,
0x4d, 0xf8, 0x7f, 0xf8, 0xf0, 0x61, 0x14, 0x1c, 0x17, 0x17, 0x47, 0x94, 0xd8, 0x94, 0x29, 0x53,
0xfe, 0xf7, 0xf6, 0xf6, 0x62, 0x88, 0x8b, 0x8a, 0x8a, 0xde, 0x1e, 0x4d, 0x0c, 0xe4, 0x5b, 0x84,
0x5e, 0x7a, 0xfb, 0x06, 0x04, 0x81, 0x0d, 0x41, 0xc6, 0x66, 0x66, 0x66, 0x44, 0x89, 0x85, 0x84,
0x84, 0xfc, 0x0f, 0x08, 0x08, 0xc0, 0x10, 0x07, 0x66, 0xd8, 0x87, 0xa3, 0x71, 0x44, 0x81, 0x45,
0x68, 0x8d, 0x13, 0x6a, 0x5b, 0xf4, 0xe4, 0xc9, 0x13, 0x50, 0x3e, 0xba, 0x86, 0xd1, 0xdc, 0x12,
0x97, 0x90, 0x7a, 0x2a, 0x25, 0x25, 0xf5, 0x08, 0x19, 0x03, 0x15, 0x3e, 0x27, 0x46, 0x4c, 0x5c,
0x5c, 0xfc, 0x09, 0x10, 0xa3, 0xe8, 0x07, 0xfa, 0xe6, 0xae, 0xb0, 0xb0, 0x70, 0x10, 0xdd, 0xda,
0x8f, 0x00, 0x62, 0x96, 0x75, 0xd5, 0x49, 0xff, 0x1d, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45,
0x4e, 0x44, 0xae, 0x42, 0x60, 0x82,
};
const BITMAP_OPAQUE spreadsheet_xpm[1] = {{ png, sizeof( png ), "spreadsheet_xpm" }};
//EOF

View File

@ -0,0 +1,440 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.0"
width="26"
height="26"
id="svg2"
inkscape:version="0.91 r13725"
sodipodi:docname="spreadsheet.svg">
<metadata
id="metadata166">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1017"
id="namedview164"
showgrid="true"
inkscape:zoom="11.313709"
inkscape:cx="-3.9181807"
inkscape:cy="-0.64398435"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:current-layer="g4260"
inkscape:snap-to-guides="false"
inkscape:snap-grids="false">
<inkscape:grid
type="xygrid"
id="grid3041"
empspacing="1"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true" />
</sodipodi:namedview>
<defs
id="defs4">
<clipPath
id="ba">
<path
style="fill:#ffffff"
d="m 0,96 v 60 H 96 V 96 H 0 z m 68,20 c 9.9411,0 18,8.0589 18,18 0,9.9411 -8.0589,18 -18,18 -9.9411,0 -18,-8.0589 -18,-18 0,-9.9411 8.0589,-18 18,-18 z"
id="path125"
inkscape:connector-curvature="0" />
</clipPath>
<linearGradient
id="bl"
y2="5.9782"
gradientUnits="userSpaceOnUse"
x2="69"
gradientTransform="matrix(-0.2255,-0.071329,0.05452,-0.20327,7.6326,90.834)"
y1="122"
x1="69">
<stop
stop-color="#1e71ac"
offset="0"
id="stop128" />
<stop
stop-color="#81c1e9"
offset="1"
id="stop130" />
</linearGradient>
<linearGradient
id="bm"
y2="67.706001"
xlink:href="#a"
gradientUnits="userSpaceOnUse"
x2="118.33"
gradientTransform="matrix(0.39018,0.62586,-0.63862,0.30043,3.5817,-20.909)"
y1="87.488998"
x1="120.65" />
<linearGradient
id="a">
<stop
offset="0"
id="stop15" />
<stop
stop-opacity="0"
offset="1"
id="stop17" />
</linearGradient>
<linearGradient
id="bn"
y2="5.9782"
gradientUnits="userSpaceOnUse"
x2="69"
gradientTransform="matrix(-0.2255,-0.071329,0.05452,-0.20327,7.6018,90.825)"
y1="122"
x1="69">
<stop
stop-color="#cd2323"
offset="0"
id="stop134" />
<stop
stop-color="#ef7474"
offset="1"
id="stop136" />
</linearGradient>
<linearGradient
id="ao"
y2="67.706001"
xlink:href="#a"
gradientUnits="userSpaceOnUse"
x2="118.33"
y1="87.488998"
x1="120.65" />
<clipPath
id="aq">
<path
style="fill:url(#linearGradient4033)"
d="m 118,56 c -9.9411,0 -18,8.0589 -18,18 0,9.9411 8.0589,18 18,18 9.7305,0 17.637,-7.7253 17.969,-17.375 v -1.25 C 135.639,63.725 127.729,56 117.999,56 z m -6,10.75 c 5.9493,0.05747 10.832,4.9413 11.031,10.875 l 3.75,0.03125 -6,8.7188 -6.1562,-8.8125 3.9688,0.03125 c -0.25101,-4.9057 -4.4893,-9.9506 -11.719,-9.625 1.5223,-0.80073 3.2718,-1.2367 5.125,-1.2188 z"
id="path122"
inkscape:connector-curvature="0" />
</clipPath>
<linearGradient
id="bo"
y2="5.1837001"
xlink:href="#an"
gradientUnits="userSpaceOnUse"
x2="84.360001"
gradientTransform="matrix(0.21868,0.069171,-0.053262,0.19858,-13.124,56.327)"
y1="79.417"
x1="84.360001" />
<linearGradient
id="an">
<stop
stop-color="#fff"
offset="0"
id="stop65" />
<stop
stop-color="#fff"
stop-opacity=".49804"
offset=".43290"
id="stop67" />
<stop
stop-color="#fff"
stop-opacity="0"
offset="1"
id="stop69" />
</linearGradient>
<linearGradient
id="bp"
y2="67.706001"
xlink:href="#a"
gradientUnits="userSpaceOnUse"
x2="118.33"
gradientTransform="matrix(-0.39018,-0.62586,0.63862,-0.30043,-9.9736,166.82)"
y1="87.488998"
x1="120.65" />
<linearGradient
y2="67.706001"
x2="118.33"
y1="87.488998"
x1="120.65"
gradientUnits="userSpaceOnUse"
id="linearGradient3263"
xlink:href="#a"
inkscape:collect="always" />
<linearGradient
y2="5.1837001"
x2="84.360001"
y1="79.417"
x1="84.360001"
gradientTransform="matrix(-0.21868,-0.069171,0.053262,-0.19858,6.7324,89.587)"
gradientUnits="userSpaceOnUse"
id="linearGradient3265"
xlink:href="#an"
inkscape:collect="always" />
<linearGradient
id="i"
y2="6.7758002"
gradientUnits="userSpaceOnUse"
x2="20.631001"
gradientTransform="matrix(0.87827,0,0,0.87827,56.157,5.6701)"
y1="42.254002"
x1="19.648001">
<stop
stop-color="#b6b6b6"
offset="0"
id="stop3120" />
<stop
stop-color="#f2f2f2"
offset=".5"
id="stop3122" />
<stop
stop-color="#fafafa"
offset=".67613"
id="stop3124" />
<stop
stop-color="#d8d8d8"
offset=".84052"
id="stop3126" />
<stop
stop-color="#f2f2f2"
offset=".875"
id="stop3128" />
<stop
stop-color="#dbdbdb"
offset="1"
id="stop3130" />
</linearGradient>
<linearGradient
id="j"
y2="-4.3003001"
gradientUnits="userSpaceOnUse"
x2="25.291"
gradientTransform="matrix(0.87827,0,0,0.87827,43.255,-36.26)"
y1="-3.6324"
x1="50.153">
<stop
stop-color="#fff"
offset="0"
id="stop3133"
style="stop-color:#4754ba;stop-opacity:1;" />
<stop
offset="1"
id="stop3135" />
</linearGradient>
<linearGradient
id="k"
y2="6.6286001"
gradientUnits="userSpaceOnUse"
x2="37.535"
gradientTransform="matrix(0.87827,0,0,0.87827,56.467,6.2911)"
y1="13.603"
x1="38.228001">
<stop
stop-color="#98a0a9"
offset="0"
id="stop3138" />
<stop
stop-color="#c3d0dd"
offset="1"
id="stop3140" />
</linearGradient>
<linearGradient
id="l"
y2="9.6569004"
gradientUnits="userSpaceOnUse"
x2="40.859001"
gradientTransform="translate(53.62,0.70241)"
y1="19.822001"
x1="31.177">
<stop
stop-color="#fff"
offset="0"
id="stop3143" />
<stop
stop-color="#fff"
stop-opacity="0"
offset="1"
id="stop3145" />
</linearGradient>
<linearGradient
id="m"
y2="39.443001"
gradientUnits="userSpaceOnUse"
x2="16.915001"
gradientTransform="matrix(0.87827,0,0,0.87827,56.157,5.6701)"
y1="32.284"
x1="9.7503004">
<stop
stop-color="#3465a4"
offset="0"
id="stop3148" />
<stop
stop-color="#9fbce1"
offset="0"
id="stop3150" />
<stop
stop-color="#6b95ca"
offset="0"
id="stop3152" />
<stop
stop-color="#3d6aa5"
offset=".75"
id="stop3154" />
<stop
stop-color="#386eb4"
offset="1"
id="stop3156" />
</linearGradient>
<linearGradient
id="n"
y2="33.195"
gradientUnits="userSpaceOnUse"
x2="10.651"
gradientTransform="matrix(1.0073,-0.026365,0.026365,1.0073,55.213,0.7816)"
y1="35.688"
x1="12.005">
<stop
stop-color="#fff"
offset="0"
id="stop3159" />
<stop
stop-color="#fff"
stop-opacity="0"
offset="1"
id="stop3161" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#o"
id="linearGradient4456"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.77155263,-0.0151812,0.01522193,0.76948813,58.140667,26.736849)"
x1="14.018"
y1="36.943001"
x2="15.416"
y2="38.268002" />
<linearGradient
id="o"
y2="38.268002"
gradientUnits="userSpaceOnUse"
x2="15.416"
gradientTransform="matrix(0.8781,-0.017324,0.017324,0.8781,55.783,4.7703)"
y1="36.943001"
x1="14.018">
<stop
offset="0"
id="stop3164" />
<stop
stop-opacity="0"
offset="1"
id="stop3166" />
</linearGradient>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath4282">
<rect
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.51315969;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4284"
width="24.723595"
height="22.915451"
x="0.47398946"
y="1.1851474"
rx="0.84872037"
ry="0.84872037" />
</clipPath>
</defs>
<g
id="g4260"
transform="translate(0.16421321,0.35712707)"
style="fill:#f2f2f2">
<rect
ry="0.84872037"
rx="0.84872037"
y="1.1851474"
x="0.47398946"
height="22.915451"
width="24.723595"
id="rect3442"
style="fill:#e6e6e6;fill-rule:evenodd;stroke:#000000;stroke-width:0.51315969;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
style="fill:#0085c0;fill-opacity:1;stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none"
clip-path="url(#clipPath4282)"
d="m 0.39828682,0.0989943 26.62500018,-0.65625 -0.375,5.5642841 -22.7500002,0.033034 0,19.7903105 -3.49999998,0 z"
id="rect4278"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccc" />
<path
inkscape:connector-curvature="0"
id="path4244"
d="m 0.40018765,19.266078 24.87119735,0"
style="fill:#f2f2f2;fill-rule:evenodd;stroke:#000000;stroke-width:0.51315969;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
style="fill:#f2f2f2;fill-rule:evenodd;stroke:#000000;stroke-width:0.51315969;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 0.40018765,14.536363 24.87119735,0"
id="path4246"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
id="path4248"
d="m 0.40018765,9.8066493 24.87119735,0"
style="fill:#f2f2f2;fill-rule:evenodd;stroke:#000000;stroke-width:0.51315969;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
style="fill:#f2f2f2;fill-rule:evenodd;stroke:#000000;stroke-width:0.51315969;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 0.40018765,5.076934 24.87119735,0"
id="path4250"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
id="path4254"
d="m 19.854056,24.026795 0,-22.758288"
style="fill:#f2f2f2;fill-rule:evenodd;stroke:#000000;stroke-width:0.51315969;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
sodipodi:nodetypes="cc" />
<path
style="fill:#f2f2f2;fill-rule:evenodd;stroke:#000000;stroke-width:0.51315969;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 14.512679,24.026795 0,-22.758288"
id="path4256"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
inkscape:connector-curvature="0"
id="path4258"
d="m 9.1713038,24.026795 0,-22.758288"
style="fill:#f2f2f2;fill-rule:evenodd;stroke:#000000;stroke-width:0.51315969;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
sodipodi:nodetypes="cc" />
<path
style="fill:#f2f2f2;fill-rule:evenodd;stroke:#000000;stroke-width:0.51315969;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 3.8299284,24.026795 0,-22.758288"
id="path4270"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<rect
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.51315969;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4286"
width="24.723595"
height="22.915451"
x="0.47398946"
y="1.1851474"
rx="0.84872037"
ry="0.84872037" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -97,6 +97,7 @@ DIALOG_SHIM::~DIALOG_SHIM()
if( IsQuasiModal() )
EndQuasiModal( wxID_CANCEL );
if( m_qmodal_parent_disabler )
delete m_qmodal_parent_disabler; // usually NULL by now
}

View File

@ -94,6 +94,7 @@ const wxString ComponentFileWildcard( _( "KiCad cmp/footprint link files (*.cmp)
const wxString DrillFileWildcard( _( "Drill files (*.drl)|*.drl;*.DRL" ) );
const wxString SVGFileWildcard( _( "SVG files (*.svg)|*.svg;*.SVG" ) );
const wxString HtmlFileWildcard( _( "HTML files (*.html)|*.htm;*.html" ) );
const wxString CsvFileWildcard( _( "CSV Files (*.csv)|*.csv" ) );
const wxString PdfFileWildcard( _( "Portable document format files (*.pdf)|*.pdf" ) );
const wxString PSFileWildcard( _( "PostScript files (.ps)|*.ps" ) );
const wxString ReportFileWildcard = _( "Report files (*.rpt)|*.rpt" );

View File

@ -25,6 +25,8 @@ set( EESCHEMA_DLGS
dialogs/dialog_annotate_base.cpp
dialogs/dialog_bom.cpp
dialogs/dialog_bom_base.cpp
dialogs/dialog_bom_editor.cpp
dialogs/dialog_bom_editor_base.cpp
dialogs/dialog_bom_cfg_keywords.cpp
dialogs/dialog_choose_component.cpp
dialogs/dialog_lib_edit_text.cpp
@ -85,6 +87,9 @@ set( EESCHEMA_SRCS
backanno.cpp
block.cpp
block_libedit.cpp
bom_exporter.cpp
bom_table_model.cpp
bom_table_column.cpp
busentry.cpp
bus-wire-junction.cpp
class_drc_erc_item.cpp

420
eeschema/bom_exporter.cpp Normal file
View File

@ -0,0 +1,420 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2017 Oliver Walters
* Copyright (C) 2017 KiCad Developers, see CHANGELOG.TXT for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 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 "bom_exporter.h"
/**
* BOM_FILE_WRITER class (pure virtual)
*/
BOM_FILE_WRITER::BOM_FILE_WRITER() :
m_includeExtraData( true ),
m_showRowNumbers( true )
{
}
void BOM_FILE_WRITER::SetHeader( const wxArrayString aHeader )
{
m_bomHeader = aHeader;
}
void BOM_FILE_WRITER::AddLine( wxArrayString aLine )
{
m_bomLines.push_back( aLine );
}
/**
* Function ExtraDataPairs
* Format extra data for writing to file
*/
wxArrayString BOM_FILE_WRITER::ExtraDataPairs()
{
wxArrayString pairs;
if( m_groupCount != m_componentCount )
{
pairs.Add( DataPair( _( "Group Count" ), m_groupCount ) );
}
pairs.Add( DataPair( _( "Component Count" ), m_componentCount ) );
pairs.Add( DataPair( _( "Schematic Title" ), m_schematicTitle ) );
pairs.Add( DataPair( _( "Schematic Date" ), m_schematicDate ) );
pairs.Add( DataPair( _( "Schematic Version" ), m_schematicVersion ) );
pairs.Add( DataPair( _( "KiCad Version" ), m_kicadVersion ) );
return pairs;
}
BOM_CSV_WRITER::BOM_CSV_WRITER( wxChar aDelim ) :
BOM_FILE_WRITER()
{
m_delim = aDelim;
}
/**
* Function WriteToFile
* Write delimited data to file
*/
bool BOM_CSV_WRITER::WriteToFile( wxFile& aFile )
{
// Generate table header
wxString line = wxJoin( EscapeLine( m_bomHeader ), m_delim )+ "\n";
if( m_showRowNumbers )
{
line = m_delim + line;
}
if( !aFile.Write( line ))
{
return false;
}
// Write each line in the file
for( unsigned int ii=0; ii<m_bomLines.size(); ii++ )
{
line = wxJoin( EscapeLine( m_bomLines[ii]), m_delim ) + "\n";
if( m_showRowNumbers )
{
line = wxString::Format( _( "%i" ), ii+1 ) + m_delim + line;
}
if( !aFile.Write( line ) )
{
return false;
}
}
// Write extra options
if( m_includeExtraData )
{
wxString extra;
extra += "\n\n";
for( wxString pair : ExtraDataPairs() )
{
extra += pair;
extra += "\n";
}
if( !aFile.Write( extra ) )
return false;
}
// File writing successful
return true;
}
/**
* Function DataPair
* Combine two items into a delimited pair
*/
wxString BOM_CSV_WRITER::DataPair( const wxString& aFirst, const wxString& aSecond )
{
wxArrayString pair;
pair.Add( aFirst );
pair.Add( aSecond );
return wxJoin( pair, m_delim );
}
/**
* Function EscapeLine
* Any values that contain the delimiter are escaped with quotes
*/
wxArrayString BOM_CSV_WRITER::EscapeLine( wxArrayString line )
{
wxArrayString escaped;
for( wxString item : line )
{
if( item.Contains( m_delim ) &&
!item.StartsWith( "\"" ) &&
!item.EndsWith( "\"" ) )
{
item = "\"" + item + "\"";
}
escaped.Add( item );
}
return escaped;
}
BOM_HTML_WRITER::BOM_HTML_WRITER() :
BOM_FILE_WRITER()
{
// Strings to check for hyperlinkable text
m_linkChecks.Add( "http:*" );
m_linkChecks.Add( "https:* " );
m_linkChecks.Add( "ftp:*" );
m_linkChecks.Add( "www.*" );
m_linkChecks.Add( "*.pdf" );
m_linkChecks.Add( "*.html" );
m_linkChecks.Add( "*.htm" );
}
/**
* Function WriteToFile
* Write HTML BoM Data
*/
bool BOM_HTML_WRITER::WriteToFile( wxFile& aFile )
{
// Write HTML header
if( !aFile.Write( HtmlHeader() ) )
return false;
if( m_includeExtraData )
{
if( !aFile.Write( ExtraData() ) )
return false;
}
// Table data
wxString tableTitle = "<h2>";
tableTitle += _( "Bill of Materials" );
tableTitle += "</h2>\n";
if( !aFile.Write( tableTitle ) )
return false;
if( !aFile.Write( "<table border=\"1\">\n" ) )
return false;
if( !aFile.Write( TableHeader( m_bomHeader ) ) )
return false;
// Write each line of the BOM
for( unsigned int ii=0; ii<m_bomLines.size(); ii++ )
{
if( !aFile.Write( TableRow( ii+1, m_bomLines[ii] ) ) )
return false;
}
if( !aFile.Write( "</table>\n" ) )
return false;
if( !aFile.Write( HtmlFooter() ) )
return false;
return true;
}
wxString BOM_HTML_WRITER::HtmlHeader()
{
wxString header = wxEmptyString;
header += "<html>\n<head>\n";
//TODO - Project title
header += "<title>";
header += m_schematicTitle;
header += "</title>\n";
header += HtmlMetaTag( "charset", "UTF-8" ) + "\n";
//TODO - KiCad reference data here
header += "</head>\n\n";
header += "<body>\n";
return header;
}
wxString BOM_HTML_WRITER::HtmlFooter()
{
wxString footer = wxEmptyString;
footer += "</body>\n\n";
footer += "</html>\n";
return footer;
}
wxString BOM_HTML_WRITER::HtmlMetaTag( const wxString aTitle, const wxString aData )
{
wxString tag = "<meta name=\"";
tag += aTitle + "\"";
tag += " content=\"";
tag += aData + "\"";
tag += ">";
return tag;
}
/**
* Function ExtraData
* Write extra project information
*/
wxString BOM_HTML_WRITER::ExtraData()
{
wxString extra;
extra += "<h2>";
extra += _( "Project details" );
extra += "</h2>\n";
extra += "<table border=\"1\">\n";
for( wxString pair : ExtraDataPairs() )
{
extra += pair + "\n";
}
extra += "</table>\n";
return extra;
}
/**
* Function LinkText
* Automatically detect linkable text, and wrap it in <a> tag
* @aText - Text to (potentially) link
*/
wxString BOM_HTML_WRITER::LinkText( const wxString& aText )
{
// Should we provide a link to the text?
wxString lower = aText.Lower();
bool found = false;
for( wxString check : m_linkChecks )
{
if( lower.Matches( check ) )
{
found = true;
break;
}
}
if( found )
{
wxString link = "<a href=\"";
link += aText;
link += "\">";
link += aText;
link += "</a>";
return link;
}
else
{
return aText;
}
}
wxString BOM_HTML_WRITER::TableHeader( const wxArrayString& aHeaderData )
{
wxString header = "<tr>\n";
if( m_showRowNumbers )
{
header += "<th></th>\n";
}
for( wxString item : aHeaderData )
{
header += "<th align=\"center\">";
header += item;
header += "</th>";
header += "\n";
}
header += "</tr>\n";
return header;
}
wxString BOM_HTML_WRITER::DataPair( const wxString& aFirst, const wxString& aSecond )
{
wxString html = "<tr>\n";
html += TableEntry( aFirst ) + "\n";
html += TableEntry( aSecond ) + "\n";
html += "</tr>\n";
return html;
}
/**
* Function TableRow
* Generate a single row of BOM data
* @aRowNum is the number of the row
* @aRowData is the array of data for the given row
*/
wxString BOM_HTML_WRITER::TableRow( const int& aRowNum, const wxArrayString& aRowData )
{
wxString row = wxEmptyString;
row += "<tr>\n";
if( m_showRowNumbers )
{
row += "<td>";
row += wxString::Format( "%i", aRowNum );
row += "</td>\n";
}
for( wxString data : aRowData )
{
row += TableEntry( data );
row += "\n";
}
row += "</tr>\n";
return row;
}
/**
* Function TableEntry
* Wrap a string in <td> tags
* @aData is the text to be wrapped
* @aColor is an (optional) HTML background color
*/
wxString BOM_HTML_WRITER::TableEntry( wxString aData, wxString aColor )
{
wxString cell = "<td align=\"center\"";
if( !aColor.IsEmpty() )
{
cell += " bgcolor=\"" + aColor + "\"";
}
cell += ">";
cell += LinkText( aData );
cell += "</td>";
return cell;
}

123
eeschema/bom_exporter.h Normal file
View File

@ -0,0 +1,123 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2017 Oliver Walters
* Copyright (C) 2017 KiCad Developers, see CHANGELOG.TXT for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 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 EESCHEMA_BOM_EXPORTER_H_
#define EESCHEMA_BOM_EXPORTER_H_
#include <vector>
#include <wx/file.h>
#include "bom_table_column.h"
#include "bom_table_model.h"
enum BOM_EXPORT_TYPE
{
BOM_EXPORT_CSV = 0,
BOM_EXPORT_HTML
};
class BOM_FILE_WRITER
{
public:
BOM_FILE_WRITER();
virtual ~BOM_FILE_WRITER() {};
virtual bool WriteToFile( wxFile& aFile ) = 0;
void SetHeader( const wxArrayString aHeader );
void AddLine( const wxArrayString aLine );
void IncludeExtraData( bool aInclude = true ) { m_includeExtraData = aInclude; }
void ShowRowNumbers( bool aShow = true ) { m_showRowNumbers = aShow; }
// Project information
void SetKicadVersion( const wxString aVersion ) { m_kicadVersion = aVersion; }
void SetSchematicTitle( const wxString aProject ) { m_schematicTitle = aProject; }
void SetSchematicVersion( const wxString aVersion ) { m_schematicVersion = aVersion; }
void SetSchematicDate( const wxString aDate ) { m_schematicDate = aDate; }
void SetGroupCount( unsigned int aCount ) { m_groupCount = wxString::Format( "%u", aCount ); }
void SetComponentCount( unsigned int aCount ) { m_componentCount = wxString::Format( "%u", aCount ); }
protected:
wxArrayString ExtraDataPairs();
virtual wxString DataPair( const wxString& aFirst, const wxString& aSecond ) = 0;
wxArrayString m_bomHeader;
std::vector< wxArrayString > m_bomLines;
bool m_includeExtraData;
bool m_showRowNumbers;
// Extra details for BOM file
wxString m_kicadVersion;
wxString m_schematicTitle;
wxString m_schematicVersion;
wxString m_schematicDate;
wxString m_componentCount;
wxString m_groupCount;
};
class BOM_CSV_WRITER : public BOM_FILE_WRITER
{
public:
BOM_CSV_WRITER( wxChar aDelim=',' );
virtual bool WriteToFile( wxFile& aFile ) override;
protected:
wxArrayString EscapeLine( wxArrayString line );
virtual wxString DataPair( const wxString& aFirst, const wxString& aSecond ) override;
wxChar m_delim;
};
class BOM_HTML_WRITER : public BOM_FILE_WRITER
{
public:
BOM_HTML_WRITER();
virtual bool WriteToFile( wxFile& aFile ) override;
protected:
virtual wxString DataPair( const wxString& aFirst, const wxString& aSecond ) override;
wxString HtmlHeader();
wxString HtmlFooter();
wxString HtmlMetaTag( const wxString aTitle, const wxString aData );
wxString ExtraData();
wxString LinkText( const wxString& aText );
wxString TableHeader( const wxArrayString& aHeaderData );
wxString TableRow( const int& aRowNum, const wxArrayString& aRowData );
wxString TableEntry( wxString aData, wxString aColor = wxEmptyString );
wxArrayString m_linkChecks;
};
#endif /* EESCHEMA_BOM_EXPORTER_H_ */

View File

@ -0,0 +1,136 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2017 Oliver Walters
* Copyright (C) 2017 KiCad Developers, see CHANGELOG.TXT for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 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 "bom_table_column.h"
BOM_COLUMN_LIST::BOM_COLUMN_LIST() : m_nextFieldId( BOM_COL_ID_USER )
{
}
void BOM_COLUMN_LIST::Clear()
{
Columns.clear();
m_nextFieldId = BOM_COL_ID_USER;
}
/**
* Return the number of columns
* @param aIncludeHidden - If this is false, only visible columns will be included
*/
unsigned int BOM_COLUMN_LIST::ColumnCount( bool aIncludeHidden ) const
{
unsigned int count = 0;
for( BOM_COLUMN* col : Columns )
{
if( col && ( col->IsVisible() || aIncludeHidden ) )
{
count++;
}
}
return count;
}
/**
* Return a column based on its stored position
*/
BOM_COLUMN* BOM_COLUMN_LIST::GetColumnByIndex( unsigned int aColId )
{
if( aColId < Columns.size() )
return Columns[aColId];
return nullptr;
}
/**
* Return a column based on its unique ID
*/
BOM_COLUMN* BOM_COLUMN_LIST::GetColumnById( unsigned int aColId )
{
for( unsigned int ii=0; ii<Columns.size(); ii++ )
{
if( Columns[ii] && Columns[ii]->Id() == aColId )
return Columns[ii];
}
return nullptr;
}
/**
* Return a column based on its string title
*/
BOM_COLUMN* BOM_COLUMN_LIST::GetColumnByTitle( wxString aColTitle )
{
for( unsigned int ii=0; ii<Columns.size(); ii++ )
{
if( Columns[ii] && Columns[ii]->Title().CmpNoCase( aColTitle ) == 0 )
return Columns[ii];
}
return nullptr;
}
/**
* Test if the list includes a column with the given unique ID
*/
bool BOM_COLUMN_LIST::ContainsColumn( unsigned int aColId )
{
for( BOM_COLUMN* col : Columns )
{
if( col && col->Id() == aColId )
return true;
}
return false;
}
/**
* Test if the list includes a column with the given title
*/
bool BOM_COLUMN_LIST::ContainsColumn( wxString aColTitle )
{
return nullptr != GetColumnByTitle( aColTitle );
}
/**
* Add a new column to the list
*/
bool BOM_COLUMN_LIST::AddColumn( BOM_COLUMN* aCol )
{
if( nullptr == aCol )
return false;
if( ContainsColumn( aCol->Id() ) )
return false;
Columns.push_back( aCol );
// If this is a user field, increment the counter
if( aCol->Id() >= BOM_COL_ID_USER )
m_nextFieldId++;
return true;
}

147
eeschema/bom_table_column.h Normal file
View File

@ -0,0 +1,147 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2017 Oliver Walters
* Copyright (C) 2017 KiCad Developers, see CHANGELOG.TXT for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 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 EESCHEMA_BOM_TABLE_COLUMN_H_
#define EESCHEMA_BOM_TABLE_COLUMN_H_
#include <wx/regex.h>
#include <wx/string.h>
#include <vector>
// Default column names (translated)
#define BOM_COL_TITLE_REFERENCE _( "Reference" )
#define BOM_COL_TITLE_DESCRIPTION _( "Description" )
#define BOM_COL_TITLE_FOOTPRINT _( "Footprint" )
#define BOM_COL_TITLE_VALUE _( "Value" )
#define BOM_COL_TITLE_DATASHEET _( "Datasheet" )
#define BOM_COL_TITLE_QUANTITY _( "Quantity" )
/**
* Column type enumeration
* Not currently implemented,
* in the future the different column 'types' might
* be used for something...
*/
enum BOM_COLUMN_TYPE
{
BOM_COL_TYPE_KICAD = 0, ///< Default column (editable)
BOM_COL_TYPE_LIBRARY, ///< Default column (non-editable)
BOM_COL_TYPE_GENERATED, ///< Generated column (e.g. Quantity)
BOM_COL_TYPE_USER, ///< User data
};
/**
* Predefined column ID values for default columns.
* User columns are assigned IDs of 1000 and above
*/
enum BOM_COLUMN_ID
{
// Default component fields
BOM_COL_ID_REFERENCE = 0,
BOM_COL_ID_DESCRIPTION,
BOM_COL_ID_FOOTPRINT,
BOM_COL_ID_VALUE,
BOM_COL_ID_DATASHEET,
// Meta-data fields
BOM_COL_ID_QUANTITY = 100,
// Custom data fields
BOM_COL_ID_USER = 1000,
};
/**
* BOM_COLUMN class
* Models a single column in the BOM view
* Each column can be used to group components,
* and can be hidden from the output BOM
*/
class BOM_COLUMN
{
protected:
unsigned int m_id; ///< Unique column ID
BOM_COLUMN_TYPE m_Type; ///< Column type
wxString m_Title; ///< The column (field) title
bool m_Show; ///< Is this column visible?
bool m_ReadOnly; ///< Is this column read only?
public:
BOM_COLUMN( unsigned int aId, BOM_COLUMN_TYPE aType, const wxString aTitle, bool aShow, bool aReadOnly = false ) :
m_id( aId ),
m_Type( aType ),
m_Title( aTitle.Strip( wxString::both ) ),
m_Show( aShow ),
m_ReadOnly( aReadOnly )
{
}
unsigned int Id() const { return m_id; }
BOM_COLUMN_TYPE Type() const { return m_Type; }
wxString Title() const { return m_Title; }
bool IsVisible() const { return m_Show; }
bool IsReadOnly() const { return m_ReadOnly; }
//TODO - Should renaming of columns be allowed?
//bool SetTitle( const wxString aTitle );
void SetVisible( bool aShow = true ) { m_Show = aShow; }
void SetReadOnly( bool aReadOnly = true ) { m_ReadOnly = aReadOnly; }
};
/*
* The BOM_COLUMN_LIST class contains information
* on all columns existing in the BOM
*/
class BOM_COLUMN_LIST
{
protected:
unsigned int m_nextFieldId;
public:
std::vector< BOM_COLUMN* > Columns;
BOM_COLUMN_LIST();
void Clear();
unsigned int NextFieldId() const { return m_nextFieldId; }
unsigned int ColumnCount( bool aIncludeHidden = true ) const;
BOM_COLUMN* GetColumnByIndex( unsigned int aColIndex );
BOM_COLUMN* GetColumnById( unsigned int aColId );
BOM_COLUMN* GetColumnByTitle( const wxString aColTitle ) ;
bool ContainsColumn( unsigned int aColId );
bool ContainsColumn( const wxString aColTitle );
bool AddColumn( BOM_COLUMN* aCol );
};
#endif /* EESCHEMA_BOM_TABLE_COLUMN_H_ */

1404
eeschema/bom_table_model.cpp Normal file

File diff suppressed because it is too large Load Diff

282
eeschema/bom_table_model.h Normal file
View File

@ -0,0 +1,282 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2017 Oliver Walters
* Copyright (C) 2017 KiCad Developers, see CHANGELOG.TXT for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 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 _EESCHEMA_BOM_TABLE_MODEL_H_
#define _EESCHEMA_BOM_TABLE_MODEL_H_
#include <wx/dataview.h>
#include <wx/regex.h>
#include <vector>
#include <map>
#include <sch_component.h>
#include <sch_reference_list.h>
#include <class_netlist_object.h>
#include <template_fieldnames.h>
#include "bom_table_column.h"
// Forward-declare classes
class BOM_TABLE_ROW; // Base-class for table row data model
class BOM_TABLE_GROUP; // Class for displaying a group of components
class BOM_TABLE_COMPONENT; // Class for displaying a single component
/**
* Virtual base class determining how a row is displayed
* There are three types of rows:
* GROUP - Displays a group of (one or more) components
* COMPONENT - Displays a single component
* UNIT - Child of COMPONENT for multi-unit components
*/
class BOM_TABLE_ROW
{
public:
BOM_TABLE_ROW();
virtual ~BOM_TABLE_ROW() {}
/// Set display properties for a cell
virtual bool GetAttr( unsigned int aFieldId, wxDataViewItemAttr& aAttr ) const;
/// Get the row value associated with provided field ID
virtual wxString GetFieldValue( unsigned int aFieldId ) const = 0;
/// Set the field value associated with the provided field ID
virtual bool SetFieldValue( unsigned int aFieldId, const wxString aValue, bool aOverwrite = false ) = 0;
/// Return parent item
virtual BOM_TABLE_ROW* GetParent() const { return nullptr; }
/// Test if row has any child rows
virtual bool HasChildren() const { return false; }
/// Return any child rows
virtual unsigned int GetChildren( wxDataViewItemArray& aChildren ) const { return 0; }
/// Determine if a value has changed
virtual bool HasValueChanged( BOM_COLUMN* aField ) const { return false; }
/// Determine if any values have changed
bool HasChanged() const;
protected:
/// Pointer to list of columns
BOM_COLUMN_LIST* m_columnList;
};
/**
* BOM_TABLE_GROUP class displays a group of similar components
* If the group contains more than one component,
* they are each displayed as child items of the group
*/
class BOM_TABLE_GROUP : public BOM_TABLE_ROW
{
public:
// List of components stored in this group
std::vector<BOM_TABLE_COMPONENT*> Components;
BOM_TABLE_GROUP( BOM_COLUMN_LIST* aColumnList );
virtual ~BOM_TABLE_GROUP() {}
// Set display properties for
virtual bool GetAttr( unsigned int aFieldId, wxDataViewItemAttr& aAttr ) const override;
// Get group row value
virtual wxString GetFieldValue( unsigned int aFieldId ) const override;
// Set group row value
virtual bool SetFieldValue( unsigned int aFieldId, const wxString aValue, bool aOverwrite = false ) override;
// Attempt to add a new component to the group
bool AddComponent( BOM_TABLE_COMPONENT* aComponent );
// Test if this group should display children
virtual bool HasChildren() const override { return Components.size() > 1; }
// Return a list of children items of this group
virtual unsigned int GetChildren( wxDataViewItemArray& aChildren ) const override;
// Test if any children have changed
virtual bool HasValueChanged( BOM_COLUMN* aField ) const override;
// Return the number of child items in this group
unsigned int GroupSize( void ) const { return Components.size(); }
// Return a sorted, concatenated list of references
wxArrayString GetReferences( bool aSort = true ) const;
// Function for sorting two reference strings
static int SortReferences( const wxString& aFirst, const wxString& aSecond );
// Function for sorting two value strings
static int SortValues( const wxString& aFirst, const wxString& aSecond );
protected:
// Test if a particular field matches against another component
bool TestField( BOM_COLUMN* aField, BOM_TABLE_COMPONENT* aComponent ) const;
};
class BOM_TABLE_COMPONENT : public BOM_TABLE_ROW
{
public:
// List of units associated with this component
std::vector<SCH_REFERENCE> Units;
BOM_TABLE_COMPONENT( BOM_TABLE_GROUP* aParent, BOM_COLUMN_LIST* aColumnList );
bool AddUnit( SCH_REFERENCE aUnit );
virtual wxString GetFieldValue( unsigned int aFieldId ) const override;
virtual bool SetFieldValue( unsigned int aFieldId, const wxString aValue, bool aOverwrite = false ) override;
virtual bool HasValueChanged( BOM_COLUMN* aField ) const override;
// Return the reference of the first unit (all units must be the same
wxString GetReference() const;
wxString GetPrefix() const;
void ApplyFieldChanges();
void RevertFieldChanges();
void SetParent( BOM_TABLE_GROUP* aParent ) { m_parent = aParent; }
virtual BOM_TABLE_ROW* GetParent() const override { return m_parent; }
protected:
// Initial data for reverting component values
std::map<unsigned int, wxString> m_fallbackData;
// Data as it is updated
std::map<unsigned int, wxString> m_fieldData;
BOM_TABLE_GROUP* m_parent;
};
/**
* BOM_TABLE_MODEL class
*
* Contains complete BOM information:
* a) List of columns (fields) to display
* b) List of groups of consolidated components
*/
class BOM_TABLE_MODEL : public wxDataViewModel
{
protected:
BOM_TABLE_MODEL();
std::vector<std::unique_ptr<BOM_TABLE_COMPONENT>> m_components;
// BOM Preferences
//! Group components based on values
bool m_groupColumns = true;
//! Filter components
bool m_filterColumns = false;
//! Allow blank fields to be merged with otherwise matching groups
bool m_mergeBlankFields = false;
wxDataViewCtrl* m_widget;
//! ID of column to sort by
unsigned int m_sortingColumn;
bool m_sortingOrder;
void AddDefaultColumns();
void ClearColumns();
virtual bool HasContainerColumns( const wxDataViewItem& aItem ) const override { return true; }
virtual bool IsContainer( const wxDataViewItem& aItem ) const override;
virtual wxDataViewItem GetParent( const wxDataViewItem& aItem ) const override;
virtual unsigned int GetChildren( const wxDataViewItem& aItem, wxDataViewItemArray& aChildren ) const override;
virtual unsigned int GetColumnCount() const override { return ColumnList.ColumnCount( false ); }
virtual wxString GetColumnType( unsigned int aFieldId ) const override { return wxString( "string" ); }
virtual void GetValue( wxVariant& aVariant, const wxDataViewItem& aItem, unsigned int aFieldId ) const override;
virtual bool SetValue( const wxVariant& aVariant, const wxDataViewItem& item, unsigned int aFieldId ) override;
public:
virtual ~BOM_TABLE_MODEL();
BOM_COLUMN_LIST ColumnList;
/// List of component groups
std::vector<std::unique_ptr<BOM_TABLE_GROUP>> Groups;
typedef wxObjectDataPtr<BOM_TABLE_MODEL> MODEL_PTR;
static MODEL_PTR Create();
void AttachTo( wxDataViewCtrl* aView );
wxDataViewColumn* AddColumn( BOM_COLUMN* aColumn, int aPosition = -1 );
bool RemoveColumn( BOM_COLUMN* aColumn );
// wxDataViewModel functions
virtual bool GetAttr( const wxDataViewItem& aItem, unsigned int aFieldId, wxDataViewItemAttr& aAttr ) const override;
virtual bool HasDefaultCompare() const override { return false; }
virtual int Compare( const wxDataViewItem& aItem1,
const wxDataViewItem& aItem2,
unsigned int aColumnId,
bool aAscending ) const override;
void ReloadTable();
unsigned int ColumnCount() const { return ColumnList.ColumnCount(); }
unsigned int GroupCount() const { return (unsigned int) Groups.size(); }
unsigned int ComponentCount() const;
void SetColumnGrouping( const bool aGroup = true ) { m_groupColumns = aGroup; }
bool GetColumnGrouping() const { return m_groupColumns; }
void SetColumnFiltering( const bool aFilter = true ) { m_filterColumns = aFilter; }
bool GetColumnFiltering() const { return m_filterColumns; }
void SetBlankMerging( const bool aMerge = true ) { m_mergeBlankFields = aMerge; }
bool GetBlankMerging() const { return m_mergeBlankFields; }
wxArrayString GetRowData( unsigned int aRow, std::vector<BOM_COLUMN*> aColumns ) const;
void SetComponents( SCH_REFERENCE_LIST aRefs );
void AddComponentFields( SCH_COMPONENT* aCmp );
void RevertFieldChanges();
void ApplyFieldChanges();
bool HaveFieldsChanged() const;
std::vector<SCH_COMPONENT*> GetChangedComponents();
unsigned int CountChangedComponents();
};
#endif // _EESCHEMA_BOM_TABLE_MODEL_H_

View File

@ -0,0 +1,439 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2017 Oliver Walters
* Copyright (C) 2017 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <wx/colour.h>
#include <wx/msgdlg.h>
#include <wx/progdlg.h>
#include <wx/file.h>
#include <wx/filename.h>
#include <confirm.h>
#include <build_version.h>
#include <general.h>
#include <class_library.h>
#include <bom_exporter.h>
#include "dialog_bom_editor.h"
#include <bom_table_model.h>
/* BOM Table Colours */
// Create and show BOM editor
int InvokeDialogCreateBOMEditor( SCH_EDIT_FRAME* aCaller )
{
DIALOG_BOM_EDITOR dlg( aCaller );
return dlg.ShowModal();
}
DIALOG_BOM_EDITOR::DIALOG_BOM_EDITOR( SCH_EDIT_FRAME* parent ) :
DIALOG_BOM_EDITOR_BASE( parent ),
m_parent( parent )
{
m_bom = BOM_TABLE_MODEL::Create();
m_columnListCtrl->DeleteAllItems();
m_columnListCtrl->ClearColumns();
auto nameColumn = m_columnListCtrl->AppendTextColumn( _( "Field" ) );
auto showColumn = m_columnListCtrl->AppendToggleColumn(
_( "Show" ),
wxDATAVIEW_CELL_ACTIVATABLE,
100 );
// Resize the columns appropriately
m_columnListCtrl->Update();
showColumn->SetWidth( wxCOL_WIDTH_AUTOSIZE );
showColumn->SetMinWidth( showColumn->GetWidth() );
showColumn->SetResizeable( false );
m_columnListCtrl->Update();
nameColumn->SetWidth( wxCOL_WIDTH_AUTOSIZE );
nameColumn->SetResizeable( true );
// Read all components
LoadComponents();
LoadColumnNames();
ReloadColumns();
m_bom->ReloadTable();
UpdateTitle();
}
DIALOG_BOM_EDITOR::~DIALOG_BOM_EDITOR()
{
//TODO
}
/**
* When the component table dialog is closed,
* work out if we need to save any changed.
* If so, capture those changes and push them to the undo stack.
*/
void DIALOG_BOM_EDITOR::OnBomEditorClosed( wxCloseEvent& event )
{
bool saveChanges = false;
// If there are changed values, warn the user first
if( m_bom->HaveFieldsChanged() )
{
int result = DisplayExitDialog( this, _( "Changes exist in component table" ) );
switch( result )
{
// Save and exit
case wxID_YES:
saveChanges = true;
break;
// Cancel (do not exit)
case wxID_CANCEL:
event.Veto();
return;
// Do not save, exit
default:
break;
}
}
if( saveChanges )
{
/** Create a list of picked items for undo
* PICKED_ITEMS_LIST contains multiple ITEM_PICKER instances
* Each ITEM_PICKER contains a component and a command
*/
auto pickerList = PICKED_ITEMS_LIST();
// List of components that have changed
auto changed = m_bom->GetChangedComponents();
ITEM_PICKER picker;
for( auto cmp : changed )
{
// Push the component into the picker list
picker = ITEM_PICKER( cmp, UR_CHANGED );
picker.SetFlags( cmp->GetFlags() );
//picker.SetLink( DuplicateStruct( cmp, true ) );
pickerList.PushItem( picker );
}
if( pickerList.GetCount() > 0 )
{
m_parent->SaveCopyInUndoList( pickerList, UR_CHANGED );
m_bom->ApplyFieldChanges();
m_parent->Refresh();
}
}
Destroy();
}
/**
* Update the window title to reflect the contents of the table
*/
void DIALOG_BOM_EDITOR::UpdateTitle()
{
wxString title = _( "Component table" ) + wxString( " - " );
title += wxString::Format( "%u %s",
m_bom->ComponentCount(),
_( "components" ) );
if( m_bom->GetColumnGrouping() )
{
title += wxString::Format( " %s %u %s",
_( "in" ),
m_bom->Groups.size(),
_( "groups" ) );
}
unsigned int count = m_bom->CountChangedComponents();
if( count > 0 )
{
title += wxString::Format( " - %u %s",
count,
_( "changed" ) );
}
SetTitle( title );
}
/**
* Load component data from the entire schematic set
*/
void DIALOG_BOM_EDITOR::LoadComponents()
{
if( !m_parent ) return;
// List of component objects
SCH_REFERENCE_LIST refs;
// Generate a list of schematic sheets
SCH_SHEET_LIST sheets( g_RootSheet );
sheets.GetComponents( m_parent->Prj().SchLibs(), refs, false );
// Pass the references through to the model
m_bom->SetComponents( refs );
}
/**
* Display list of columns (fields)
*/
void DIALOG_BOM_EDITOR::LoadColumnNames()
{
m_columnListCtrl->DeleteAllItems();
wxVector< wxVariant > data;
for( auto* col : m_bom->ColumnList.Columns )
{
if( nullptr == col )
continue;
data.clear();
data.push_back( wxVariant( col->Title() ) ); // Column title (string)
data.push_back( wxVariant( col->IsVisible() ) ); // Column visibility (bool)
m_columnListCtrl->AppendItem( data );
}
}
void DIALOG_BOM_EDITOR::ReloadColumns()
{
m_bom->AttachTo( m_bomView );
UpdateTitle();
}
void DIALOG_BOM_EDITOR::OnColumnItemToggled( wxDataViewEvent& event )
{
wxDataViewItem item = event.GetItem();
int row = m_columnListCtrl->ItemToRow( item );
int col = event.GetColumn();
if( row == wxNOT_FOUND || row < 0 || row >= (int) m_bom->ColumnCount() ) return;
BOM_COLUMN* bomColumn = m_bom->ColumnList.GetColumnByIndex( row );
if( nullptr == bomColumn ) return;
bool bValue = m_columnListCtrl->GetToggleValue( row, col );
switch ( col )
{
default:
break;
case 1: // Column visibility
bomColumn->SetVisible( bValue );
// Insert a new column
if( bValue )
{
m_bom->AddColumn( bomColumn );
}
else
{
m_bom->RemoveColumn( bomColumn );
}
break;
}
}
/**
* Called when the "Group Components" toggle is pressed
*/
void DIALOG_BOM_EDITOR::OnGroupComponentsToggled( wxCommandEvent& event )
{
bool group = m_groupComponentsBox->GetValue();
m_bom->SetColumnGrouping( group );
m_bom->ReloadTable();
m_regroupComponentsButton->Enable( group );
UpdateTitle();
}
/**
* Called when the "Export BOM" button is pressed
* Extract row data from the component table,
* and export it to a BOM file
*/
void DIALOG_BOM_EDITOR::OnExportBOM( wxCommandEvent& event )
{
// Allowable BOM file formats
static const wxString wildcard = _( "BOM Files" ) + wxString( " *.csv, *.tsv, *.html)|*.csv;*.tsv;*.htm;*.html" );
wxFileDialog bomFileDialog(this, _("Select BOM file"),
Prj().GetProjectPath(),
wxEmptyString,
wildcard,
wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
if( bomFileDialog.ShowModal() == wxID_CANCEL )
{
return;
}
// Ensure the component groups are correct
m_bom->ReloadTable();
wxString msg;
wxFileName filename = bomFileDialog.GetPath();
// Ensure correct file format
BOM_FILE_WRITER* writer;
wxString fn = filename.GetFullPath().Lower();
// CSV File
if( fn.EndsWith( ".csv" ) )
{
writer = new BOM_CSV_WRITER();
}
// TSV file
else if( fn.EndsWith( ".tsv" ) )
{
writer = new BOM_CSV_WRITER( '\t' );
}
// HTML file
else if( fn.EndsWith( ".html" ) || fn.EndsWith( ".htm" ) )
{
writer = new BOM_HTML_WRITER();
}
// Unknown file!
else
{
msg.Printf("%s:\n%s",
_( "Unsupported file type" ),
filename.GetExt() );
wxMessageBox( msg );
return;
}
// Set export preferences
writer->IncludeExtraData( m_includeProjectData->GetValue() );
writer->ShowRowNumbers( m_showRowNumbers->GetValue() );
// Project information
writer->SetKicadVersion( GetBuildVersion() );
// Extract sheet info from top-level sheet
if( g_RootSheet )
{
const TITLE_BLOCK& tb = g_RootSheet->GetScreen()->GetTitleBlock();
writer->SetSchematicDate( tb.GetDate() );
writer->SetSchematicVersion( tb.GetRevision() );
writer->SetSchematicTitle( tb.GetTitle() );
}
std::vector<BOM_COLUMN*> columns;
wxArrayString headings;
// Extract the visible column data
for( auto column : m_bom->ColumnList.Columns )
{
if( column && column->IsVisible() )
{
columns.push_back( column );
headings.push_back( column->Title() );
}
}
writer->SetHeader( headings );
// Extract the row data
for( unsigned int row=0; row<m_bom->GroupCount(); row++ )
{
writer->AddLine( m_bom->GetRowData( row, columns ) );
}
writer->SetGroupCount( m_bom->GroupCount() );
writer->SetComponentCount( m_bom->ComponentCount() );
// Open the BOM file for writing
wxFile bomFile( filename.GetFullPath(), wxFile::write );
if( bomFile.IsOpened() )
{
if( !writer->WriteToFile( bomFile ) )
{
msg.Printf( "%s:\n%s",
_( "Error writing BOM file" ),
filename.GetFullPath() );
}
bomFile.Close();
}
else
{
msg.Printf( "%s:\n%s",
_( "Error opening BOM file" ),
filename.GetFullPath() );
wxMessageBox( msg );
}
}
void DIALOG_BOM_EDITOR::OnTableValueChanged( wxDataViewEvent& event )
{
m_reloadTableButton->Enable( m_bom->HaveFieldsChanged() );
UpdateTitle();
}
void DIALOG_BOM_EDITOR::OnRegroupComponents( wxCommandEvent& event )
{
m_bom->ReloadTable();
}
void DIALOG_BOM_EDITOR::OnRevertFieldChanges( wxCommandEvent& event )
{
if( m_bom->HaveFieldsChanged() )
{
if( IsOK( this, _( "Revert all component table changes?" ) ) )
{
m_bom->RevertFieldChanges();
m_reloadTableButton->Enable( m_bom->HaveFieldsChanged() );
UpdateTitle();
}
}
}

View File

@ -0,0 +1,83 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2017 Oliver Walters
* Copyright (C) 2017 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/**
* @file eeschema/dialogs/dialog_bom.cpp
* @brief Dialog box for creating bom and other documents from generic netlist.
*/
#ifndef EESCHEMA_DIALOGS_DIALOG_BOM_EDITOR_H_
#define EESCHEMA_DIALOGS_DIALOG_BOM_EDITOR_H_
#include <wx/dataview.h>
#include <schframe.h>
#include <sch_sheet.h>
#include <sch_sheet_path.h>
#include <sch_component.h>
#include <invoke_sch_dialog.h>
#include <dialog_bom_editor_base.h>
#include <class_netlist_object.h>
#include <sch_reference_list.h>
#include <vector>
#include <bom_table_model.h>
class DIALOG_BOM_EDITOR : public DIALOG_BOM_EDITOR_BASE
{
public:
DIALOG_BOM_EDITOR( SCH_EDIT_FRAME* parent );
virtual ~DIALOG_BOM_EDITOR();
private:
//! Parent object (Schematic)
SCH_EDIT_FRAME* m_parent;
BOM_TABLE_MODEL::MODEL_PTR m_bom;
void LoadComponents( void );
void LoadColumnNames( void );
void ReloadColumns( void );
// Checkbox event callbacks
virtual void OnColumnItemToggled( wxDataViewEvent& event ) override;
virtual void OnGroupComponentsToggled( wxCommandEvent& event ) override;
virtual void OnExportBOM( wxCommandEvent& event ) override;
virtual void OnRevertFieldChanges( wxCommandEvent& event ) override;
virtual void OnRegroupComponents( wxCommandEvent& event ) override;
// Called after a value in the table has changed
virtual void OnTableValueChanged( wxDataViewEvent& event ) override;
virtual void OnBomEditorClosed( wxCloseEvent& event ) override;
void UpdateTitle( void );
};
#endif /* EESCHEMA_DIALOGS_DIALOG_BOM_EDITOR_H_ */

View File

@ -0,0 +1,150 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Apr 1 2017)
// http://www.wxformbuilder.org/
//
// PLEASE DO "NOT" EDIT THIS FILE!
///////////////////////////////////////////////////////////////////////////
#include "dialog_bom_editor_base.h"
///////////////////////////////////////////////////////////////////////////
BEGIN_EVENT_TABLE( DIALOG_BOM_EDITOR_BASE, DIALOG_SHIM )
EVT_CLOSE( DIALOG_BOM_EDITOR_BASE::_wxFB_OnBomEditorClosed )
EVT_CHECKBOX( OPT_GROUP_COMPONENTS, DIALOG_BOM_EDITOR_BASE::_wxFB_OnGroupComponentsToggled )
EVT_BUTTON( ID_BUTTON_REGROUP, DIALOG_BOM_EDITOR_BASE::_wxFB_OnRegroupComponents )
EVT_BUTTON( ID_BUTTON_REVERT_CHANGES, DIALOG_BOM_EDITOR_BASE::_wxFB_OnRevertFieldChanges )
EVT_DATAVIEW_ITEM_VALUE_CHANGED( wxID_ANY, DIALOG_BOM_EDITOR_BASE::_wxFB_OnColumnItemToggled )
EVT_BUTTON( wxID_BOM_BUTTON_EXPORT, DIALOG_BOM_EDITOR_BASE::_wxFB_OnExportBOM )
EVT_DATAVIEW_COLUMN_REORDERED( wxID_ANY, DIALOG_BOM_EDITOR_BASE::_wxFB_OnBomColumReordered )
EVT_DATAVIEW_COLUMN_SORTED( wxID_ANY, DIALOG_BOM_EDITOR_BASE::_wxFB_OnBomColumnSorted )
EVT_DATAVIEW_ITEM_EDITING_DONE( wxID_ANY, DIALOG_BOM_EDITOR_BASE::_wxFB_OnTableValueChanged )
EVT_DATAVIEW_SELECTION_CHANGED( wxID_ANY, DIALOG_BOM_EDITOR_BASE::_wxFB_OnSelectionChanged )
END_EVENT_TABLE()
DIALOG_BOM_EDITOR_BASE::DIALOG_BOM_EDITOR_BASE( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : DIALOG_SHIM( parent, id, title, pos, size, style )
{
this->SetSizeHints( wxDefaultSize, wxDefaultSize );
wxBoxSizer* bHorizontalSizer;
bHorizontalSizer = new wxBoxSizer( wxVERTICAL );
m_panel = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
wxBoxSizer* bSizer7;
bSizer7 = new wxBoxSizer( wxVERTICAL );
m_splitter1 = new wxSplitterWindow( m_panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_3D );
m_splitter1->Connect( wxEVT_IDLE, wxIdleEventHandler( DIALOG_BOM_EDITOR_BASE::m_splitter1OnIdle ), NULL, this );
m_leftPanel = new wxPanel( m_splitter1, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
wxBoxSizer* bSizer6;
bSizer6 = new wxBoxSizer( wxVERTICAL );
wxStaticBoxSizer* sbSizer1;
sbSizer1 = new wxStaticBoxSizer( new wxStaticBox( m_leftPanel, wxID_ANY, _("Options") ), wxVERTICAL );
m_groupComponentsBox = new wxCheckBox( sbSizer1->GetStaticBox(), OPT_GROUP_COMPONENTS, _("Group components"), wxDefaultPosition, wxDefaultSize, 0 );
m_groupComponentsBox->SetValue(true);
m_groupComponentsBox->SetToolTip( _("Group components together based on common properties") );
sbSizer1->Add( m_groupComponentsBox, 0, wxALL|wxEXPAND, 5 );
m_regroupComponentsButton = new wxButton( sbSizer1->GetStaticBox(), ID_BUTTON_REGROUP, _("Regroup components"), wxDefaultPosition, wxDefaultSize, 0 );
sbSizer1->Add( m_regroupComponentsButton, 0, wxALL|wxEXPAND, 5 );
m_reloadTableButton = new wxButton( sbSizer1->GetStaticBox(), ID_BUTTON_REVERT_CHANGES, _("Revert all changes"), wxDefaultPosition, wxDefaultSize, 0 );
m_reloadTableButton->Enable( false );
m_reloadTableButton->SetToolTip( _("Reload table (reverts component field changes)") );
sbSizer1->Add( m_reloadTableButton, 0, wxALL|wxEXPAND, 5 );
bSizer6->Add( sbSizer1, 0, wxEXPAND, 5 );
wxBoxSizer* bSizer9;
bSizer9 = new wxBoxSizer( wxVERTICAL );
wxStaticBoxSizer* m_fieldListSizer;
m_fieldListSizer = new wxStaticBoxSizer( new wxStaticBox( m_leftPanel, wxID_ANY, _("Fields") ), wxVERTICAL );
m_columnListCtrl = new wxDataViewListCtrl( m_fieldListSizer->GetStaticBox(), wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
m_fieldListSizer->Add( m_columnListCtrl, 1, wxALL|wxEXPAND, 5 );
bSizer9->Add( m_fieldListSizer, 1, wxEXPAND, 5 );
bSizer6->Add( bSizer9, 5, wxEXPAND, 5 );
bSizer6->Add( 0, 0, 0, wxEXPAND, 5 );
wxStaticBoxSizer* sbSizer2;
sbSizer2 = new wxStaticBoxSizer( new wxStaticBox( m_leftPanel, wxID_ANY, _("Export options") ), wxVERTICAL );
m_includeProjectData = new wxCheckBox( sbSizer2->GetStaticBox(), wxID_BOM_OPT_INC_PRJ_DATA, _("Include project data"), wxDefaultPosition, wxDefaultSize, 0 );
m_includeProjectData->SetValue(true);
m_includeProjectData->SetToolTip( _("Include project information in BOM file") );
sbSizer2->Add( m_includeProjectData, 0, wxALL|wxEXPAND, 5 );
m_showRowNumbers = new wxCheckBox( sbSizer2->GetStaticBox(), wxID_BOM_OPT_SHOW_ROW_NUMS, _("Show row numbers"), wxDefaultPosition, wxDefaultSize, 0 );
m_showRowNumbers->SetValue(true);
m_showRowNumbers->SetToolTip( _("Show BOM row numbers ") );
sbSizer2->Add( m_showRowNumbers, 0, wxALL|wxEXPAND, 5 );
sbSizer2->Add( 0, 0, 1, wxEXPAND, 5 );
wxBoxSizer* bSizer13;
bSizer13 = new wxBoxSizer( wxHORIZONTAL );
bSizer13->Add( 0, 0, 1, wxEXPAND, 5 );
m_exportButton = new wxButton( sbSizer2->GetStaticBox(), wxID_BOM_BUTTON_EXPORT, _("Export BOM"), wxDefaultPosition, wxDefaultSize, 0 );
bSizer13->Add( m_exportButton, 0, wxALL, 5 );
sbSizer2->Add( bSizer13, 0, wxEXPAND, 5 );
bSizer6->Add( sbSizer2, 0, wxEXPAND, 5 );
m_leftPanel->SetSizer( bSizer6 );
m_leftPanel->Layout();
bSizer6->Fit( m_leftPanel );
m_panel4 = new wxPanel( m_splitter1, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
wxBoxSizer* bSizer5;
bSizer5 = new wxBoxSizer( wxVERTICAL );
m_bomView = new wxDataViewCtrl( m_panel4, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxDV_MULTIPLE|wxDV_ROW_LINES|wxDV_VERT_RULES );
m_bomView->SetMinSize( wxSize( 250,250 ) );
bSizer5->Add( m_bomView, 1, wxALL|wxEXPAND, 5 );
m_panel4->SetSizer( bSizer5 );
m_panel4->Layout();
bSizer5->Fit( m_panel4 );
m_splitter1->SplitVertically( m_leftPanel, m_panel4, 231 );
bSizer7->Add( m_splitter1, 1, wxEXPAND, 5 );
m_panel->SetSizer( bSizer7 );
m_panel->Layout();
bSizer7->Fit( m_panel );
bHorizontalSizer->Add( m_panel, 1, wxEXPAND | wxALL, 5 );
this->SetSizer( bHorizontalSizer );
this->Layout();
this->Centre( wxBOTH );
}
DIALOG_BOM_EDITOR_BASE::~DIALOG_BOM_EDITOR_BASE()
{
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,101 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Apr 1 2017)
// http://www.wxformbuilder.org/
//
// PLEASE DO "NOT" EDIT THIS FILE!
///////////////////////////////////////////////////////////////////////////
#ifndef __DIALOG_BOM_EDITOR_BASE_H__
#define __DIALOG_BOM_EDITOR_BASE_H__
#include <wx/artprov.h>
#include <wx/xrc/xmlres.h>
#include <wx/intl.h>
class DIALOG_SHIM;
#include "dialog_shim.h"
#include <wx/string.h>
#include <wx/checkbox.h>
#include <wx/gdicmn.h>
#include <wx/font.h>
#include <wx/colour.h>
#include <wx/settings.h>
#include <wx/button.h>
#include <wx/sizer.h>
#include <wx/statbox.h>
#include <wx/dataview.h>
#include <wx/panel.h>
#include <wx/splitter.h>
#include <wx/dialog.h>
///////////////////////////////////////////////////////////////////////////
#define OPT_GROUP_COMPONENTS 1000
#define ID_BUTTON_REGROUP 1001
#define ID_BUTTON_REVERT_CHANGES 1002
#define wxID_BOM_OPT_INC_PRJ_DATA 1003
#define wxID_BOM_OPT_SHOW_ROW_NUMS 1004
#define wxID_BOM_BUTTON_EXPORT 1005
///////////////////////////////////////////////////////////////////////////////
/// Class DIALOG_BOM_EDITOR_BASE
///////////////////////////////////////////////////////////////////////////////
class DIALOG_BOM_EDITOR_BASE : public DIALOG_SHIM
{
DECLARE_EVENT_TABLE()
private:
// Private event handlers
void _wxFB_OnBomEditorClosed( wxCloseEvent& event ){ OnBomEditorClosed( event ); }
void _wxFB_OnGroupComponentsToggled( wxCommandEvent& event ){ OnGroupComponentsToggled( event ); }
void _wxFB_OnRegroupComponents( wxCommandEvent& event ){ OnRegroupComponents( event ); }
void _wxFB_OnRevertFieldChanges( wxCommandEvent& event ){ OnRevertFieldChanges( event ); }
void _wxFB_OnColumnItemToggled( wxDataViewEvent& event ){ OnColumnItemToggled( event ); }
void _wxFB_OnExportBOM( wxCommandEvent& event ){ OnExportBOM( event ); }
void _wxFB_OnBomColumReordered( wxDataViewEvent& event ){ OnBomColumReordered( event ); }
void _wxFB_OnBomColumnSorted( wxDataViewEvent& event ){ OnBomColumnSorted( event ); }
void _wxFB_OnTableValueChanged( wxDataViewEvent& event ){ OnTableValueChanged( event ); }
void _wxFB_OnSelectionChanged( wxDataViewEvent& event ){ OnSelectionChanged( event ); }
protected:
wxPanel* m_panel;
wxSplitterWindow* m_splitter1;
wxPanel* m_leftPanel;
wxCheckBox* m_groupComponentsBox;
wxButton* m_regroupComponentsButton;
wxButton* m_reloadTableButton;
wxDataViewListCtrl* m_columnListCtrl;
wxCheckBox* m_includeProjectData;
wxCheckBox* m_showRowNumbers;
wxButton* m_exportButton;
wxPanel* m_panel4;
wxDataViewCtrl* m_bomView;
// Virtual event handlers, overide them in your derived class
virtual void OnBomEditorClosed( wxCloseEvent& event ) { event.Skip(); }
virtual void OnGroupComponentsToggled( wxCommandEvent& event ) { event.Skip(); }
virtual void OnRegroupComponents( wxCommandEvent& event ) { event.Skip(); }
virtual void OnRevertFieldChanges( wxCommandEvent& event ) { event.Skip(); }
virtual void OnColumnItemToggled( wxDataViewEvent& event ) { event.Skip(); }
virtual void OnExportBOM( wxCommandEvent& event ) { event.Skip(); }
virtual void OnBomColumReordered( wxDataViewEvent& event ) { event.Skip(); }
virtual void OnBomColumnSorted( wxDataViewEvent& event ) { event.Skip(); }
virtual void OnTableValueChanged( wxDataViewEvent& event ) { event.Skip(); }
virtual void OnSelectionChanged( wxDataViewEvent& event ) { event.Skip(); }
public:
DIALOG_BOM_EDITOR_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("BOM editor"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 1047,649 ), long style = wxDEFAULT_DIALOG_STYLE|wxMAXIMIZE_BOX|wxRESIZE_BORDER );
~DIALOG_BOM_EDITOR_BASE();
void m_splitter1OnIdle( wxIdleEvent& )
{
m_splitter1->SetSashPosition( 231 );
m_splitter1->Disconnect( wxEVT_IDLE, wxIdleEventHandler( DIALOG_BOM_EDITOR_BASE::m_splitter1OnIdle ), NULL, this );
}
};
#endif //__DIALOG_BOM_EDITOR_BASE_H__

View File

@ -80,6 +80,9 @@ int InvokeDialogPrintUsingPrinter( SCH_EDIT_FRAME* aCaller );
/// DIALOG_BOM::ShowModal() returns.
int InvokeDialogCreateBOM( SCH_EDIT_FRAME* aCaller );
/// Create and show DIALOG_BOM_EDITOR
int InvokeDialogCreateBOMEditor( SCH_EDIT_FRAME* aCaller );
/**
* Function InvokeDialogNetList
* creates and shows NETLIST_DIALOG and returns whatever

View File

@ -502,12 +502,19 @@ void prepareToolsMenu( wxMenu* aParentMenu )
_( "Generate the component netlist file" ),
KiBitmap( netlist_xpm ) );
AddMenuItem( aParentMenu,
ID_OPEN_CMP_TABLE,
_( "Component Table &View" ),
KiBitmap( spreadsheet_xpm ) );
AddMenuItem( aParentMenu,
ID_GET_TOOLS,
_( "Generate Bill of &Materials..." ),
HELP_GENERATE_BOM,
KiBitmap( bom_xpm ) );
aParentMenu->AppendSeparator();
// Run CvPcb

View File

@ -293,6 +293,43 @@ void SCH_COMPONENT::SetLibId( const LIB_ID& aLibId, SYMBOL_LIB_TABLE* aSymLibTab
}
}
/**
* Function GetAliasDescription
* Return the description text for the given part alias
*/
wxString SCH_COMPONENT::GetAliasDescription() const
{
if( PART_SPTR part = m_part.lock() )
{
LIB_ALIAS* alias = part->GetAlias( GetLibId().GetLibItemName() );
if( !alias )
return wxEmptyString;
return alias->GetDescription();
}
return wxEmptyString;
}
/**
* Function GetAliasDocumentation
* Return the documentation text for the given part alias
*/
wxString SCH_COMPONENT::GetAliasDocumentation() const
{
if( PART_SPTR part = m_part.lock() )
{
LIB_ALIAS* alias = part->GetAlias( GetLibId().GetLibItemName() );
if( !alias )
return wxEmptyString;
return alias->GetDocFileName();
}
return wxEmptyString;
}
bool SCH_COMPONENT::Resolve( PART_LIBS* aLibs )
{
@ -732,6 +769,37 @@ SCH_FIELD* SCH_COMPONENT::GetField( int aFieldNdx ) const
return (SCH_FIELD*) field;
}
wxString SCH_COMPONENT::GetFieldText( wxString aFieldName ) const
{
// Field name for comparison
wxString cmpFieldName;
// Default field names
for ( unsigned int i=0; i<MANDATORY_FIELDS; i++)
{
cmpFieldName = TEMPLATE_FIELDNAME::GetDefaultFieldName( i );
if( cmpFieldName.Cmp( aFieldName ) == 0 )
{
return m_Fields[i].GetText();
}
}
// Search custom fields
for( unsigned int ii=MANDATORY_FIELDS; ii<m_Fields.size(); ii++ )
{
cmpFieldName = m_Fields[ii].GetName();
if( cmpFieldName.Cmp( aFieldName ) == 0 )
{
return m_Fields[ii].GetText();
}
}
return wxEmptyString;
}
void SCH_COMPONENT::GetFields( std::vector<SCH_FIELD*>& aVector, bool aVisibleOnly )
{

View File

@ -169,6 +169,12 @@ public:
PART_REF& GetPartRef() { return m_part; }
/**
* Return information about the aliased parts
*/
wxString GetAliasDescription() const;
wxString GetAliasDocumentation() const;
/**
* Function Resolve
* [re-]assigns the current LIB_PART from aLibs which this component
@ -292,6 +298,12 @@ public:
*/
SCH_FIELD* GetField( int aFieldNdx ) const;
/**
* Returns text associated with a given field (if such a field exists)
* @aFieldName is the name of the field
*/
wxString GetFieldText( wxString aFieldName ) const;
/**
* Function GetFields
* populates a std::vector with SCH_FIELDs.

View File

@ -267,6 +267,7 @@ BEGIN_EVENT_TABLE( SCH_EDIT_FRAME, EDA_DRAW_FRAME )
EVT_TOOL( ID_GET_NETLIST, SCH_EDIT_FRAME::OnCreateNetlist )
EVT_TOOL( ID_UPDATE_PCB_FROM_SCH, SCH_EDIT_FRAME::OnUpdatePCB )
EVT_TOOL( ID_GET_TOOLS, SCH_EDIT_FRAME::OnCreateBillOfMaterials )
EVT_TOOL( ID_OPEN_CMP_TABLE, SCH_EDIT_FRAME::OnLaunchBomManager )
EVT_TOOL( ID_FIND_ITEMS, SCH_EDIT_FRAME::OnFindItems )
EVT_TOOL( wxID_REPLACE, SCH_EDIT_FRAME::OnFindItems )
EVT_TOOL( ID_BACKANNO_ITEMS, SCH_EDIT_FRAME::OnLoadCmpToFootprintLinkFile )
@ -764,6 +765,8 @@ void SCH_EDIT_FRAME::OnModify()
GetScreen()->SetSave();
m_foundItems.SetForceSearch();
m_canvas->Refresh();
}
@ -912,6 +915,14 @@ void SCH_EDIT_FRAME::OnCreateBillOfMaterials( wxCommandEvent& )
InvokeDialogCreateBOM( this );
}
void SCH_EDIT_FRAME::OnLaunchBomManager( wxCommandEvent& event )
{
// First ensure that entire schematic is annotated
if( !prepareForNetlist() )
return;
InvokeDialogCreateBOMEditor( this );
}
void SCH_EDIT_FRAME::OnFindItems( wxCommandEvent& aEvent )
{

View File

@ -833,6 +833,7 @@ private:
void OnUpdatePCB( wxCommandEvent& event );
void OnSimulate( wxCommandEvent& event );
void OnCreateBillOfMaterials( wxCommandEvent& event );
void OnLaunchBomManager( wxCommandEvent& event );
void OnFindItems( wxCommandEvent& event );
void OnFindDialogClose( wxFindDialogEvent& event );
void OnFindDrcMarker( wxFindDialogEvent& event );

View File

@ -160,10 +160,13 @@ void SCH_EDIT_FRAME::ReCreateHToolbar()
m_mainToolBar->AddTool( ID_GET_NETLIST, wxEmptyString, KiBitmap( netlist_xpm ),
_( "Generate netlist" ) );
m_mainToolBar->AddTool( ID_OPEN_CMP_TABLE, wxEmptyString, KiBitmap( spreadsheet_xpm ),
_( "Component table view" ) );
m_mainToolBar->AddTool( ID_GET_TOOLS, wxEmptyString, KiBitmap( bom_xpm ),
HELP_GENERATE_BOM );
m_mainToolBar->AddSeparator();
m_mainToolBar->AddTool( ID_RUN_PCB, wxEmptyString, KiBitmap( pcbnew_xpm ),

View File

@ -493,6 +493,7 @@ EXTERN_BITMAP( showtrack_xpm )
EXTERN_BITMAP( show_zone_xpm )
EXTERN_BITMAP( show_zone_disable_xpm )
EXTERN_BITMAP( show_zone_outline_only_xpm )
EXTERN_BITMAP( spreadsheet_xpm )
EXTERN_BITMAP( svg_file_xpm )
EXTERN_BITMAP( swap_layer_xpm )
EXTERN_BITMAP( text_sketch_xpm )

View File

@ -249,6 +249,7 @@ enum main_id
ID_PAN_RIGHT,
ID_GET_NETLIST,
ID_OPEN_CMP_TABLE,
ID_GET_TOOLS,
ID_FIND_ITEMS,

View File

@ -83,6 +83,7 @@ extern const wxString BoardFileWildcard;
extern const wxString NetlistFileWildcard;
extern const wxString GerberFileWildcard;
extern const wxString HtmlFileWildcard;
extern const wxString CsvFileWildcard;
extern const wxString LegacyPcbFileWildcard;
extern const wxString PcbFileWildcard;
extern const wxString EaglePcbFileWildcard;