Patched Gerber parsing to support some non-compliant instructions.

This commit is contained in:
Juan Pablo Caram
2014-02-19 00:21:29 -05:00
parent 7979757d60
commit b6497b2edb
11 changed files with 360 additions and 88 deletions

View File

@@ -1,7 +1,9 @@
############################################################ ############################################################
# Author: Juan Pablo Caram # # FlatCAM: 2D Post-processing for Manufacturing #
# http://caram.cl/software/flatcam #
# Author: Juan Pablo Caram (c) #
# Date: 2/5/2014 # # Date: 2/5/2014 #
# caram.cl # # MIT Licence #
############################################################ ############################################################
import threading import threading
@@ -553,7 +555,7 @@ class App:
self.builder = Gtk.Builder() self.builder = Gtk.Builder()
self.builder.add_from_file(self.gladefile) self.builder.add_from_file(self.gladefile)
self.window = self.builder.get_object("window1") self.window = self.builder.get_object("window1")
self.window.set_title("FlatCAM") self.window.set_title("FlatCAM - Alpha 1 UNSTABLE - Check for updates!")
self.position_label = self.builder.get_object("label3") self.position_label = self.builder.get_object("label3")
self.grid = self.builder.get_object("grid1") self.grid = self.builder.get_object("grid1")
self.notebook = self.builder.get_object("notebook1") self.notebook = self.builder.get_object("notebook1")
@@ -969,9 +971,9 @@ class App:
def set_progress_bar(self, percentage, text=""): def set_progress_bar(self, percentage, text=""):
""" """
Sets the application's progress bar to a given fraction and text. Sets the application's progress bar to a given frac_digits and text.
:param percentage: The fraction (0.0-1.0) of the progress. :param percentage: The frac_digits (0.0-1.0) of the progress.
:type percentage: float :type percentage: float
:param text: Text to display on the progress bar. :param text: Text to display on the progress bar.
:type text: str :type text: str
@@ -1260,6 +1262,18 @@ class App:
######################################## ########################################
## EVENT HANDLERS ## ## EVENT HANDLERS ##
######################################## ########################################
def on_about(self, widget):
"""
Opens the 'About' dialog box.
:param widget: Ignored.
:return: None
"""
about = self.builder.get_object("aboutdialog")
response = about.run()
about.destroy()
def on_create_mirror(self, widget): def on_create_mirror(self, widget):
""" """
Creates a mirror image of a Gerber object to be used as a bottom Creates a mirror image of a Gerber object to be used as a bottom

View File

@@ -1,6 +1,61 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<interface> <interface>
<!-- interface-requires gtk+ 3.0 --> <!-- interface-requires gtk+ 3.0 -->
<object class="GtkAboutDialog" id="aboutdialog">
<property name="can_focus">False</property>
<property name="border_width">5</property>
<property name="type_hint">dialog</property>
<property name="program_name">FlatCAM</property>
<property name="version">Version Alpha 1 (2014/02) - UNSTABLE</property>
<property name="copyright" translatable="yes">(c) 2014 Juan Pablo Caram</property>
<property name="comments" translatable="yes">2D Post-processing for Manufacturing specialized in
Printed Circuit Boards</property>
<property name="website">http://caram.cl/software/flatcam/</property>
<property name="website_label" translatable="yes">Caram.cl/software/flatcam</property>
<property name="license" translatable="yes">The MIT License (MIT)
Copyright (c) 2014 Juan Pablo Caram
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.</property>
<child internal-child="vbox">
<object class="GtkBox" id="aboutdialog-vbox1">
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">2</property>
<child internal-child="action_area">
<object class="GtkButtonBox" id="aboutdialog-action_area1">
<property name="can_focus">False</property>
<property name="layout_style">end</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack_type">end</property>
<property name="position">0</property>
</packing>
</child>
<child>
<placeholder/>
</child>
</object>
</child>
</object>
<object class="GtkImage" id="image1"> <object class="GtkImage" id="image1">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
@@ -2673,6 +2728,7 @@ to application defaults.</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="use_underline">True</property> <property name="use_underline">True</property>
<property name="use_stock">True</property> <property name="use_stock">True</property>
<signal name="activate" handler="on_about" swapped="no"/>
</object> </object>
</child> </child>
</object> </object>

336
camlib.py
View File

@@ -1,7 +1,9 @@
############################################################ ############################################################
# Author: Juan Pablo Caram # # FlatCAM: 2D Post-processing for Manufacturing #
# http://caram.cl/software/flatcam #
# Author: Juan Pablo Caram (c) #
# Date: 2/5/2014 # # Date: 2/5/2014 #
# caram.cl # # MIT Licence #
############################################################ ############################################################
from numpy import arctan2, Inf, array, sqrt, pi, ceil, sin, cos from numpy import arctan2, Inf, array, sqrt, pi, ceil, sin, cos
@@ -25,6 +27,7 @@ import simplejson as json
# TODO: Commented for FlatCAM packaging with cx_freeze # TODO: Commented for FlatCAM packaging with cx_freeze
#from matplotlib.pyplot import plot #from matplotlib.pyplot import plot
class Geometry: class Geometry:
def __init__(self): def __init__(self):
# Units (in or mm) # Units (in or mm)
@@ -232,10 +235,10 @@ class Gerber (Geometry):
Geometry.__init__(self) Geometry.__init__(self)
# Number format # Number format
self.digits = 3 self.int_digits = 3
"""Number of integer digits in Gerber numbers. Used during parsing.""" """Number of integer digits in Gerber numbers. Used during parsing."""
self.fraction = 4 self.frac_digits = 4
"""Number of fraction digits in Gerber numbers. Used during parsing.""" """Number of fraction digits in Gerber numbers. Used during parsing."""
## Gerber elements ## ## Gerber elements ##
@@ -264,10 +267,72 @@ class Gerber (Geometry):
# Attributes to be included in serialization # Attributes to be included in serialization
# Always append to it because it carries contents # Always append to it because it carries contents
# from Geometry. # from Geometry.
self.ser_attrs += ['digits', 'fraction', 'apertures', 'paths', self.ser_attrs += ['int_digits', 'frac_digits', 'apertures', 'paths',
'buffered_paths', 'regions', 'flashes', 'buffered_paths', 'regions', 'flashes',
'flash_geometry'] 'flash_geometry']
#### Parser patterns ####
# FS - Format Specification
# The format of X and Y must be the same!
# L-omit leading zeros, T-omit trailing zeros
# A-absolute notation, I-incremental notation
self.fmt_re = re.compile(r'%FS([LT])([AI])X(\d)(\d)Y\d\d\*%$')
# Mode (IN/MM)
self.mode_re = re.compile(r'^%MO(IN|MM)\*%$')
# Comment G04|G4
self.comm_re = re.compile(r'^G0?4(.*)$')
# AD - Aperture definition
self.ad_re = re.compile(r'^%ADD(\d\d+)([a-zA-Z0-9]*),(.*)\*%$')
# AM - Aperture Macro
# Beginning of macro (Ends with *%):
self.am_re = re.compile(r'^%AM([a-zA-Z0-9]*)\*')
# Tool change
# May begin with G54 but that is deprecated
self.tool_re = re.compile(r'^(?:G54)?D(\d\d+)\*$')
# G01 - Linear interpolation plus flashes
# Operation code (D0x) missing is deprecated... oh well I will support it.
self.lin_re = re.compile(r'^(?:G0?(1))?(?:X(-?\d+))?(?:Y(-?\d+))?(?:D0([123]))?\*$')
self.setlin_re = re.compile(r'^(?:G0?1)\*')
# G02/3 - Circular interpolation
# 2-clockwise, 3-counterclockwise
self.circ_re = re.compile(r'^(?:G0?([23]))?(?:X(-?\d+))?(?:Y(-?\d+))' +
'?(?:I(-?\d+))?(?:J(-?\d+))?D0([12])\*$')
# G01/2/3 Occurring without coordinates
self.interp_re = re.compile(r'^(?:G0?([123]))\*')
# Single D74 or multi D75 quadrant for circular interpolation
self.quad_re = re.compile(r'^G7([45])\*$')
# Region mode on
# In region mode, D01 starts a region
# and D02 ends it. A new region can be started again
# with D01. All contours must be closed before
# D02 or G37.
self.regionon_re = re.compile(r'^G36\*$')
# Region mode off
# Will end a region and come off region mode.
# All contours must be closed before D02 or G37.
self.regionoff_re = re.compile(r'^G37\*$')
# End of file
self.eof_re = re.compile(r'^M02\*')
# IP - Image polarity
self.pol_re = re.compile(r'^%IP(POS|NEG)\*%$')
# LP - Level polarity
self.lpol_re = re.compile(r'^%LP([DC])\*%$')
def scale(self, factor): def scale(self, factor):
""" """
Scales the objects' geometry on the XY plane by a given factor. Scales the objects' geometry on the XY plane by a given factor.
@@ -343,16 +408,20 @@ class Gerber (Geometry):
:return: Identifier of the aperture. :return: Identifier of the aperture.
:rtype: str :rtype: str
""" """
indexstar = gline.find("*") indexstar = gline.find("*")
indexc = gline.find("C,") indexc = gline.find("C,")
if indexc != -1: # Circle, example: %ADD11C,0.1*% if indexc != -1: # Circle, example: %ADD11C,0.1*%
apid = gline[4:indexc] # Found some Gerber with a leading zero in the aperture id and the
# referenced it without the zero, so this is a hack to handle that.
apid = str(int(gline[4:indexc]))
self.apertures[apid] = {"type": "C", self.apertures[apid] = {"type": "C",
"size": float(gline[indexc+2:indexstar])} "size": float(gline[indexc+2:indexstar])}
return apid return apid
indexr = gline.find("R,") indexr = gline.find("R,")
if indexr != -1: # Rectangle, example: %ADD15R,0.05X0.12*% if indexr != -1: # Rectangle, example: %ADD15R,0.05X0.12*%
apid = gline[4:indexr] # Hack explained above
apid = str(int(gline[4:indexr]))
indexx = gline.find("X") indexx = gline.find("X")
self.apertures[apid] = {"type": "R", self.apertures[apid] = {"type": "R",
"width": float(gline[indexr+2:indexx]), "width": float(gline[indexr+2:indexx]),
@@ -360,7 +429,8 @@ class Gerber (Geometry):
return apid return apid
indexo = gline.find("O,") indexo = gline.find("O,")
if indexo != -1: # Obround if indexo != -1: # Obround
apid = gline[4:indexo] # Hack explained above
apid = str(int(gline[4:indexo]))
indexx = gline.find("X") indexx = gline.find("X")
self.apertures[apid] = {"type": "O", self.apertures[apid] = {"type": "O",
"width": float(gline[indexo+2:indexx]), "width": float(gline[indexo+2:indexx]),
@@ -381,67 +451,148 @@ class Gerber (Geometry):
def parse_lines(self, glines): def parse_lines(self, glines):
""" """
Main Gerber parser. Main Gerber parser. Reads Gerber and populates ``self.paths``, ``self.apertures``,
``self.flashes``, ``self.regions`` and ``self.units``.
:param glines: Gerber code as list of strings, each
element being one line of the source file.
:type glines: list
:return: None
:rtype: None
""" """
# Mode (IN/MM)
mode_re = re.compile(r'^%MO(IN|MM)\*%$')
path = [] # Coordinates of the current path path = [] # Coordinates of the current path
last_path_aperture = None last_path_aperture = None
current_aperture = None current_aperture = None
# 1,2 or 3 from "G01", "G02" or "G03"
current_interpolation_mode = None
# 1 or 2 from "D01" or "D02"
# Note this is to support deprecated Gerber not putting
# an operation code at the end of every coordinate line.
current_operation_code = None
# Current coordinates
current_x = None
current_y = None
for gline in glines: for gline in glines:
if gline.find("D01*") != -1: # pen down # Linear interpolation plus flashes
path.append(coord(gline, self.digits, self.fraction)) match = self.lin_re.search(gline)
last_path_aperture = current_aperture if match:
# Parse coordinates
if match.group(2) is not None:
current_x = parse_gerber_number(match.group(2), self.frac_digits)
if match.group(3) is not None:
current_y = parse_gerber_number(match.group(3), self.frac_digits)
# Parse operation code
if match.group(4) is not None:
current_operation_code = match.group(4)
# Pen down: add segment
if current_operation_code == '1':
path.append([current_x, current_y])
last_path_aperture = current_aperture
# Pen up: finish path
elif current_operation_code == '2':
if len(path) > 1:
self.paths.append({"linestring": LineString(path),
"aperture": last_path_aperture})
path = [[current_x, current_y]]
# Flash
elif current_operation_code == '3':
self.flashes.append({"loc": [current_x, current_y],
"aperture": current_aperture})
continue continue
if gline.find("D02*") != -1: # pen up # if gline.find("D01*") != -1: # pen down
if len(path) > 1: # path.append(parse_gerber_coords(gline, self.int_digits, self.frac_digits))
# Path completed, create shapely LineString # last_path_aperture = current_aperture
self.paths.append({"linestring": LineString(path), # continue
"aperture": last_path_aperture}) #
path = [coord(gline, self.digits, self.fraction)] # if gline.find("D02*") != -1: # pen up
continue # if len(path) > 1:
# # Path completed, create shapely LineString
indexd3 = gline.find("D03*") # self.paths.append({"linestring": LineString(path),
if indexd3 > 0: # Flash # "aperture": last_path_aperture})
self.flashes.append({"loc": coord(gline, self.digits, self.fraction), # path = [parse_gerber_coords(gline, self.int_digits, self.frac_digits)]
"aperture": current_aperture}) # continue
continue #
if indexd3 == 0: # Flash? # indexd3 = gline.find("D03*")
print "WARNING: Uninplemented flash style:", gline # if indexd3 > 0: # Flash
continue # self.flashes.append({"loc": parse_gerber_coords(gline, self.int_digits, self.frac_digits),
# "aperture": current_aperture})
if gline.find("G37*") != -1: # end region # continue
# if indexd3 == 0: # Flash?
# print "WARNING: Uninplemented flash style:", gline
# continue
# End region
if self.regionoff_re.search(gline):
# Only one path defines region? # Only one path defines region?
self.regions.append({"polygon": Polygon(path), self.regions.append({"polygon": Polygon(path),
"aperture": last_path_aperture}) "aperture": last_path_aperture})
path = [] path = []
continue continue
# if gline.find("G37*") != -1: # end region
# # Only one path defines region?
# self.regions.append({"polygon": Polygon(path),
# "aperture": last_path_aperture})
# path = []
# continue
if gline.find("%ADD") != -1: # aperture definition if gline.find("%ADD") != -1: # aperture definition
self.aperture_parse(gline) # adds element to apertures self.aperture_parse(gline) # adds element to apertures
continue continue
indexstar = gline.find("*") # Interpolation mode change
if gline.find("D") == 0: # Aperture change # Can occur along with coordinates and operation code but
current_aperture = gline[1:indexstar] # sometimes by itself (handled here).
continue # Example: G01*
if gline.find("G54D") == 0: # Aperture change (deprecated) match = self.interp_re.search(gline)
current_aperture = gline[4:indexstar] if match:
continue current_interpolation_mode = int(match.group(1))
if gline.find("%FS") != -1: # Format statement
indexx = gline.find("X")
self.digits = int(gline[indexx + 1])
self.fraction = int(gline[indexx + 2])
continue continue
# Tool/aperture change
# Example: D12*
match = self.tool_re.search(gline)
if match:
current_aperture = match.group(1)
continue
# indexstar = gline.find("*")
# if gline.find("D") == 0: # Aperture change
# current_aperture = gline[1:indexstar]
# continue
# if gline.find("G54D") == 0: # Aperture change (deprecated)
# current_aperture = gline[4:indexstar]
# continue
# Number format
# TODO: This is ignoring most of the format. Implement the rest.
match = self.fmt_re.search(gline)
if match:
self.int_digits = int(match.group(3))
self.frac_digits = int(match.group(4))
continue
# if gline.find("%FS") != -1: # Format statement
# indexx = gline.find("X")
# self.int_digits = int(gline[indexx + 1])
# self.frac_digits = int(gline[indexx + 2])
# continue
# Mode (IN/MM) # Mode (IN/MM)
match = mode_re.search(gline) match = self.mode_re.search(gline)
if match: if match:
self.units = match.group(1) self.units = match.group(1)
continue continue
@@ -452,7 +603,12 @@ class Gerber (Geometry):
# EOF, create shapely LineString if something still in path # EOF, create shapely LineString if something still in path
self.paths.append({"linestring": LineString(path), self.paths.append({"linestring": LineString(path),
"aperture": last_path_aperture}) "aperture": last_path_aperture})
# if len(path) > 1:
# # EOF, create shapely LineString if something still in path
# self.paths.append({"linestring": LineString(path),
# "aperture": current_aperture})
def do_flashes(self): def do_flashes(self):
""" """
Creates geometry for Gerber flashes (aperture on a single point). Creates geometry for Gerber flashes (aperture on a single point).
@@ -1133,19 +1289,22 @@ def get_bounds(geometry_set):
def arc(center, radius, start, stop, direction, steps_per_circ): def arc(center, radius, start, stop, direction, steps_per_circ):
""" """
Creates a Shapely.LineString for the specified arc. Creates a Shapely.LineString for the specified arc.
@param center: Coordinates of the center [x, y]
@type center: list :param center: Coordinates of the center [x, y]
@param radius: Radius of the arc. :type center: list
@type radius: float :param radius: Radius of the arc.
@param start: Starting angle in radians :type radius: float
@type start: float :param start: Starting angle in radians
@param stop: End angle in radians :type start: float
@type stop: float :param stop: End angle in radians
@param direction: Orientation of the arc, "CW" or "CCW" :type stop: float
@type direction: string :param direction: Orientation of the arc, "CW" or "CCW"
@param steps_per_circ: Number of straight line segments to :type direction: string
:param steps_per_circ: Number of straight line segments to
represent a circle. represent a circle.
@type steps_per_circ: int :type steps_per_circ: int
:return: The desired arc.
:rtype: Shapely.LineString
""" """
da_sign = {"cw": -1.0, "ccw": 1.0} da_sign = {"cw": -1.0, "ccw": 1.0}
points = [] points = []
@@ -1170,14 +1329,16 @@ def clear_poly(poly, tooldia, overlap=0.1):
Creates a list of Shapely geometry objects covering the inside Creates a list of Shapely geometry objects covering the inside
of a Shapely.Polygon. Use for removing all the copper in a region of a Shapely.Polygon. Use for removing all the copper in a region
or bed flattening. or bed flattening.
@param poly: Target polygon
@type poly: Shapely.Polygon :param poly: Target polygon
@param tooldia: Diameter of the tool :type poly: Shapely.Polygon
@type tooldia: float :param tooldia: Diameter of the tool
@param overlap: Fraction of the tool diameter to overlap :type tooldia: float
:param overlap: Fraction of the tool diameter to overlap
in each pass. in each pass.
@type overlap: float :type overlap: float
@return list of Shapely.Polygon :return: list of Shapely.Polygon
:rtype: list
""" """
poly_cuts = [poly.buffer(-tooldia/2.0)] poly_cuts = [poly.buffer(-tooldia/2.0)]
while True: while True:
@@ -1251,11 +1412,33 @@ def plotg(geo):
print "Cannot plot:", str(type(g)) print "Cannot plot:", str(type(g))
continue continue
def parse_gerber_number(strnumber, frac_digits):
"""
Parse a single number of Gerber coordinates.
############### cam.py #################### :param strnumber: String containing a number in decimal digits
def coord(gstr, digits, fraction): from a coordinate data block, possibly with a leading sign.
:type strnumber: str
:param frac_digits: Number of digits used for the fractional
part of the number
:type frac_digits: int
:return: The number in floating point.
:rtype: float
"""
return int(strnumber)*(10**(-frac_digits))
def parse_gerber_coords(gstr, int_digits, frac_digits):
""" """
Parse Gerber coordinates Parse Gerber coordinates
:param gstr: Line of G-Code containing coordinates.
:type gstr: str
:param int_digits: Number of digits in integer part of a number.
:type int_digits: int
:param frac_digits: Number of digits in frac_digits part of a number.
:type frac_digits: int
:return: [x, y] coordinates.
:rtype: list
""" """
global gerbx, gerby global gerbx, gerby
xindex = gstr.find("X") xindex = gstr.find("X")
@@ -1263,14 +1446,13 @@ def coord(gstr, digits, fraction):
index = gstr.find("D") index = gstr.find("D")
if xindex == -1: if xindex == -1:
x = gerbx x = gerbx
y = int(gstr[(yindex+1):index])*(10**(-fraction)) y = int(gstr[(yindex+1):index])*(10**(-frac_digits))
elif yindex == -1: elif yindex == -1:
y = gerby y = gerby
x = int(gstr[(xindex+1):index])*(10**(-fraction)) x = int(gstr[(xindex+1):index])*(10**(-frac_digits))
else: else:
x = int(gstr[(xindex+1):yindex])*(10**(-fraction)) x = int(gstr[(xindex+1):yindex])*(10**(-frac_digits))
y = int(gstr[(yindex+1):index])*(10**(-fraction)) y = int(gstr[(yindex+1):index])*(10**(-frac_digits))
gerbx = x gerbx = x
gerby = y gerby = y
return [x, y] return [x, y]
################ end of cam.py #############

Binary file not shown.

Binary file not shown.

View File

@@ -5,7 +5,7 @@
Welcome to Cirkuix's documentation! Welcome to FlatCAM's documentation!
=================================== ===================================
Contents: Contents:

View File

@@ -382,6 +382,10 @@
<table style="width: 100%" class="indextable genindextable"><tr> <table style="width: 100%" class="indextable genindextable"><tr>
<td style="width: 33%" valign="top"><dl> <td style="width: 33%" valign="top"><dl>
<dt><a href="index.html#FlatCAM.App.on_about">on_about() (FlatCAM.App method)</a>
</dt>
<dt><a href="index.html#FlatCAM.App.on_activate_name">on_activate_name() (FlatCAM.App method)</a> <dt><a href="index.html#FlatCAM.App.on_activate_name">on_activate_name() (FlatCAM.App method)</a>
</dt> </dt>

24
doc/build/index.html vendored
View File

@@ -7,7 +7,7 @@
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Welcome to Cirkuixs documentation! &mdash; Cirkuix 0.5 documentation</title> <title>Welcome to FlatCAMs documentation! &mdash; Cirkuix 0.5 documentation</title>
@@ -102,7 +102,7 @@
<ul class="wy-breadcrumbs"> <ul class="wy-breadcrumbs">
<li><a href="#">Docs</a> &raquo;</li> <li><a href="#">Docs</a> &raquo;</li>
<li>Welcome to Cirkuix&#8217;s documentation!</li> <li>Welcome to FlatCAM&#8217;s documentation!</li>
<li class="wy-breadcrumbs-aside"> <li class="wy-breadcrumbs-aside">
<a href="_sources/index.txt" rel="nofollow"> View page source</a> <a href="_sources/index.txt" rel="nofollow"> View page source</a>
@@ -113,8 +113,8 @@
</div> </div>
<div role="main"> <div role="main">
<div class="section" id="welcome-to-cirkuix-s-documentation"> <div class="section" id="welcome-to-flatcam-s-documentation">
<h1>Welcome to Cirkuix&#8217;s documentation!<a class="headerlink" href="#welcome-to-cirkuix-s-documentation" title="Permalink to this headline"></a></h1> <h1>Welcome to FlatCAM&#8217;s documentation!<a class="headerlink" href="#welcome-to-flatcam-s-documentation" title="Permalink to this headline"></a></h1>
<p>Contents:</p> <p>Contents:</p>
<div class="toctree-wrapper compound"> <div class="toctree-wrapper compound">
<ul class="simple"> <ul class="simple">
@@ -326,6 +326,22 @@ called with 2 parameters: the new object and the App instance.</li>
</table> </table>
</dd></dl> </dd></dl>
<dl class="method">
<dt id="FlatCAM.App.on_about">
<tt class="descname">on_about</tt><big>(</big><em>widget</em><big>)</big><a class="headerlink" href="#FlatCAM.App.on_about" title="Permalink to this definition"></a></dt>
<dd><p>Opens the &#8216;About&#8217; dialog box.</p>
<table class="docutils field-list" frame="void" rules="none">
<col class="field-name" />
<col class="field-body" />
<tbody valign="top">
<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>widget</strong> &#8211; Ignored.</td>
</tr>
<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body">None</td>
</tr>
</tbody>
</table>
</dd></dl>
<dl class="method"> <dl class="method">
<dt id="FlatCAM.App.on_activate_name"> <dt id="FlatCAM.App.on_activate_name">
<tt class="descname">on_activate_name</tt><big>(</big><em>entry</em><big>)</big><a class="headerlink" href="#FlatCAM.App.on_activate_name" title="Permalink to this definition"></a></dt> <tt class="descname">on_activate_name</tt><big>(</big><em>entry</em><big>)</big><a class="headerlink" href="#FlatCAM.App.on_activate_name" title="Permalink to this definition"></a></dt>

BIN
doc/build/objects.inv vendored

Binary file not shown.

File diff suppressed because one or more lines are too long

0
doc/source/test Normal file
View File