Import LinuxCNC source tree

This commit is contained in:
Wang Dequan
2026-08-20 06:17:39 +08:00
commit 2c814634c3
9429 changed files with 10556013 additions and 0 deletions

View File

@@ -0,0 +1,14 @@
plasmac2 is a customised AXIS GUI for operating a plasma cutting table using the plasmac component.
Included is an application to enable migrating a working QtPlasmaC configuration to plasmac2.
To begin a migration, call the application from a terminal using one of the following commands depending on the LinuxCNC installation type:
Package installation:
python3 /usr/share/doc/linuxcnc/examples/sample-configs/sim/axis/plasmac2/plasmac2/migrate.py
Run-In-Place installation:
python3 ~/linuxcnc-dev/configs/sim/axis/plasmac2/plasmac2/migrate.py
The correct file link may be copied from the plasmac2 menu Help > Migration or directly from above.
See the file customizing.html for user customization tips.

View File

@@ -0,0 +1,17 @@
# Keep your plasmac2 I/O connections here to prevent them from
# being overwritten by updates or pncconf/stepconf changes
# Other customisations may be placed here as well
#***** DEBOUNCE FOR THE INPUTS *****
# for the float and ohmic inputs
# each increment in delay is a 0.001mm (0.00004") increase in any probed height result
setp db_float.delay 5
setp db_ohmic.delay 5
setp db_breakaway.delay 5
setp db_arc-ok.delay 5
#***** ARC VOLTAGE LOWPASS FILTER *****
# only use this if comprehensive testing shows that it is required
# change to the cutoff frequency you require
setp plasmac.lowpass-frequency 0

View File

@@ -0,0 +1,65 @@
<!DOCTYPE html>
<html>
<head>
<h2>plasmac2 Customization</h2>
</head>
<body>
<p><b>plasmac2</b> makes extensive use of the
<a href='http://linuxcnc.org/docs/devel/html/gui/axis.html#_axis_customization_hints'>AXIS customization tips</a>
from the LinuxCNC docs.</p>
<p>The three files available in plasmac2 for user customizing are:
<ul>
<li><a href='user_commands.py'>user_commands.py</a> for custom python code, called once at startup</li>
<li><a href='./user_hal.py'>user_hal.py</a> for creating HAL pins, called once at startup</li>
<li><a href='./user_periodic.py'>user_periodic.py</a> for updating, called every cycle</li>
</ul></p>
<hr style='width:90%'>
<br>
<p>The AXIS GUI is written in TCL which requires calling the TCL interpreter to customize widgets.</p>
<p>There are two available "shortcuts" to achieve this.
<ul>
<li><code>rC = root_window.tk.call()</code></li>
<li><code>rE = root_window.tk.eval()</code></li>
</ul>
Both of these require the arguments to be passed as strings, variable names may be passed as python format strings.</p>
<p>In the following examples, <i>foverride</i> is the variable name for the height override frame which has a string name of <i>.pane.top.tabs.fmanual.override</i></p>
<p>Hiding the height override frame can be achieved by either of the above methods:
<ul>
<li><code>rC('grid', 'forget', f'{foverride}')</code></li>
<li><code>rE(f'grid forget {foverride}')</code></li>
</ul></p>
<p>To show the override frame again you would need to find where <i>foverride</i> was first shown in <a href='./plasmac2/plasmac2.py'>plasmac2.py</a> and copy the code.
<br>Either of the following would achieve this:
<ul>
<li><code>rC('grid',foverride,'-column',0,'-row',3,'-padx',2,'-pady',(0,4),'-sticky','ew')</code></li>
<li><code>rE(f'grid {foverride} -column 0 -row 3 -padx 2 -pady [list 0 4] -sticky ew')</code></li>
</ul></p>
<hr style='width:90%'>
<br>
<p>A list of widget names may be obtained by using an existing function that returns all the children of a widget.
<br>
Note that conversational widgets will not be shown until the conversational panel is opened at least once.</p>
<p><code>parent = '.' # '.' is the root widget
<br>#parent = '.pane.top.tabs.fmanual' # '.pane.top.tabs.fmanual' is the manual tab
<br>widget_list = get_all_children(parent)
<br>print(f'\nplasmac2 has {len(widget_list)} widgets:\n{sorted(widget_list)}')</code></p>
<p>There is an example in <a href='./user_periodic.py'>user_periodic.py</a> of creating a file listing all the available widgets, this requires an example HAL pin created in <a href='./user_hal.py'>user_hal.py</a></p>
<hr style='width:90%'>
<br>
<p>The HAL component name for AXIS is <i>axisui</i> which means any pins created in <a href='./user_hal.py'>user_hal.py</a> will have <i>axisui.</i> as the first part of the pin name.</p>
</body>
</html>

View File

@@ -0,0 +1,176 @@
[APPLICATIONS]
DELAY = 3
APP = plasmac2/lib/sim/sim_panel.py
[FILTER]
PROGRAM_EXTENSION = .ngc,.nc,.tap (filter gcode files)
ngc = qtplasmac_gcode
nc = qtplasmac_gcode
tap = qtplasmac_gcode
[RS274NGC]
RS274NGC_STARTUP_CODE = G20 G40 G49 G80 G90 G92.1 G94 G97 M52P1
PARAMETER_FILE = imperial_parameters.txt
SUBROUTINE_PATH = ./:../../nc_files
FEATURES = 12
USER_M_PATH = ./:plasmac2/lib
[HAL]
TWOPASS = ON
HALFILE = plasmac2/lib/sim/sim_stepgen.tcl
HALFILE = qtplasmac_comp.hal
HALFILE = custom.hal
HALUI = halui
[DISPLAY]
DISPLAY = axis
POSITION_OFFSET = RELATIVE
POSITION_FEEDBACK = ACTUAL
MAX_FEED_OVERRIDE = 1.5
PROGRAM_PREFIX = ../../nc_files
INTRO_GRAPHIC = linuxcnc.gif
INTRO_TIME = 1
CYCLE_TIME = 100
INCREMENTS = 1, .1, .01, .001, .0001
MDI_HISTORY_FILE = imperial_mdi_history.txt
OPEN_FILE = ""
EDITOR = geany
TOOL_EDITOR = tooledit x y
USER_COMMAND_FILE = ./plasmac2/plasmac2.py
[EMC]
VERSION = 1.1
MACHINE = imperial
DEBUG = 0
[EMCIO]
TOOL_TABLE = imperial_tool.tbl
[EMCMOT]
EMCMOT = motmod
BASE_PERIOD = 100000
SERVO_PERIOD = 1000000
[TASK]
TASK = milltask
CYCLE_TIME = 0.01
[KINS]
KINEMATICS = trivkins coordinates=xyyz
JOINTS = 4
[TRAJ]
SPINDLES = 3
COORDINATES = XYYZ
LINEAR_UNITS = inch
MAX_LINEAR_VELOCITY = 14
ANGULAR_UNITS = degree
POSITION_FILE = imperial_position.txt
[AXIS_X]
MIN_LIMIT = -0.001
MAX_LIMIT = 48.001
# MAX_VEL & MAX_ACC need to be twice the corresponding joint value
MAX_VELOCITY = 20
MAX_ACCELERATION = 200
OFFSET_AV_RATIO = 0.5
[JOINT_0]
MIN_LIMIT = -0.001
MAX_LIMIT = 48.001
MAX_VELOCITY = 10
MAX_ACCELERATION = 100
STEPGEN_MAXACCEL = 120
TYPE = LINEAR
MIN_FERROR = 0.04
FERROR = 0.4
HOME = 0
HOME_OFFSET = 0
HOME_SEQUENCE = 1
HOME_SEARCH_VEL = 2
HOME_LATCH_VEL = 0.2
HOME_FINAL_VEL = 4
STEP_SCALE = 1
STEPLEN = 1
STEPSPACE = 1
DIRSETUP = 1
DIRHOLD = 1
[AXIS_Y]
MIN_LIMIT = -0.001
MAX_LIMIT = 48.001
# MAX_VEL & MAX_ACC need to be twice the corresponding joint value
MAX_VELOCITY = 20
MAX_ACCELERATION = 200
OFFSET_AV_RATIO = 0.5
[JOINT_1]
MIN_LIMIT = -0.001
MAX_LIMIT = 48.001
MAX_VELOCITY = 10
MAX_ACCELERATION = 100
STEPGEN_MAXACCEL = 120
TYPE = LINEAR
MIN_FERROR = 0.04
FERROR = 0.4
HOME = 0
HOME_OFFSET = 0
HOME_SEQUENCE = -2
HOME_SEARCH_VEL = 2
HOME_LATCH_VEL = 0.2
HOME_FINAL_VEL = 4
STEP_SCALE = 1
STEPLEN = 1
STEPSPACE = 1
DIRSETUP = 1
DIRHOLD = 1
[JOINT_2]
MIN_LIMIT = -0.001
MAX_LIMIT = 48.001
MAX_VELOCITY = 10
MAX_ACCELERATION = 100
STEPGEN_MAXACCEL = 120
TYPE = LINEAR
MIN_FERROR = 0.04
FERROR = 0.4
HOME = 0
HOME_OFFSET = 0
HOME_SEQUENCE = -2
HOME_SEARCH_VEL = 2
HOME_LATCH_VEL = 0.2
HOME_FINAL_VEL = 4
STEP_SCALE = 1
STEPLEN = 1
STEPSPACE = 1
DIRSETUP = 1
DIRHOLD = 1
[AXIS_Z]
MIN_LIMIT = -0.001
MAX_LIMIT = 4.001
# MAX_VEL & MAX_ACC need to be twice the corresponding joint value
MAX_VELOCITY = 4.8
MAX_ACCELERATION = 48
OFFSET_AV_RATIO = 0.5
[JOINT_3]
MIN_LIMIT = -0.001
MAX_LIMIT = 4.001
MAX_VELOCITY = 2.4
MAX_ACCELERATION = 24
STEPGEN_MAXACCEL = 35
TYPE = LINEAR
MIN_FERROR = 0.04
FERROR = 0.4
HOME = 3.8
HOME_OFFSET = 4
HOME_SEQUENCE = 0
HOME_SEARCH_VEL = 2
HOME_LATCH_VEL = 0.2
HOME_FINAL_VEL = 4
STEP_SCALE = 1
STEPLEN = 1
STEPSPACE = 1
DIRSETUP = 1
DIRHOLD = 1

View File

@@ -0,0 +1,150 @@
[GUI_OPTIONS]
Mode = 0
Font size = 10
Exit warning = True
Window size = default
Preview cone size = 0.2
Cut recovery speed % = 20
Default material = 2
Open file =
Exit warning text = Did I turn the gas off ?
Window last = 983x562
Jog speed = 300
Table zoom = 1.3
Version = 2.21
Orientation = landscape
GUI font = Sans
Gcode font = Sans
Foreground color = #000000
Background color = #808080
Disabled color = #a0a0a0
Active color = #00cc00
Warning color = #dd0000
Voltage color = #ff8800
Arc OK color = #ff8800
LED color = #eeff00
Trough color = #505050
Popup location = pointer
Use soft keyboard = False
Use keyboard shortcuts = True
[LASER_OFFSET]
X axis = 1.23
Y axis = 0.45
[ENABLE_OPTIONS]
THC enable = True
Corner lock enable = True
Kerf cross enable = False
Use auto volts = True
Ohmic probe enable = True
THC auto = False
Void lock enable = False
[STATISTICS]
Cut length = 0.0
Pierce count = 0
Rapid time = 0
Probe time = 0
Torch on time = 0
Paused time = 0
Cut time = 0
Program run time = 0
[PLASMA_PARAMETERS]
Float Switch Travel = 0.06
Probe Feed Rate = 18.0
Probe Start Height = 0.6
Ohmic Probe Offset = 0.0
Ohmic Maximum Attempts = 0
Skip IHS Distance = 0
Setup Feed Rate = 114.0
THC Delay = 0.5
THC Threshold = 1.0
Pid P Gain = 10
Pid I Gain = 0
Pid D Gain = 0
Velocity Anti Dive Threshold = 90
Void Sense Override = 100
Safe Height = 0.75
Arc Fail Timeout = 3.0
Arc Maximum Starts = 3
Arc Restart Delay = 3
Arc Voltage Scale = 1.0
Arc Voltage Offset = 0.0
Ark OK High = 99999
Arc OK Low = 60
Height Per Volt = 0.004
Scribe Arming Delay = 0.0
Scribe On Delay = 0.0
Spotting Threshold = 0
Spotting Time = 0
THC Sample Counts = 50
THC Sample Threshold = 1
Void Sense Slope = 500
Arc OK High = 99999
Offset Feed Rate = 480.0
X Pierce Offset = 0.06
Y Pierce Offset = 0.0
[POWERMAX]
Port =
[BUTTONS]
Torch enabled = Torch Enabled
Torch disabled = Torch Disabled
1 Name = Ohmic Test
1 Code = ohmic-test
2 Name = Probe Test
2 Code = probe-test 10
3 Name = Single Cut
3 Code = single-cut
4 Name = Pierce & Cut
4 Code = cut-type
5 Name = Torch Pulse
5 Code = torch-pulse 0.5
6 Name = Framing
6 Code = framing F20 usecurrentzheight
7 Name = Change Cons
7 Code = change-consumables X4 Y4 F200
8 Name =
8 Code =
9 Name =
9 Code =
10 Name =
10 Code =
11 Name = Z To Top
11 Code = g53g0Z[{AXIS_Z MAX_LIMIT}-0.04]
12 Name =
12 Code =
13 Name =
13 Code =
14 Name =
14 Code =
15 Name =
15 Code =
16 Name =
16 Code =
17 Name =
17 Code =
18 Name =
18 Code =
19 Name = HAL Show
19 Code = %halshow
20 Name = Clear Errors
20 Code = pulse-halpin axisui.notifications-clear .25
[CONVERSATIONAL]
Preamble = G20 G64P0.01 G40 G49 G80 G90 G92.1 G94 G97
Postamble = G20 G64P0.01 G40 G49 G80 G90 G92.1 G94 G97
Origin = 0
Leadin = 0.2
Leadout = 0.0
Hole diameter = 1.26
Hole speed = 60
[OFFSET_PROBING]
X axis = 0
Y axis = 0
Delay = 0

View File

@@ -0,0 +1,74 @@
[MATERIAL_NUMBER_1]
NAME = Mild Steel 16GA
KERF_WIDTH = 0.053
PIERCE_HEIGHT = 0.15
PIERCE_DELAY = 0.1
PUDDLE_JUMP_HEIGHT = 0.0
PUDDLE_JUMP_DELAY = 0.0
CUT_HEIGHT = 0.06
CUT_SPEED = 249
CUT_AMPS = 45
CUT_VOLTS = 128
PAUSE_AT_END = 0.0
GAS_PRESSURE = 0.0
CUT_MODE = 1.0
[MATERIAL_NUMBER_2]
NAME = Mild Steel 14GA
KERF_WIDTH = 0.054
PIERCE_HEIGHT = 0.15
PIERCE_DELAY = 0.2
PUDDLE_JUMP_HEIGHT = 0
PUDDLE_JUMP_DELAY = 0.0
CUT_HEIGHT = 0.06
CUT_SPEED = 225
CUT_AMPS = 45
CUT_VOLTS = 128
PAUSE_AT_END = 0.0
GAS_PRESSURE = 0.0
CUT_MODE = 1
[MATERIAL_NUMBER_3]
NAME = Mild Steel 10GA
KERF_WIDTH = 0.057
PIERCE_HEIGHT = 0.15
PIERCE_DELAY = 0.4
PUDDLE_JUMP_HEIGHT = 0.0
PUDDLE_JUMP_DELAY = 0.0
CUT_HEIGHT = 0.06
CUT_SPEED = 129
CUT_AMPS = 45
CUT_VOLTS = 128
PAUSE_AT_END = 0.0
GAS_PRESSURE = 0.0
CUT_MODE = 1.0
[MATERIAL_NUMBER_4]
NAME = Mild Steel 3/16
KERF_WIDTH = 0.059
PIERCE_HEIGHT = 0.15
PIERCE_DELAY = 0.5
PUDDLE_JUMP_HEIGHT = 0
PUDDLE_JUMP_DELAY = 0.0
CUT_HEIGHT = 0.06
CUT_SPEED = 85
CUT_AMPS = 45
CUT_VOLTS = 129
PAUSE_AT_END = 0.0
GAS_PRESSURE = 0
CUT_MODE = 1
[MATERIAL_NUMBER_114]
NAME = for alex.ngc
KERF_WIDTH = 0.054
PIERCE_HEIGHT = 0.15
PIERCE_DELAY = 0.2
PUDDLE_JUMP_HEIGHT = 0
PUDDLE_JUMP_DELAY = 0.0
CUT_HEIGHT = 0.06
CUT_SPEED = 225
CUT_AMPS = 45
CUT_VOLTS = 128
PAUSE_AT_END = 0.0
GAS_PRESSURE = 0.0
CUT_MODE = 1

View File

@@ -0,0 +1,2 @@
T0 P1 X0.0 Y0.0 ;torch
T1 P2 X1.0 Y0.0 ;scribe

View File

@@ -0,0 +1,176 @@
[APPLICATIONS]
DELAY = 3
APP = plasmac2/lib/sim/sim_panel.py
[FILTER]
PROGRAM_EXTENSION = .ngc,.nc,.tap (filter gcode files)
ngc = qtplasmac_gcode
nc = qtplasmac_gcode
tap = qtplasmac_gcode
[RS274NGC]
RS274NGC_STARTUP_CODE = G21 G40 G49 G80 G90 G92.1 G94 G97 M52P1
PARAMETER_FILE = metric_parameters.txt
SUBROUTINE_PATH = ./:../../nc_files
FEATURES = 12
USER_M_PATH = ./:plasmac2/lib
[HAL]
TWOPASS = ON
HALFILE = plasmac2/lib/sim/sim_stepgen.tcl
HALFILE = qtplasmac_comp.hal
HALFILE = custom.hal
HALUI = halui
[DISPLAY]
DISPLAY = axis
POSITION_OFFSET = RELATIVE
POSITION_FEEDBACK = ACTUAL
MAX_FEED_OVERRIDE = 1.5
PROGRAM_PREFIX = ../../nc_files
INTRO_GRAPHIC = linuxcnc.gif
INTRO_TIME = 1
CYCLE_TIME = 100
INCREMENTS = 10, 1, .1, .01, .001
MDI_HISTORY_FILE = metric_mdi_history.txt
OPEN_FILE = ""
EDITOR = geany
TOOL_EDITOR = tooledit x y
USER_COMMAND_FILE = ./plasmac2/plasmac2.py
[EMC]
VERSION = 1.1
MACHINE = metric
DEBUG = 0
[EMCIO]
TOOL_TABLE = metric_tool.tbl
[EMCMOT]
EMCMOT = motmod
BASE_PERIOD = 100000
SERVO_PERIOD = 1000000
[TASK]
TASK = milltask
CYCLE_TIME = 0.01
[KINS]
KINEMATICS = trivkins coordinates=xyyz
JOINTS = 4
[TRAJ]
SPINDLES = 3
COORDINATES = XYYZ
LINEAR_UNITS = mm
MAX_LINEAR_VELOCITY = 350
ANGULAR_UNITS = degree
POSITION_FILE = metric_position.txt
[AXIS_X]
MIN_LIMIT = -0.01
MAX_LIMIT = 1200.01
# MAX_VEL & MAX_ACC need to be twice the corresponding joint value
MAX_VELOCITY = 500
MAX_ACCELERATION = 5000
OFFSET_AV_RATIO = 0.5
[JOINT_0]
MIN_LIMIT = -0.01
MAX_LIMIT = 1200.01
MAX_VELOCITY = 250
MAX_ACCELERATION = 2500
STEPGEN_MAXACCEL = 3000
TYPE = LINEAR
MIN_FERROR = 1
FERROR = 10
HOME = 0
HOME_OFFSET = 0
HOME_SEQUENCE = 1
HOME_SEARCH_VEL = 50
HOME_LATCH_VEL = 5
HOME_FINAL_VEL = 100
STEP_SCALE = 1
STEPLEN = 1
STEPSPACE = 1
DIRSETUP = 1
DIRHOLD = 1
[AXIS_Y]
MIN_LIMIT = -0.01
MAX_LIMIT = 1200.01
# MAX_VEL & MAX_ACC need to be twice the corresponding joint value
MAX_VELOCITY = 500
MAX_ACCELERATION = 5000
OFFSET_AV_RATIO = 0.5
[JOINT_1]
MIN_LIMIT = -0.01
MAX_LIMIT = 1200.01
MAX_VELOCITY = 250
MAX_ACCELERATION = 2500
STEPGEN_MAXACCEL = 3000
TYPE = LINEAR
MIN_FERROR = 1
FERROR = 10
HOME = 0
HOME_OFFSET = 0
HOME_SEQUENCE = -2
HOME_SEARCH_VEL = 50
HOME_LATCH_VEL = 5
HOME_FINAL_VEL = 100
STEP_SCALE = 1
STEPLEN = 1
STEPSPACE = 1
DIRSETUP = 1
DIRHOLD = 1
[JOINT_2]
MIN_LIMIT = -0.01
MAX_LIMIT = 1200.01
MAX_VELOCITY = 250
MAX_ACCELERATION = 2500
STEPGEN_MAXACCEL = 3000
TYPE = LINEAR
MIN_FERROR = 1
FERROR = 10
HOME = 0
HOME_OFFSET = 0
HOME_SEQUENCE = -2
HOME_SEARCH_VEL = 50
HOME_LATCH_VEL = 5
HOME_FINAL_VEL = 100
STEP_SCALE = 1
STEPLEN = 1
STEPSPACE = 1
DIRSETUP = 1
DIRHOLD = 1
[AXIS_Z]
MIN_LIMIT = -0.01
MAX_LIMIT = 100.01
# MAX_VEL & MAX_ACC need to be twice the corresponding joint value
MAX_VELOCITY = 120
MAX_ACCELERATION = 1200
OFFSET_AV_RATIO = 0.5
[JOINT_3]
MIN_LIMIT = -0.01
MAX_LIMIT = 100.01
MAX_VELOCITY = 60
MAX_ACCELERATION = 600
STEPGEN_MAXACCEL = 900
TYPE = LINEAR
MIN_FERROR = 1
FERROR = 10
HOME = 95
HOME_OFFSET = 100
HOME_SEQUENCE = 0
HOME_SEARCH_VEL = 50
HOME_LATCH_VEL = 5
HOME_FINAL_VEL = 100
STEP_SCALE = 1
STEPLEN = 1
STEPSPACE = 1
DIRSETUP = 1
DIRHOLD = 1

View File

@@ -0,0 +1,150 @@
[GUI_OPTIONS]
Mode = 0
Font size = 10
Exit warning = True
Window size = default
Preview cone size = 0.2
Cut recovery speed % = 10
Default material = 2
Open file =
Exit warning text = Did I turn the gas off ?
Window last = 983x562
Jog speed = 2400
Table zoom = 1.3
Version = 2.21
Orientation = landscape
GUI font = Sans
Gcode font = Sans
Foreground color = #000000
Background color = #808080
Disabled color = #a0a0a0
Active color = #00cc00
Warning color = #dd0000
Voltage color = #ff8800
Arc OK color = #ff8800
LED color = #eeff00
Trough color = #505050
Popup location = pointer
Use soft keyboard = False
Use keyboard shortcuts = True
[LASER_OFFSET]
X axis = 25
Y axis = 5
[ENABLE_OPTIONS]
THC enable = True
Corner lock enable = True
Kerf cross enable = False
Use auto volts = True
Ohmic probe enable = True
THC auto = False
Void lock enable = False
[STATISTICS]
Cut length = 0.0
Pierce count = 0
Rapid time = 0
Probe time = 0
Torch on time = 0
Paused time = 0
Cut time = 0
Program run time = 0
[PLASMA_PARAMETERS]
Float Switch Travel = 1.5
Probe Feed Rate = 300
Probe Start Height = 15
Ohmic Probe Offset = 0.0
Ohmic Maximum Attempts = 0
Skip IHS Distance = 0.0
Setup Feed Rate = 2880
THC Delay = 0.5
THC Threshold = 1.0
Pid P Gain = 10
Pid I Gain = 0
Pid D Gain = 0
Velocity Anti Dive Threshold = 90
Void Sense Override = 100
Safe Height = 20
Arc Fail Timeout = 3.0
Arc Maximum Starts = 3
Arc Restart Delay = 3
Arc Voltage Scale = 1.0
Arc Voltage Offset = 0.0
Ark OK High = 99999
Arc OK Low = 60
Height Per Volt = 0.1
Scribe Arming Delay = 0.0
Scribe On Delay = 0.0
Spotting Threshold = 0
Spotting Time = 0
THC Sample Counts = 50
THC Sample Threshold = 1
Void Sense Slope = 500
Arc OK High = 99999
Offset Feed Rate = 12000.0
X Pierce Offset = 1.6
Y Pierce Offset = 0.0
[POWERMAX]
Port =
[BUTTONS]
Torch enabled = Torch Enabled
Torch disabled = Torch Disabled
1 Name = Ohmic Test
1 Code = ohmic-test
2 Name = Probe Test
2 Code = probe-test 10
3 Name = Single Cut
3 Code = single-cut
4 Name = Pierce & Cut
4 Code = cut-type
5 Name = Torch Pulse
5 Code = torch-pulse 0.5
6 Name = Framing
6 Code = framing F500 usecurrentzheight
7 Name = Change Cons
7 Code = change-consumables X100 Y100 F5000
8 Name =
8 Code =
9 Name =
9 Code =
10 Name =
10 Code =
11 Name = Z To Top
11 Code = g53g0Z[{AXIS_Z MAX_LIMIT}-0.1]
12 Name =
12 Code =
13 Name =
13 Code =
14 Name =
14 Code =
15 Name =
15 Code =
16 Name =
16 Code =
17 Name =
17 Code =
18 Name =
18 Code =
19 Name = HAL Show
19 Code = %halshow
20 Name = Clear Errors
20 Code = pulse-halpin axisui.notifications-clear .25
[CONVERSATIONAL]
Preamble = G21 G64P0.25 G40 G49 G80 G90 G92.1 G94 G97
Postamble = G21 G64P0.25 G40 G49 G80 G90 G92.1 G94 G97
Origin = 0
Leadin = 4.0
Leadout = 0.0
Hole diameter = 32.0
Hole speed = 60
[OFFSET_PROBING]
X axis = 0.0
Y axis = 0.0
Delay = 0

View File

@@ -0,0 +1,89 @@
[MATERIAL_NUMBER_0]
NAME = Zero
KERF_WIDTH = 2.0
PIERCE_HEIGHT = 3.8
PIERCE_DELAY = 0.2
PUDDLE_JUMP_HEIGHT = 0
PUDDLE_JUMP_DELAY = 0.0
CUT_HEIGHT = 1.5
CUT_SPEED = 3960
CUT_AMPS = 45
CUT_VOLTS = 128
PAUSE_AT_END = 0.0
GAS_PRESSURE = 0.0
CUT_MODE = 1
[MATERIAL_NUMBER_1]
NAME = Mild Steel 2mm
KERF_WIDTH = 1.0
PIERCE_HEIGHT = 3.8
PIERCE_DELAY = 0.2
PUDDLE_JUMP_HEIGHT = 0
PUDDLE_JUMP_DELAY = 0.0
CUT_HEIGHT = 1.5
CUT_SPEED = 5560
CUT_AMPS = 45
CUT_VOLTS = 128
PAUSE_AT_END = 0.0
GAS_PRESSURE = 0.0
CUT_MODE = 1
[MATERIAL_NUMBER_2]
NAME = Mild Steel 3mm
KERF_WIDTH = 2.0
PIERCE_HEIGHT = 3.8
PIERCE_DELAY = 0.2
PUDDLE_JUMP_HEIGHT = 0
PUDDLE_JUMP_DELAY = 0.0
CUT_HEIGHT = 1.5
CUT_SPEED = 3960
CUT_AMPS = 45
CUT_VOLTS = 128
PAUSE_AT_END = 0.0
GAS_PRESSURE = 0.0
CUT_MODE = 1
[MATERIAL_NUMBER_3]
NAME = Mild Steel 4mm
KERF_WIDTH = 1.0
PIERCE_HEIGHT = 3.8
PIERCE_DELAY = 0.4
PUDDLE_JUMP_HEIGHT = 0.0
PUDDLE_JUMP_DELAY = 0.0
CUT_HEIGHT = 1.5
CUT_SPEED = 2800
CUT_AMPS = 45
CUT_VOLTS = 128
PAUSE_AT_END = 0.0
GAS_PRESSURE = 0.0
CUT_MODE = 1
[MATERIAL_NUMBER_4]
NAME = Mild Steel 6mm
KERF_WIDTH = 0.0
PIERCE_HEIGHT = 3.8
PIERCE_DELAY = 0.6
PUDDLE_JUMP_HEIGHT = 0.0
PUDDLE_JUMP_DELAY = 0.0
CUT_HEIGHT = 1.5
CUT_SPEED = 1430
CUT_AMPS = 45
CUT_VOLTS = 130
PAUSE_AT_END = 0.0
GAS_PRESSURE = 0.0
CUT_MODE = 1
[MATERIAL_NUMBER_114]
NAME = for alex.ngc
KERF_WIDTH = 1.3
PIERCE_HEIGHT = 3.8
PIERCE_DELAY = 0.2
PUDDLE_JUMP_HEIGHT = 0
PUDDLE_JUMP_DELAY = 0.0
CUT_HEIGHT = 1.5
CUT_SPEED = 5715
CUT_AMPS = 45
CUT_VOLTS = 128
PAUSE_AT_END = 0.0
GAS_PRESSURE = 0.0
CUT_MODE = 1

View File

@@ -0,0 +1,2 @@
T0 P1 X0 Y0 ;torch
T1 P2 X0 Y0 ;scribe

View File

@@ -0,0 +1,68 @@
#!/usr/bin/python3
'''
M190
Copyright (C) 2019 - 2024 Phillip A Carter
Copyright (C) 2020 - 2024 Gregory D Carl
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, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
'''
import sys
import time
from subprocess import run as RUN
materialNum = int(float(sys.argv[1]))
timeout = 0.5
def get_material():
response = RUN(['halcmd', 'getp', 'axisui.material-change-number'], capture_output=True)
return int(response.stdout.decode())
def set_material(material):
RUN(['halcmd', 'setp', 'axisui.material-change-number', f'{material}'])
def get_change():
response = RUN(['halcmd', 'getp', 'axisui.material-change'], capture_output=True)
return int(response.stdout.decode())
def set_change(value):
RUN(['halcmd', 'setp', 'axisui.material-change', f'{value}'])
def set_timeout():
RUN(['halcmd', 'setp', 'axisui.material-change-timeout', 1])
try:
if materialNum != get_material():
set_change(1)
set_material(materialNum)
else:
set_change(3)
start = time.time()
while get_change() == 1 or get_change() == 3:
if time.time() > start + timeout:
set_timeout()
break
set_change(0)
except:
pass
exit()

View File

@@ -0,0 +1,164 @@
'''
conv_block.py
Copyright (C) 2020, 2021, 2022 Phillip A Carter
Copyright (C) 2020, 2021, 2022 Gregory D Carl
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, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
'''
import os, sys
import gettext
from importlib import reload
from plasmac import block as BLOCK
for f in sys.path:
if '/lib/python' in f:
if '/usr' in f:
localeDir = 'usr/share/locale'
else:
localeDir = os.path.join(f"{f.split('/lib')[0]}",'share','locale')
break
gettext.install('linuxcnc', localedir=localeDir)
def preview(self):
error = BLOCK.preview(self, self.fNgc, self.fTmp, \
self.cnValue.get(), self.rnValue.get(), self.coValue.get(), self.roValue.get(), \
self.xsValue.get(), self.ysValue.get(), self.aValue.get(), self.scValue.get(), \
self.rtValue.get(), self.convBlock, self.convMirror, self.convFlip, \
self.convMirrorToggle, self.convFlipToggle, self.g5xIndex, self.convUnits)
if error:
self.dialog_show_ok(_('Block Error'), error)
else:
self.fileOpener(self.fNgc, True, False)
self.addC['state'] = 'normal'
self.undoC['state'] = 'normal'
self.preview_button_pressed(True)
self.convBlock[0] = True
self.convMirrorToggle = False
self.convFlipToggle = False
def auto_preview(self):
if not self.cnValue.get() or not self.rnValue.get() or not self.scValue.get(): return
if int(self.cnValue.get()) > 1 and not self.coValue.get(): return
if int(self.rnValue.get()) > 1 and not self.roValue.get(): return
if not float(self.scValue.get()): return
if self.cnValue.get() or self.rnValue.get():
preview(self)
def mirror_shape(self):
self.convMirror = -1 if self.convMirror == 1 else 1
self.convMirrorToggle = True
preview(self)
def flip_shape(self):
self.convFlip = -1 if self.convFlip == 1 else 1
self.convFlipToggle = True
preview(self)
def get_parameters(self):
self.wcs_rotation('get')
inCode = open(self.fNgc, 'r')
self.convBlock = [False, False]
# isConvBlock = False
self.convUnits = [1, None]
self.convMirror = 1
self.convMirrorToggle = False
self.convFlip = 1
self.convFlipToggle = False
for line in inCode:
line = line.strip().lower()
# maybe check here for old style rotate, scale, and array
if line.startswith(';conversational block'):
self.convBlock = [True, True]
# isConvBlock = True
elif 'G21' in line.upper().replace(' ', '') and self.unitsPerMm != 1:
self.convUnits = [25.4, 'G21']
elif 'G20' in line.upper().replace(' ', '') and self.unitsPerMm == 1:
self.convUnits = [0.03937, 'G20']
elif 'm3' in line:
break
inCode.seek(0, 0)
if self.convBlock[0]:
# if isConvBlock:
for line in inCode:
line = line.strip().lower()
if line.startswith('#<array_x_offset>'):
self.coValue.set(f"{float(line.split('=')[1].strip()):0.4f}")
elif line.startswith('#<array_y_offset>'):
self.roValue.set(f"{float(line.split('=')[1].strip()):0.4f}")
elif line.startswith('#<array_columns>'):
self.cnValue.set(line.split('=')[1].strip())
elif line.startswith('#<array_rows>'):
self.rnValue.set(line.split('=')[1].strip())
elif line.startswith('#<origin_x_offset>'):
self.xsValue.set(f"{float(line.split('=')[1].strip()):0.4f}")
elif line.startswith('#<origin_y_offset>'):
self.ysValue.set(f"{float(line.split('=')[1].strip()):0.4f}")
elif line.startswith('#<array_angle>'):
self.aValue.set(line.split('=')[1].strip())
elif line.startswith('#<blk_scale>'):
self.scValue.set(line.split('=')[1].strip())
elif line.startswith('#<shape_angle>'):
self.rtValue.set(line.split('=')[1].strip())
elif line.startswith('#<shape_mirror>'):
self.convMirror = int(line.split('=')[1].strip())
elif line.startswith('#<shape_flip>'):
self.convFlip = int(line.split('=')[1].strip())
elif 'm3' in line:
break
inCode.seek(0, 0)
def widgets(self):
if self.comp['development']:
reload(BLOCK)
#starting parameters
# self.addC['state'] = 'disabled'
#connections
self.previewC['command'] = lambda:preview(self)
self.mirror['command'] = lambda:mirror_shape(self)
self.flip['command'] = lambda:flip_shape(self)
#add to layout
self.ccLabel.grid(column=0, row=0, pady=(4,0), columnspan=4, sticky='ew')
self.cnLabel.grid(column=0, row=1, pady=(4,0), sticky='e')
self.cnEntry.grid(column=1, row=1, pady=(4,0))
self.coLabel.grid(column=2, row=1, pady=(4,0), sticky='e')
self.coEntry.grid(column=3, row=1, pady=(4,0))
self.rrLabel.grid(column=0, row=2, pady=(14,0), columnspan=4, sticky='ew')
self.rnLabel.grid(column=0, row=3, pady=(4,0), sticky='e')
self.rnEntry.grid(column=1, row=3, pady=(4,0))
self.roLabel.grid(column=2, row=3, pady=(4,0), sticky='e')
self.roEntry.grid(column=3, row=3, pady=(4,0))
self.bsLabel.grid(column=0, row=4, pady=(14,0), columnspan=4, sticky='ew')
self.scLabel.grid(column=0, row=5, pady=(4,0), sticky='e')
self.scEntry.grid(column=1, row=5, pady=(4,0))
self.rtLabel.grid(column=2, row=5, pady=(4,0), sticky='e')
self.rtEntry.grid(column=3, row=5, pady=(4,0))
self.mirror.grid(column=1, row=6, pady=(4,0))
self.flip.grid(column=3, row=6, pady=(4,0))
self.oLabel.grid(column=0, row=7, pady=(14,0), columnspan=4, sticky='ew')
self.xsLabel.grid(column=0, row=8, pady=(4,0), sticky='e')
self.xsEntry.grid(column=1, row=8, pady=(4,0))
self.ysLabel.grid(column=2, row=8, pady=(4,0), sticky='e')
self.ysEntry.grid(column=3, row=8, pady=(4,0))
self.aLabel.grid(column=0, row=9, pady=(4,0), sticky='e')
self.aEntry.grid(column=1, row=9, pady=(4,0))
self.cnEntry.focus()
self.settingsChanged = False
get_parameters(self)
if not self.coValue.get() and self.shapeLen['x'] is not None:
self.coValue.set(round(self.shapeLen['x'], 2))
if not self.roValue.get() and self.shapeLen['y'] is not None:
self.roValue.set(round(self.shapeLen['y'], 2))

View File

@@ -0,0 +1,126 @@
'''
conv_bolt.py
Copyright (C) 2020, 2021, 2022 Phillip A Carter
Copyright (C) 2020, 2021, 2022 Gregory D Carl
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, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
'''
import os, sys
import gettext
from importlib import reload
from plasmac import bolt_circle as BOLT
for f in sys.path:
if '/lib/python' in f:
if '/usr' in f:
localeDir = 'usr/share/locale'
else:
localeDir = os.path.join(f"{f.split('/lib')[0]}",'share','locale')
break
gettext.install('linuxcnc', localedir=localeDir)
def preview(self):
matNum = int(self.matCombo.get().split(':')[0])
matNam = self.matCombo.get().split(':')[1].strip()
isCenter = self.spbValue.get() == _('CENTER')
isOvercut = self.ocEntry['state'] == 'normal' and self.ocbValue.get() == _('ON')
kerfWidth = self.materials[matNum]['kerf_width']
error = BOLT.preview(self, self.fTmp, self.fNgc, self.fNgcBkp, \
matNum, matNam, \
self.preAmble, self.postAmble, \
self.liValue.get(), self.loValue.get(), self.aValue.get(), \
isCenter, self.xsValue.get(), self.ysValue.get(), \
kerfWidth, \
isOvercut, self.ocValue.get(), \
self.smallHoleDia, self.smallHoleSpeed, self.dValue.get(), self.hdValue.get(), \
self.hoValue.get(), self.bcaValue.get(), self.invalidLeads)
if error:
self.dialog_show_ok(_('Bolt-Circle Error'), error)
else:
self.fileOpener(self.fNgc, True, False)
self.addC['state'] = 'normal'
self.undoC['state'] = 'normal'
self.preview_button_pressed(True)
def overcut_clicked(self):
if self.ocbValue.get() == _('OFF'):
self.ocbValue.set(_('ON'))
try:
lolen = float(self.loValue.get())
except:
lolen = 0
try:
dia = float(self.hdValue.get())
except:
dia = 0
if not dia or dia > self.smallHoleDia:
return
else:
self.ocEntry['state'] = 'normal'
else:
self.ocbValue.set(_('OFF'))
auto_preview(self)
def auto_preview(self):
if self.dValue.get() and self.hdValue.get() and self.hoValue.get():
preview(self)
def widgets(self):
if self.comp['development']:
reload(BOLT)
# start settings
if not self.settingsExited:
self.dValue.set('')
self.hdValue.set('')
self.hoValue.set('')
self.bcaValue.set('360')
self.aValue.set('')
self.ocButton['state'] = 'disabled'
self.dLabel['text'] = _('DIAMETER')
#connections
self.spButton['command'] = lambda:self.start_point_clicked()
self.ocButton['command'] = lambda:overcut_clicked(self)
self.previewC['command'] = lambda:preview(self)
#add to layout
self.matLabel.grid(column=0, row=0, pady=(4,0), sticky='e')
self.matCombo.grid(column=1, row=0, pady=(4,0), columnspan=3, sticky='ew')
self.spLabel.grid(column=0, row=1, pady=(4,0), sticky='e')
self.spButton.grid(column=1, row=1, pady=(4,0))
self.xsLabel.grid(column=0, row=2, pady=(4,0), sticky='e')
self.xsEntry.grid(column=1, row=2, pady=(4,0))
self.ysLabel.grid(column=2, row=2, pady=(4,0), sticky='e')
self.ysEntry.grid(column=3, row=2, pady=(4,0))
self.liLabel.grid(column=0, row=3, pady=(4,0), sticky='e')
self.liEntry.grid(column=1, row=3, pady=(4,0))
self.loLabel.grid(column=2, row=3, pady=(4,0), sticky='e')
self.loEntry.grid(column=3, row=3, pady=(4,0))
self.dLabel.grid(column=0, row=4, pady=(4,0), sticky='e')
self.dEntry.grid(column=1, row=4, pady=(4,0))
self.hdLabel.grid(column=0, row=5, pady=(4,0), sticky='e')
self.hdEntry.grid(column=1, row=5, pady=(4,0))
self.hoLabel.grid(column=0, row=6, pady=(4,0), sticky='e')
self.hoEntry.grid(column=1, row=6, pady=(4,0))
self.bcaLabel.grid(column=0, row=7, pady=(4,0), sticky='e')
self.bcaEntry.grid(column=1, row=7, pady=(4,0))
self.ocLabel.grid(column=0, row=8, pady=(4,0), sticky='e')
self.ocEntry.grid(column=1, row=8, pady=(4,0))
self.ocButton.grid(column=2, row=8, pady=(4,0))
self.aLabel.grid(column=0, row=9, pady=(4,0), sticky='e')
self.aEntry.grid(column=1, row=9, pady=(4,0))
# finish setup
self.dEntry.focus()
self.settingsExited = False

View File

@@ -0,0 +1,117 @@
'''
conv_circle.py
Copyright (C) 2020, 2021, 2022 Phillip A Carter
Copyright (C) 2020, 2021, 2022 Gregory D Carl
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, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
'''
import os, sys
import gettext
from importlib import reload
from plasmac import circle as CIRCLE
for f in sys.path:
if '/lib/python' in f:
if '/usr' in f:
localeDir = 'usr/share/locale'
else:
localeDir = os.path.join(f"{f.split('/lib')[0]}",'share','locale')
break
gettext.install('linuxcnc', localedir=localeDir)
def preview(self):
matNum = int(self.matCombo.get().split(':')[0])
matNam = self.matCombo.get().split(':')[1].strip()
isCenter = self.spbValue.get() == _('CENTER')
isExternal = self.ctbValue.get() == _('EXTERNAL')
isOvercut = self.ocEntry['state'] == 'normal' and self.ocbValue.get() == _('ON')
kerfWidth = self.materials[matNum]['kerf_width']
error = CIRCLE.preview(self, self.fTmp, self.fNgc, self.fNgcBkp, \
matNum, matNam, \
self.preAmble, self.postAmble, \
self.liValue.get(), self.loValue.get(), \
isCenter, self.xsValue.get(), self.ysValue.get(), \
kerfWidth, isExternal, \
isOvercut, self.ocValue.get(), \
self.smallHoleDia, self.smallHoleSpeed, \
self.dValue.get(), self.invalidLeads)
if error:
self.dialog_show_ok(_('Circle Error'), error)
else:
self.fileOpener(self.fNgc, True, False)
self.addC['state'] = 'normal'
self.undoC['state'] = 'normal'
self.preview_button_pressed(True)
def auto_preview(self, button=False):
if self.dValue.get():
preview(self)
def overcut_clicked(self):
if self.ocbValue.get() == _('OFF'):
self.ocbValue.set(_('ON'))
try:
lolen = float(self.loValue.get())
except:
lolen = 0
try:
dia = float(self.dValue.get())
except:
dia = 0
if (self.ctbValue.get() == _('EXTERNAL') and lolen) or not dia or dia > self.smallHoleDia:
return
else:
self.ocEntry['state'] = 'normal'
else:
self.ocbValue.set(_('OFF'))
def widgets(self):
if self.comp['development']:
reload(CIRCLE)
# start settings
if not self.settingsExited:
self.ocButton['state'] = 'disabled'
self.dValue.set('')
self.dLabel['text'] = _('DIAMETER')
#connections
self.ctButton['command'] = lambda:self.cut_type_clicked(True)
self.spButton['command'] = lambda:self.start_point_clicked()
self.ocButton['command'] = lambda:overcut_clicked(self)
self.previewC['command'] = lambda:preview(self)
#add to layout
self.matLabel.grid(column=0, row=0, pady=(4,0), sticky='e')
self.matCombo.grid(column=1, row=0, pady=(4,0), columnspan=3, sticky='ew')
self.spLabel.grid(column=0, row=1, pady=(4,0), sticky='e')
self.spButton.grid(column=1, row=1, pady=(4,0))
self.ctLabel.grid(column=2, row=1, pady=(4,0), sticky='e')
self.ctButton.grid(column=3, row=1, pady=(4,0))
self.xsLabel.grid(column=0, row=2, pady=(4,0), sticky='e')
self.xsEntry.grid(column=1, row=2, pady=(4,0))
self.ysLabel.grid(column=2, row=2, pady=(4,0), sticky='e')
self.ysEntry.grid(column=3, row=2, pady=(4,0))
self.liLabel.grid(column=0, row=3, pady=(4,0), sticky='e')
self.liEntry.grid(column=1, row=3, pady=(4,0))
self.loLabel.grid(column=2, row=3, pady=(4,0), sticky='e')
self.loEntry.grid(column=3, row=3, pady=(4,0))
self.dLabel.grid(column=0, row=4, pady=(4,0), sticky='e')
self.dEntry.grid(column=1, row=4, pady=(4,0))
self.ocLabel.grid(column=0, row=5, pady=(4,0), sticky='e')
self.ocEntry.grid(column=1, row=5, pady=(4,0))
self.ocButton.grid(column=2, row=5, pady=(4,0))
# finish setup
self.dEntry.focus()
self.settingsExited = False

View File

@@ -0,0 +1,97 @@
'''
conv_ellipse.py
Copyright (C) 2021, 2022 Phillip A Carter
Copyright (C) 2021, 2022 Gregory D Carl
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, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
'''
import os, sys
import gettext
from importlib import reload
from plasmac import ellipse as ELLIPSE
for f in sys.path:
if '/lib/python' in f:
if '/usr' in f:
localeDir = 'usr/share/locale'
else:
localeDir = os.path.join(f"{f.split('/lib')[0]}",'share','locale')
break
gettext.install('linuxcnc', localedir=localeDir)
def preview(self):
matNum = int(self.matCombo.get().split(':')[0])
matNam = self.matCombo.get().split(':')[1].strip()
isCenter = self.spbValue.get() == _('CENTER')
isExternal = self.ctbValue.get() == _('EXTERNAL')
kerfWidth = self.materials[matNum]['kerf_width']
error = ELLIPSE.preview(self, self.fTmp, self.fNgc, self.fNgcBkp, \
matNum, matNam, \
self.preAmble, self.postAmble, \
self.liValue.get(), self.loValue.get(), \
isCenter, self.xsValue.get(), self.ysValue.get(), \
kerfWidth, isExternal, \
self.wValue.get(), self.hValue.get(), self.aValue.get(), \
self.unitsPerMm)
if error:
self.dialog_show_ok(_('Ellipse Error'), error)
else:
self.fileOpener(self.fNgc, True, False)
self.addC['state'] = 'normal'
self.undoC['state'] = 'normal'
self.preview_button_pressed(True)
def auto_preview(self):
if self.wValue.get() and self.hValue.get():
preview(self)
def widgets(self):
if self.comp['development']:
reload(ELLIPSE)
# start settings
if not self.settingsExited:
self.wValue.set('')
self.hValue.set('')
self.aValue.set('')
#connections
self.ctButton['command'] = lambda:self.cut_type_clicked()
self.spButton['command'] = lambda:self.start_point_clicked()
self.previewC['command'] = lambda:preview(self)
#add to layout
self.matLabel.grid(column=0, row=0, pady=(4,0), sticky='e')
self.matCombo.grid(column=1, row=0, pady=(4,0), columnspan=3, sticky='ew')
self.spLabel.grid(column=0, row=1, pady=(4,0), sticky='e')
self.spButton.grid(column=1, row=1, pady=(4,0))
self.ctLabel.grid(column=2, row=1, pady=(4,0), sticky='e')
self.ctButton.grid(column=3, row=1, pady=(4,0))
self.xsLabel.grid(column=0, row=2, pady=(4,0), sticky='e')
self.xsEntry.grid(column=1, row=2, pady=(4,0))
self.ysLabel.grid(column=2, row=2, pady=(4,0), sticky='e')
self.ysEntry.grid(column=3, row=2, pady=(4,0))
self.liLabel.grid(column=0, row=3, pady=(4,0), sticky='e')
self.liEntry.grid(column=1, row=3, pady=(4,0))
self.loLabel.grid(column=2, row=3, pady=(4,0), sticky='e')
self.loEntry.grid(column=3, row=3, pady=(4,0))
self.wLabel.grid(column=0, row=4, pady=(4,0), sticky='e')
self.wEntry.grid(column=1, row=4, pady=(4,0))
self.hLabel.grid(column=0, row=5, pady=(4,0), sticky='e')
self.hEntry.grid(column=1, row=5, pady=(4,0))
self.aLabel.grid(column=0, row=6, pady=(4,0), sticky='e')
self.aEntry.grid(column=1, row=6, pady=(4,0))
# finish setup
self.wEntry.focus()
self.settingsExited = False

View File

@@ -0,0 +1,105 @@
'''
conv_gusset.py
Copyright (C) 2020, 2021, 2022 Phillip A Carter
Copyright (C) 2020, 2021, 2022 Gregory D Carl
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, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
'''
import os, sys
import gettext
from importlib import reload
from plasmac import gusset as GUSSET
for f in sys.path:
if '/lib/python' in f:
if '/usr' in f:
localeDir = 'usr/share/locale'
else:
localeDir = os.path.join(f"{f.split('/lib')[0]}",'share','locale')
break
gettext.install('linuxcnc', localedir=localeDir)
def preview(self):
matNum = int(self.matCombo.get().split(':')[0])
matNam = self.matCombo.get().split(':')[1].strip()
isExternal = self.ctbValue.get() == _('EXTERNAL')
kerfWidth = self.materials[matNum]['kerf_width']
error = GUSSET.preview(self, self.fTmp, self.fNgc, self.fNgcBkp, \
matNum, matNam, \
self.preAmble, self.postAmble, \
self.liValue.get(), self.loValue.get(), \
self.xsValue.get(), self.ysValue.get(), \
kerfWidth, isExternal, \
self.wValue.get(), self.hValue.get(), self.aValue.get(), \
self.rValue.get(), self.rbValue.get())
if error:
self.dialog_show_ok(_('Gusset Error'), error)
else:
self.fileOpener(self.fNgc, True, False)
self.addC['state'] = 'normal'
self.undoC['state'] = 'normal'
self.preview_button_pressed(True)
def auto_preview(self):
if self.wValue.get() and self.hValue.get() and self.aValue.get():
preview(self)
def radius_button_pressed(self, value):
if value.get().split()[0] == _('RADIUS'):
text = _('CHAMFER')
else:
text = _('RADIUS')
value.set(text)
auto_preview(self)
def widgets(self):
if self.comp['development']:
reload(GUSSET)
# start settings
if not self.settingsExited:
self.wValue.set('')
self.hValue.set('')
self.rValue.set('')
self.aValue.set('90')
#connections
self.ctButton['command'] = lambda:self.cut_type_clicked()
self.previewC['command'] = lambda:preview(self)
self.rButton['command'] = lambda:radius_button_pressed(self, self.rbValue)
#add to layout
self.matLabel.grid(column=0, row=0, pady=(4,0), sticky='e')
self.matCombo.grid(column=1, row=0, pady=(4,0), columnspan=3, sticky='ew')
self.ctLabel.grid(column=2, row=1, pady=(4,0), sticky='e')
self.ctButton.grid(column=3, row=1, pady=(4,0))
self.xsLabel.grid(column=0, row=2, pady=(4,0), sticky='e')
self.xsEntry.grid(column=1, row=2, pady=(4,0))
self.ysLabel.grid(column=2, row=2, pady=(4,0), sticky='e')
self.ysEntry.grid(column=3, row=2, pady=(4,0))
self.liLabel.grid(column=0, row=3, pady=(4,0), sticky='e')
self.liEntry.grid(column=1, row=3, pady=(4,0))
self.loLabel.grid(column=2, row=3, pady=(4,0), sticky='e')
self.loEntry.grid(column=3, row=3, pady=(4,0))
self.wLabel.grid(column=0, row=4, pady=(4,0), sticky='e')
self.wEntry.grid(column=1, row=4, pady=(4,0))
self.hLabel.grid(column=0, row=5, pady=(4,0), sticky='e')
self.hEntry.grid(column=1, row=5, pady=(4,0))
self.rButton.grid(column=0, row=6, pady=(4,0))
self.rEntry.grid(column=1, row=6, pady=(4,0))
self.aLabel.grid(column=0, row=7, pady=(4,0), sticky='e')
self.aEntry.grid(column=1, row=7, pady=(4,0))
# finish setup
self.wEntry.focus()
self.settingsExited = False

View File

@@ -0,0 +1,258 @@
'''
conv_line.py
Copyright (C) 2020, 2021, 2022 Phillip A Carter
Copyright (C) 2020, 2021, 2022 Gregory D Carl
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, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
'''
import os, sys
import gettext
from importlib import reload
from plasmac import line as LINE
for f in sys.path:
if '/lib/python' in f:
if '/usr' in f:
localeDir = 'usr/share/locale'
else:
localeDir = os.path.join(f"{f.split('/lib')[0]}",'share','locale')
break
gettext.install('linuxcnc', localedir=localeDir)
def preview(self):
if self.convLine['xLineEnd'] != self.conv_is_float(self.l1Value.get()) or \
self.convLine['yLineEnd'] != self.conv_is_float(self.l2Value.get()):
self.convLine['addSegment'] = 0
if self.lineCombo.get() == _('LINE POINT ~ POINT'):
error = LINE.do_line_point_to_point(self, self.l1Value.get(), self.l2Value.get(), \
self.l3Value.get(), self.l4Value.get())
if not error[0]:
self.convLine['xLineEnd'] = error[1]
self.convLine['yLineEnd'] = error[2]
self.convLine['gcodeLine'] = error[3]
else:
error_set(self, f'{error[1]}\n')
return
elif self.lineCombo.get() == _('LINE BY ANGLE'):
error = LINE.do_line_by_angle(self, self.l1Value.get(), self.l2Value.get(), \
self.l3Value.get(), self.l4Value.get())
if not error[0]:
self.convLine['xLineEnd'] = error[1]
self.convLine['yLineEnd'] = error[2]
self.convLine['gcodeLine'] = error[3]
else:
error_set(self, f'{error[1]}\n')
return
elif self.lineCombo.get() == _('ARC 3P'):
error = LINE.do_arc_3_points(self, self.l1Value.get(), self.l2Value.get(), \
self.l3Value.get(), self.l4Value.get(), \
self.l5Value.get(), self.l6Value.get())
if not error[0]:
self.convLine['xLineEnd'] = error[1]
self.convLine['yLineEnd'] = error[2]
self.convLine['gcodeLine'] = error[3]
else:
error_set(self, f'{error[1]}\n')
return
elif self.lineCombo.get() == _('ARC 2P +RADIUS'):
arcType = '3' if 'CCW' in self.g23bValue.get() else '2'
error = LINE.do_arc_2_points_radius(self, self.l1Value.get(), self.l2Value.get(), self.l3Value.get(), \
self.l4Value.get(), self.l5Value.get(), arcType)
if not error[0]:
self.convLine['xLineEnd'] = error[1]
self.convLine['yLineEnd'] = error[2]
self.convLine['gcodeLine'] = error[3]
else:
error_set(self, f'{error[1]}\n')
return
elif self.lineCombo.get() == _('ARC ANGLE +RADIUS'):
arcType = '3' if 'CCW' in self.g23bValue.get() else '2'
error = LINE.do_arc_by_angle_radius(self, self.l1Value.get(), self.l2Value.get(), self.l3Value.get(),
self.l4Value.get(), self.l5Value.get(), arcType)
if not error[0]:
self.convLine['xLineEnd'] = error[1]
self.convLine['yLineEnd'] = error[2]
self.convLine['gcodeLine'] = error[3]
else:
error_set(self, f'{error[1]}\n')
return
if self.convLine['addSegment'] == 1:
LINE.next_segment(self.fTmp, self.fNgc)
else:
valid, self.convLine['xLineStart'] = self.conv_is_float(self.l1Value.get())
valid, self.convLine['yLineStart'] = self.conv_is_float(self.l2Value.get())
LINE.first_segment(self.fTmp, self.fNgc, self.fNgcBkp, self.preAmble, \
self.lineCombo.get(), self.convLine['xLineStart'], self.convLine['yLineStart'], \
int(self.matCombo.get().split(':')[0]), \
self.matCombo.get().split(':')[1].strip())
LINE.last_segment(self.fTmp, self.fNgc, self.convLine['gcodeLine'], self.postAmble)
self.fileOpener(self.fNgc, True, False)
self.addC['state'] = 'normal'
self.undoC['state'] = 'normal'
self.preview_button_pressed(True)
if self.convLine['addSegment'] == 1:
self.convLine['addSegment'] = 2
self.previewActive = True
def auto_preview(self):
if self.l1Value.get() and self.l2Value.get() and self.l3Value.get() and self.l4Value.get():
if self.lineCombo.get() == _('LINE POINT ~ POINT') or \
self.lineCombo.get() == _('LINE BY ANGLE') or \
(self.lineCombo.get() == _('ARC 3P') and self.l5Value.get() and self.l6Value.get()) or \
(self.lineCombo.get() == _('ARC 2P +RADIUS') and self.l5Value.get()) or \
(self.lineCombo.get() == _('ARC ANGLE +RADIUS') and self.l5Value.get()):
preview(self)
def arc_type_changed(self):
text = 'CW - G2' if 'CCW' in self.g23bValue.get() else 'CCW - G3'
self.g23bValue.set(text)
auto_preview(self)
def line_type_changed(self, refresh):
# self.lineCombo.selection_clear()
if self.lineCombo.get() == _('LINE POINT ~ POINT'):
if not refresh:
set_line_point_to_point(self)
elif self.lineCombo.get() == _('LINE BY ANGLE'):
if not refresh:
set_line_by_angle(self)
elif self.lineCombo.get() == _('ARC 3P'):
if not refresh:
set_arc_3_points(self)
elif self.lineCombo.get() == _('ARC 2P +RADIUS'):
if not refresh:
set_arc_2_points_radius(self)
elif self.lineCombo.get() == _('ARC ANGLE +RADIUS'):
if not refresh:
set_arc_by_angle_radius(self)
self.l3Entry.focus()
def clear_widgets(self):
set_start_point(self)
for w in [self.l3Label, self.l4Label, self.l5Label, self.l6Label, ]:
w['text'] = ''
for w in [self.l3Entry, self.l4Entry, self.l5Entry, self.l6Entry, ]:
w.grid_remove()
self.g23Arc.grid_remove()
def set_start_point(self):
text = _('START')
self.l1Label['text'] = _('X START')
self.l1Value.set(f'{self.convLine["xLineStart"]:0.3f}')
self.l2Label['text'] = _('Y START')
self.l2Value.set(f'{self.convLine["yLineStart"]:0.3f}')
def set_line_point_to_point(self):
clear_widgets(self)
self.l3Label['text'] = _('X END')
self.l4Label['text'] = _('Y END')
for w in [self.l3Value, self.l4Value]:
w.set('')
self.l3Entry.grid(column=1, row=4, pady=(24,0))
self.l4Entry.grid(column=1, row=5, pady=(4,0))
def set_line_by_angle(self):
clear_widgets(self)
self.l3Label['text'] = _('LENGTH')
self.l4Label['text'] = _('ANGLE')
self.l4Value.set('0.000')
for w in [self.l3Value, self.l4Value]:
w.set('')
self.l3Entry.grid(column=1, row=4, pady=(24,0))
self.l4Entry.grid(column=1, row=5, pady=(4,0))
def set_arc_3_points(self):
clear_widgets(self)
self.l3Label['text'] = _('X NEXT')
self.l4Label['text'] = _('Y NEXT')
self.l5Label['text'] = _('X END')
self.l6Label['text'] = _('Y END')
for w in [self.l3Value, self.l4Value, self.l5Value, self.l6Value]:
w.set('')
self.l3Entry.grid(column=1, row=4, pady=(24,0))
self.l4Entry.grid(column=1, row=5, pady=(4,0))
self.l5Entry.grid(column=1, row=6, pady=(24,0))
self.l6Entry.grid(column=1, row=7, pady=(4,0))
def set_arc_2_points_radius(self):
clear_widgets(self)
self.l3Label['text'] = _('X END')
self.l4Label['text'] = _('Y END')
self.l5Label['text'] = _('RADIUS')
self.l5Value.set('0.000')
self.l6Label['text'] = _('DIRECTION')
for w in [self.l3Value, self.l4Value, self.l5Value]:
w.set('')
self.l3Entry.grid(column=1, row=4, pady=(24,0))
self.l4Entry.grid(column=1, row=5, pady=(4,0))
self.l5Entry.grid(column=1, row=6, pady=(24,0))
self.g23Arc.grid(column=1, row=7, pady=(4,0))
def set_arc_by_angle_radius(self):
clear_widgets(self)
self.l3Label['text'] = _('LENGTH')
self.l4Label['text'] = _('ANGLE')
self.l4Value.set('0.000')
self.l5Label['text'] = _('RADIUS')
self.l6Label['text'] = _('DIRECTION')
for w in [self.l3Value, self.l4Value, self.l5Value]:
w.set('')
self.l3Entry.grid(column=1, row=4, pady=(24,0))
self.l4Entry.grid(column=1, row=5, pady=(4,0))
self.l5Entry.grid(column=1, row=6, pady=(24,0))
self.g23Arc.grid(column=1, row=7, pady=(4,0))
def error_set(self, error):
self.dialog_show_ok(_('Line Error'), error)
def widgets(self):
if self.comp['development']:
reload(LINE)
# start settings
self.previewActive = False
if not self.settingsExited:
self.dValue.set('')
self.convLine['xLineStart'] = 0.0
self.convLine['yLineStart'] = 0.0
self.convLine['addSegment'] = 0
self.convLine['gcodeSave'] = ''
self.dLabel['text'] = _('DIAMETER')
#connections
self.previewC['command'] = lambda:preview(self)
self.g23Arc['command'] = lambda:arc_type_changed(self)
self.lineCombo['modifycmd'] = lambda:line_type_changed(self, False)
#add to layout
self.matLabel.grid(column=0, row=0, pady=(4,0), sticky='e')
self.matCombo.grid(column=1, row=0, padx=(4,0), pady=(4,0), columnspan=3, sticky='ew')
self.lnLabel.grid(column=0, row=1, pady=(4,0), sticky='e')
self.lineCombo.grid(column=1, row=1, padx=(4,0), pady=(4,0), columnspan=2, sticky='ew')
self.l1Label.grid(column=0, row=2, pady=(4,0), sticky='e')
self.l1Entry.grid(column=1, row=2, pady=(4,0))
self.l2Label.grid(column=0, row=3, pady=(4,0), sticky='e')
self.l2Entry.grid(column=1, row=3, pady=(4,0))
self.l3Label.grid(column=0, row=4, pady=(24,0), sticky='e')
self.l3Entry.grid(column=1, row=4, pady=(4,0))
self.l4Label.grid(column=0, row=5, pady=(4,0), sticky='e')
self.l4Entry.grid(column=1, row=5, pady=(4,0))
self.l5Label.grid(column=0, row=6, pady=(24,0), sticky='e')
self.l5Entry.grid(column=1, row=6, pady=(4,0))
self.l6Label.grid(column=0, row=7, pady=(4,0), sticky='e')
self.l6Entry.grid(column=1, row=7, pady=(4,0))
# finish setup
if not self.settingsExited:
line_type_changed(self, False)
self.settingsExited = False

View File

@@ -0,0 +1,112 @@
'''
conv_polygon.py
Copyright (C) 2020, 2021, 2022 Phillip A Carter
Copyright (C) 2020, 2021, 2022 Gregory D Carl
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, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
'''
import os, sys
import gettext
from importlib import reload
from plasmac import polygon as POLYGON
for f in sys.path:
if '/lib/python' in f:
if '/usr' in f:
localeDir = 'usr/share/locale'
else:
localeDir = os.path.join(f"{f.split('/lib')[0]}",'share','locale')
break
gettext.install('linuxcnc', localedir=localeDir)
def preview(self):
matNum = int(self.matCombo.get().split(':')[0])
matNam = self.matCombo.get().split(':')[1].strip()
isCenter = self.spbValue.get() == _('CENTER')
isExternal = self.ctbValue.get() == _('EXTERNAL')
kerfWidth = self.materials[matNum]['kerf_width']
error = POLYGON.preview(self, self.fTmp, self.fNgc, self.fNgcBkp, \
matNum, matNam, \
self.preAmble, self.postAmble, \
self.liValue.get(), self.loValue.get(), \
isCenter, self.xsValue.get(), self.ysValue.get(), \
kerfWidth, isExternal, \
self.sValue.get(), self.dValue.get(), self.aValue.get(), \
self.polyCombo.getvalue(), self.dLabel['text'])
if error:
self.dialog_show_ok(_('Polygon Error'), error)
else:
self.fileOpener(self.fNgc, True, False)
self.addC['state'] = 'normal'
self.undoC['state'] = 'normal'
self.preview_button_pressed(True)
def auto_preview(self):
if self.sValue.get() and self.dValue.get():
preview(self)
def mode_changed(self):
# self.polyCombo.selection_clear()
if self.polyCombo.get() == _('SIDE LENGTH'):
self.dLabel['text'] = _('LENGTH')
else:
self.dLabel['text'] = _('DIAMETER')
auto_preview(self)
def widgets(self):
if self.comp['development']:
reload(POLYGON)
# start settings
if not self.settingsExited:
self.sValue.set('')
self.dValue.set('')
self.aValue.set('')
if self.polyCombo.get() == _('SIDE LENGTH'):
self.dLabel['text'] = _('LENGTH')
else:
self.dLabel['text'] = _('DIAMETER')
#connections
self.ctButton['command'] = lambda:self.cut_type_clicked()
self.spButton['command'] = lambda:self.start_point_clicked()
self.previewC['command'] = lambda:preview(self)
self.polyCombo['modifycmd'] = lambda:mode_changed(self)
#add to layout
self.matLabel.grid(column=0, row=0, pady=(4,0), sticky='e')
self.matCombo.grid(column=1, row=0, pady=(4,0), columnspan=3, sticky='ew')
self.spLabel.grid(column=0, row=1, pady=(4,0), sticky='e')
self.spButton.grid(column=1, row=1, pady=(4,0))
self.ctLabel.grid(column=2, row=1, pady=(4,0), sticky='e')
self.ctButton.grid(column=3, row=1, pady=(4,0))
self.xsLabel.grid(column=0, row=2, pady=(4,0), sticky='e')
self.xsEntry.grid(column=1, row=2, pady=(4,0))
self.ysLabel.grid(column=2, row=2, pady=(4,0), sticky='e')
self.ysEntry.grid(column=3, row=2, pady=(4,0))
self.liLabel.grid(column=0, row=3, pady=(4,0), sticky='e')
self.liEntry.grid(column=1, row=3, pady=(4,0))
self.loLabel.grid(column=2, row=3, pady=(4,0), sticky='e')
self.loEntry.grid(column=3, row=3, pady=(4,0))
self.polyLabel.grid(column=0, row=4, pady=(4,0), sticky='e')
self.polyCombo.grid(column=1, row=4, padx=(4,0), pady=(4,0), columnspan=2, sticky='ew')
self.sLabel.grid(column=0, row=5, pady=(4,0), sticky='e')
self.sEntry.grid(column=1, row=5, pady=(4,0))
self.dLabel.grid(column=0, row=6, pady=(4,0), sticky='e')
self.dEntry.grid(column=1, row=6, pady=(4,0))
self.aLabel.grid(column=0, row=7, pady=(4,0), sticky='e')
self.aEntry.grid(column=1, row=7, pady=(4,0))
# finish setup
self.sEntry.focus()
self.settingsExited = False

View File

@@ -0,0 +1,138 @@
'''
conv_rectangle.py
Copyright (C) 2020, 2021, 2022 Phillip A Carter
Copyright (C) 2020, 2021, 2022 Gregory D Carl
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, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
'''
import os, sys
import gettext
from importlib import reload
from plasmac import rectangle as RECTANGLE
for f in sys.path:
if '/lib/python' in f:
if '/usr' in f:
localeDir = 'usr/share/locale'
else:
localeDir = os.path.join(f"{f.split('/lib')[0]}",'share','locale')
break
gettext.install('linuxcnc', localedir=localeDir)
def preview(self):
matNum = int(self.matCombo.get().split(':')[0])
matNam = self.matCombo.get().split(':')[1].strip()
isCenter = self.spbValue.get() == _('CENTER')
isExternal = self.ctbValue.get() == _('EXTERNAL')
isOvercut = self.ocButton['state'] == 'normal' and self.ocbValue.get() == _('ON')
kerfWidth = self.materials[matNum]['kerf_width']
styles = [None, 'extRadius', 'extRadius', 'extRadius', 'extRadius']
values = [None, self.r1bValue.get(), self.r2bValue.get(), self.r3bValue.get(), self.r4bValue.get()]
for n in range(1, 5):
if values[n].startswith(_('CHAMFER')):
styles[n] = 'chamfer'
elif values[n].startswith(_('iRADIUS')):
styles[n] = 'intRadius'
error = RECTANGLE.preview(self, self.fTmp, self.fNgc, self.fNgcBkp, \
matNum, matNam, \
self.preAmble, self.postAmble, \
self.liValue.get(), self.loValue.get(), \
isCenter, self.xsValue.get(), self.ysValue.get(), \
kerfWidth, isExternal, \
self.wValue.get(), self.hValue.get(), self.aValue.get(), \
styles[1], styles[2], styles[3], styles[4], \
self.r1Value.get(), self.r2Value.get(), self.r3Value.get(), self.r4Value.get(),
self.r1bValue.get(), self.r2bValue.get(), self.r3bValue.get(), self.r4bValue.get())
if error:
self.dialog_show_ok(_('Rectangle Error'), error)
else:
self.fileOpener(self.fNgc, True, False)
self.addC['state'] = 'normal'
self.undoC['state'] = 'normal'
self.preview_button_pressed(True)
def auto_preview(self):
if self.wValue.get() and self.hValue.get():
preview(self)
def radius_button_pressed(self, value, sequence):
if value.get().split()[0] == _('RADIUS'):
text = _('CHAMFER')
elif value.get().split()[0] == _('CHAMFER'):
text = _('iRADIUS')
else:
text = _('RADIUS')
value.set(f'{text} {sequence}')
auto_preview(self)
def widgets(self):
if self.comp['development']:
reload(RECTANGLE)
# start settings
if not self.settingsExited:
self.wValue.set('')
self.hValue.set('')
self.aValue.set('')
self.r1Value.set('')
self.r1bValue.set(_('RADIUS 1'))
self.r2Value.set('')
self.r2bValue.set(_('RADIUS 2'))
self.r3Value.set('')
self.r3bValue.set(_('RADIUS 3'))
self.r4Value.set('')
self.r4bValue.set(_('RADIUS 4'))
#connections
self.ctButton['command'] = lambda:self.cut_type_clicked()
self.spButton['command'] = lambda:self.start_point_clicked()
self.previewC['command'] = lambda:preview(self)
self.r1Button['command'] = lambda:radius_button_pressed(self, self.r1bValue, '1')
self.r2Button['command'] = lambda:radius_button_pressed(self, self.r2bValue, '2')
self.r3Button['command'] = lambda:radius_button_pressed(self, self.r3bValue, '3')
self.r4Button['command'] = lambda:radius_button_pressed(self, self.r4bValue, '4')
#add to layout
self.matLabel.grid(column=0, row=0, pady=(4,0), sticky='e')
self.matCombo.grid(column=1, row=0, pady=(4,0), columnspan=3, sticky='ew')
self.spLabel.grid(column=0, row=1, pady=(4,0), sticky='e')
self.spButton.grid(column=1, row=1, pady=(4,0))
self.ctLabel.grid(column=2, row=1, pady=(4,0), sticky='e')
self.ctButton.grid(column=3, row=1, pady=(4,0))
self.xsLabel.grid(column=0, row=2, pady=(4,0), sticky='e')
self.xsEntry.grid(column=1, row=2, pady=(4,0))
self.ysLabel.grid(column=2, row=2, pady=(4,0), sticky='e')
self.ysEntry.grid(column=3, row=2, pady=(4,0))
self.liLabel.grid(column=0, row=3, pady=(4,0), sticky='e')
self.liEntry.grid(column=1, row=3, pady=(4,0))
self.loLabel.grid(column=2, row=3, pady=(4,0), sticky='e')
self.loEntry.grid(column=3, row=3, pady=(4,0))
self.wLabel.grid(column=0, row=4, pady=(4,0), sticky='e')
self.wEntry.grid(column=1, row=4, pady=(4,0))
self.hLabel.grid(column=2, row=4, pady=(4,0), sticky='e')
self.hEntry.grid(column=3, row=4, pady=(4,0))
self.aLabel.grid(column=0, row=5, pady=(4,0), sticky='e')
self.aEntry.grid(column=1, row=5, pady=(4,0))
self.r1Button.grid(column=0, row=6, pady=(4,0), sticky='e')
self.r1Entry.grid(column=1, row=6, pady=(4,0))
self.r2Button.grid(column=2, row=6, pady=(4,0), sticky='e')
self.r2Entry.grid(column=3, row=6, pady=(4,0))
self.r3Button.grid(column=0, row=7, pady=(4,0), sticky='e')
self.r3Entry.grid(column=1, row=7, pady=(4,0))
self.r4Button.grid(column=2, row=7, pady=(4,0), sticky='e')
self.r4Entry.grid(column=3, row=7, pady=(4,0))
# finish setup
self.wEntry.focus()
self.settingsExited = False

View File

@@ -0,0 +1,92 @@
'''
conv_sector.py
Copyright (C) 2020, 2021, 2022 Phillip A Carter
Copyright (C) 2020, 2021, 2022 Gregory D Carl
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, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
'''
import os, sys
import gettext
from importlib import reload
from plasmac import sector as SECTOR
for f in sys.path:
if '/lib/python' in f:
if '/usr' in f:
localeDir = 'usr/share/locale'
else:
localeDir = os.path.join(f"{f.split('/lib')[0]}",'share','locale')
break
gettext.install('linuxcnc', localedir=localeDir)
def preview(self):
matNum = int(self.matCombo.get().split(':')[0])
matNam = self.matCombo.get().split(':')[1].strip()
isExternal = self.ctbValue.get() == _('EXTERNAL')
kerfWidth = self.materials[matNum]['kerf_width']
error = SECTOR.preview(self, self.fTmp, self.fNgc, self.fNgcBkp, \
matNum, matNam, \
self.preAmble, self.postAmble, \
self.liValue.get(), self.loValue.get(), \
self.xsValue.get(), self.ysValue.get(), \
kerfWidth, isExternal, \
self.rValue.get(), self.saValue.get(), self.aValue.get())
if error:
self.dialog_show_ok(_('Sector Error'), error)
else:
self.fileOpener(self.fNgc, True, False)
self.addC['state'] = 'normal'
self.undoC['state'] = 'normal'
self.preview_button_pressed(True)
def auto_preview(self):
if self.rValue.get() and self.saValue.get():
preview(self)
def widgets(self):
if self.comp['development']:
reload(SECTOR)
# start settings
if not self.settingsExited:
self.rValue.set('')
self.saValue.set('')
self.aValue.set('')
# connections
self.ctButton['command'] = lambda:self.cut_type_clicked()
self.previewC['command'] = lambda:preview(self)
#add to layout
self.matLabel.grid(column=0, row=0, pady=(4,0), sticky='e')
self.matCombo.grid(column=1, row=0, pady=(4,0), columnspan=3, sticky='ew')
self.ctLabel.grid(column=2, row=1, pady=(4,0), sticky='e')
self.ctButton.grid(column=3, row=1, pady=(4,0))
self.xsLabel.grid(column=0, row=2, pady=(4,0), sticky='e')
self.xsEntry.grid(column=1, row=2, pady=(4,0))
self.ysLabel.grid(column=2, row=2, pady=(4,0), sticky='e')
self.ysEntry.grid(column=3, row=2, pady=(4,0))
self.liLabel.grid(column=0, row=3, pady=(4,0), sticky='e')
self.liEntry.grid(column=1, row=3, pady=(4,0))
self.loLabel.grid(column=2, row=3, pady=(4,0), sticky='e')
self.loEntry.grid(column=3, row=3, pady=(4,0))
self.rLabel.grid(column=0, row=4, pady=(4,0), sticky='e')
self.rEntry.grid(column=1, row=4, pady=(4,0))
self.saLabel.grid(column=0, row=5, pady=(4,0), sticky='e')
self.saEntry.grid(column=1, row=5, pady=(4,0))
self.aLabel.grid(column=0, row=6, pady=(4,0), sticky='e')
self.aEntry.grid(column=1, row=6, pady=(4,0))
# finish setup
self.rEntry.focus()
self.settingsExited = False

View File

@@ -0,0 +1,140 @@
'''
conv_settings.py
Copyright (C) 2020, 2021, 2022 Phillip A Carter
Copyright (C) 2020, 2021, 2022 Gregory D Carl
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, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
'''
import os, sys
import gettext
for f in sys.path:
if '/lib/python' in f:
if '/usr' in f:
localeDir = 'usr/share/locale'
else:
localeDir = os.path.join(f"{f.split('/lib')[0]}",'share','locale')
break
gettext.install('linuxcnc', localedir=localeDir)
def save_clicked(self):
msg = []
self.preAmble = self.preValue.get()
self.postAmble = self.pstValue.get()
self.origin = self.spbValue.get() == 'CENTER'
error = ''
valid, self.leadIn = self.conv_is_float(self.liValue.get())
if not valid:
msg = _('Invalid LEAD IN entry detected')
error += f"{msg}\n\n"
valid, self.leadOut = self.conv_is_float(self.loValue.get())
if not valid:
msg = _('Invalid LEAD OUT entry detected')
error += f"{msg}\n\n"
valid, self.smallHoleDia = self.conv_is_float(self.shValue.get())
if not valid:
msg = _('Invalid DIAMETER entry detected')
error += f"{msg}\n\n"
valid, self.smallHoleSpeed = self.conv_is_int(self.hsValue.get())
if not valid:
msg = _('Invalid SPEED % entry detected')
error += f"{msg}\n\n"
if error:
self.dialog_show_ok(_('Settings Error'), error)
return
self.putPrefs(self.prefs, 'CONVERSATIONAL', 'Preamble', self.preAmble, str)
self.putPrefs(self.prefs, 'CONVERSATIONAL', 'Postamble', self.postAmble, str)
self.putPrefs(self.prefs, 'CONVERSATIONAL', 'Origin', self.origin, int)
self.putPrefs(self.prefs, 'CONVERSATIONAL', 'Leadin', self.leadIn, float)
self.putPrefs(self.prefs, 'CONVERSATIONAL', 'Leadout', self.leadOut, float)
self.putPrefs(self.prefs, 'CONVERSATIONAL', 'Hole diameter', self.smallHoleDia, float)
self.putPrefs(self.prefs, 'CONVERSATIONAL', 'Hole speed', self.smallHoleSpeed, int)
self.savedSettings['lead_in'] = self.liValue.get()
self.savedSettings['lead_out'] = self.loValue.get()
self.savedSettings['start_pos'] = self.spbValue.get()
self.settingsExited = 1
def reload_clicked(self):
load(self, self.preAmble, self.leadIn, self.smallHoleDia, self.postAmble)
show(self)
if not self.settingsExited:
self.settingsExited = 2
def exit_clicked(self):
for child in self.toolFrame.winfo_children():
if child.winfo_class() == 'Radiobutton':
child['state'] = 'normal'
self.restore_buttons()
if not self.settingsExited:
self.settingsExited = 3
self.shape_request(self.oldConvButton)
def load(self, preAmble, leadin, smallHole, postAmble=None):
postAmble = postAmble if postAmble else preAmble
self.preAmble = self.getPrefs(self.prefs, 'CONVERSATIONAL', 'Preamble', preAmble, str)
self.postAmble = self.getPrefs(self.prefs, 'CONVERSATIONAL', 'Postamble', postAmble, str)
self.origin = self.getPrefs(self.prefs, 'CONVERSATIONAL', 'Origin', 0, int)
self.leadIn = self.getPrefs(self.prefs, 'CONVERSATIONAL', 'Leadin', leadin, float)
self.leadOut = self.getPrefs(self.prefs, 'CONVERSATIONAL', 'Leadout', 0, float)
self.smallHoleDia = self.getPrefs(self.prefs, 'CONVERSATIONAL', 'Hole diameter', smallHole, float)
self.smallHoleSpeed = self.getPrefs(self.prefs, 'CONVERSATIONAL', 'Hole speed', 60, int)
def show(self):
self.preValue.set(self.preAmble)
self.pstValue.set(self.postAmble)
self.liValue.set(self.leadIn)
self.loValue.set(self.leadOut)
self.shValue.set(f"{self.smallHoleDia}")
self.hsValue.set(f"{self.smallHoleSpeed}")
if self.origin:
self.spbValue.set('CENTER')
else:
self.spbValue.set('BTM LEFT')
def widgets(self):
# connections
self.spButton['command'] = lambda:self.start_point_clicked()
self.saveS['command'] = lambda:save_clicked(self)
self.reloadS['command'] = lambda:reload_clicked(self)
self.exitS['command'] = lambda:exit_clicked(self)
# remove common widgets
self.previewC.grid_remove()
self.addC.grid_remove()
self.undoC.grid_remove()
# add to layout
self.preLabel.grid(column=0, row=0, pady=(4,0), sticky='e')
self.preEntry.grid(column=1, row=0, pady=(4,0), sticky='ew', columnspan=3)
self.pstLabel.grid(column=0, row=1, pady=(4,0), sticky='e')
self.pstEntry.grid(column=1, row=1, pady=(4,0), sticky='ew', columnspan=3)
self.llLabel.grid(column=0, row=2, pady=(4,0), sticky='ew', columnspan=4)
self.liLabel.grid(column=0, row=3, pady=(4,0), sticky='e')
self.liEntry.grid(column=1, row=3, pady=(4,0), sticky='w')
self.loLabel.grid(column=2, row=3, pady=(4,0), sticky='e')
self.loEntry.grid(column=3, row=3, pady=(4,0), sticky='w')
self.shLabel.grid(column=0, row=4, pady=(4,0), sticky='ew', columnspan=4)
self.dLabel.grid(column=0, row=5, pady=(4,0), sticky='e')
self.shEntry.grid(column=1, row=5, pady=(4,0), sticky='w')
self.hsLabel.grid(column=2, row=5, pady=(4,0), sticky='e')
self.hsEntry.grid(column=3, row=5, pady=(4,0), sticky='w')
self.pvLabel.grid(column=0, row=6, pady=(4,0), sticky='ew', columnspan=4)
self.spLabel.grid(column=0, row=7, pady=(4,0), sticky='e')
self.spButton.grid(column=1, row=7, pady=(4,0), sticky='w')
self.saveS.grid(column=0, row=12)
self.reloadS.grid(column=1, row=12, columnspan=2)
self.exitS.grid(column=3, row=12)
# finish setup
self.preEntry.focus()

View File

@@ -0,0 +1,96 @@
'''
conv_slot.py
Copyright (C) 2020, 2021, 2022 Phillip A Carter
Copyright (C) 2020, 2021, 2022 Gregory D Carl
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, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
'''
import os, sys
import gettext
from importlib import reload
from plasmac import slot as SLOT
for f in sys.path:
if '/lib/python' in f:
if '/usr' in f:
localeDir = 'usr/share/locale'
else:
localeDir = os.path.join(f"{f.split('/lib')[0]}",'share','locale')
break
gettext.install('linuxcnc', localedir=localeDir)
def preview(self):
matNum = int(self.matCombo.get().split(':')[0])
matNam = self.matCombo.get().split(':')[1].strip()
isCenter = self.spbValue.get() == _('CENTER')
isExternal = self.ctbValue.get() == _('EXTERNAL')
kerfWidth = self.materials[matNum]['kerf_width']
error = SLOT.preview(self, self.fTmp, self.fNgc, self.fNgcBkp, \
matNum, matNam, \
self.preAmble, self.postAmble, \
self.liValue.get(), self.loValue.get(), \
isCenter, self.xsValue.get(), self.ysValue.get(), \
kerfWidth, isExternal, \
self.lValue.get(), self.wValue.get(), self.aValue.get())
if error:
self.dialog_show_ok(_('Slot Error'), error)
else:
self.fileOpener(self.fNgc, True, False)
self.addC['state'] = 'normal'
self.undoC['state'] = 'normal'
self.preview_button_pressed(True)
def auto_preview(self):
if self.lValue.get() and self.wValue.get():
preview(self)
def widgets(self):
if self.comp['development']:
reload(SLOT)
# start settings
if not self.settingsExited:
self.lValue.set('')
self.wValue.set('')
self.aValue.set('')
#connections
self.ctButton['command'] = lambda:self.cut_type_clicked()
self.spButton['command'] = lambda:self.start_point_clicked()
self.previewC['command'] = lambda:preview(self)
#add to layout
self.matLabel.grid(column=0, row=0, pady=(4,0), sticky='e')
self.matCombo.grid(column=1, row=0, pady=(4,0), columnspan=3, sticky='ew')
self.spLabel.grid(column=0, row=1, pady=(4,0), sticky='e')
self.spButton.grid(column=1, row=1, pady=(4,0))
self.ctLabel.grid(column=2, row=1, pady=(4,0), sticky='e')
self.ctButton.grid(column=3, row=1, pady=(4,0))
self.xsLabel.grid(column=0, row=2, pady=(4,0), sticky='e')
self.xsEntry.grid(column=1, row=2, pady=(4,0))
self.ysLabel.grid(column=2, row=2, pady=(4,0), sticky='e')
self.ysEntry.grid(column=3, row=2, pady=(4,0))
self.liLabel.grid(column=0, row=3, pady=(4,0), sticky='e')
self.liEntry.grid(column=1, row=3, pady=(4,0))
self.loLabel.grid(column=2, row=3, pady=(4,0), sticky='e')
self.loEntry.grid(column=3, row=3, pady=(4,0))
self.lLabel.grid(column=0, row=4, pady=(4,0), sticky='e')
self.lEntry.grid(column=1, row=4, pady=(4,0))
self.wLabel.grid(column=0, row=5, pady=(4,0), sticky='e')
self.wEntry.grid(column=1, row=5, pady=(4,0))
self.aLabel.grid(column=0, row=6, pady=(4,0), sticky='e')
self.aEntry.grid(column=1, row=6, pady=(4,0))
# finish setup
self.lEntry.focus()
self.settingsExited = False

View File

@@ -0,0 +1,99 @@
'''
conv_star.py
Copyright (C) 2020, 2021, 2022 Phillip A Carter
Copyright (C) 2020, 2021, 2022 Gregory D Carl
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, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
'''
import os, sys
import gettext
from importlib import reload
from plasmac import star as STAR
for f in sys.path:
if '/lib/python' in f:
if '/usr' in f:
localeDir = 'usr/share/locale'
else:
localeDir = os.path.join(f"{f.split('/lib')[0]}",'share','locale')
break
gettext.install('linuxcnc', localedir=localeDir)
def preview(self):
matNum = int(self.matCombo.get().split(':')[0])
matNam = self.matCombo.get().split(':')[1].strip()
isCenter = self.spbValue.get() == _('CENTER')
isExternal = self.ctbValue.get() == _('EXTERNAL')
kerfWidth = self.materials[matNum]['kerf_width']
error = STAR.preview(self, self.fTmp, self.fNgc, self.fNgcBkp, \
matNum, matNam, \
self.preAmble, self.postAmble, \
self.liValue.get(), self.loValue.get(), \
isCenter, self.xsValue.get(), self.ysValue.get(), \
kerfWidth, isExternal, \
self.pValue.get(), self.odValue.get(), self.idValue.get(), self.aValue.get())
if error:
self.dialog_show_ok(_('Star Error'), error)
else:
self.fileOpener(self.fNgc, True, False)
self.addC['state'] = 'normal'
self.undoC['state'] = 'normal'
self.preview_button_pressed(True)
def auto_preview(self):
if self.pValue.get() and self.odValue.get() and self.idValue.get():
preview(self)
def widgets(self):
if self.comp['development']:
reload(STAR)
# start settings
if not self.settingsExited:
self.pValue.set('')
self.odValue.set('')
self.idValue.set('')
self.aValue.set('')
#connections
self.ctButton['command'] = lambda:self.cut_type_clicked()
self.spButton['command'] = lambda:self.start_point_clicked()
self.previewC['command'] = lambda:preview(self)
#add to layout
self.matLabel.grid(column=0, row=0, pady=(4,0), sticky='e')
self.matCombo.grid(column=1, row=0, pady=(4,0), columnspan=3, sticky='ew')
self.spLabel.grid(column=0, row=1, pady=(4,0), sticky='e')
self.spButton.grid(column=1, row=1, pady=(4,0))
self.ctLabel.grid(column=2, row=1, pady=(4,0), sticky='e')
self.ctButton.grid(column=3, row=1, pady=(4,0))
self.xsLabel.grid(column=0, row=2, pady=(4,0), sticky='e')
self.xsEntry.grid(column=1, row=2, pady=(4,0))
self.ysLabel.grid(column=2, row=2, pady=(4,0), sticky='e')
self.ysEntry.grid(column=3, row=2, pady=(4,0))
self.liLabel.grid(column=0, row=3, pady=(4,0), sticky='e')
self.liEntry.grid(column=1, row=3, pady=(4,0))
self.loLabel.grid(column=2, row=3, pady=(4,0), sticky='e')
self.loEntry.grid(column=3, row=3, pady=(4,0))
self.pLabel.grid(column=0, row=4, pady=(4,0), sticky='e')
self.pEntry.grid(column=1, row=4, pady=(4,0))
self.odLabel.grid(column=0, row=5, pady=(4,0), sticky='e')
self.odEntry.grid(column=1, row=5, pady=(4,0))
self.idLabel.grid(column=0, row=6, pady=(4,0), sticky='e')
self.idEntry.grid(column=1, row=6, pady=(4,0))
self.aLabel.grid(column=0, row=7, pady=(4,0), sticky='e')
self.aEntry.grid(column=1, row=7, pady=(4,0))
# finish setup
self.pEntry.focus()
self.settingsExited = False

View File

@@ -0,0 +1,111 @@
'''
conv_triangle.py
Copyright (C) 2020, 2021, 2022 Phillip A Carter
Copyright (C) 2020, 2021, 2022 Gregory D Carl
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, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
'''
import os, sys
import gettext
from importlib import reload
from plasmac import triangle as TRIANGLE
for f in sys.path:
if '/lib/python' in f:
if '/usr' in f:
localeDir = 'usr/share/locale'
else:
localeDir = os.path.join(f"{f.split('/lib')[0]}",'share','locale')
break
gettext.install('linuxcnc', localedir=localeDir)
def preview(self):
matNum = int(self.matCombo.get().split(':')[0])
matNam = self.matCombo.get().split(':')[1].strip()
isExternal = self.ctbValue.get() == _('EXTERNAL')
kerfWidth = self.materials[matNum]['kerf_width']
error = TRIANGLE.preview(self, self.fTmp, self.fNgc, self.fNgcBkp, \
matNum, matNam, \
self.preAmble, self.postAmble, \
self.liValue.get(), self.loValue.get(), \
self.xsValue.get(), self.ysValue.get(), \
kerfWidth, isExternal, \
self.aaValue.get(), self.baValue.get(), self.caValue.get(), \
self.alValue.get(), self.blValue.get(), self.clValue.get(), \
self.aValue.get())
if error:
self.dialog_show_ok(_('Triangle Error'), error)
else:
self.fileOpener(self.fNgc, True, False)
self.addC['state'] = 'normal'
self.undoC['state'] = 'normal'
self.preview_button_pressed(True)
def auto_preview(self):
if (self.aaValue.get() and self.baValue.get() and self.caValue.get() and \
(self.alValue.get() or self.blValue.get() or self.clValue.get())) or \
(self.aaValue.get() and self.blValue.get() and self.clValue.get()) or \
(self.alValue.get() and self.baValue.get() and self.clValue.get()) or \
(self.alValue.get() and self.blValue.get() and self.caValue.get()) or \
(self.alValue.get() and self.blValue.get() and self.clValue.get()):
preview(self)
def widgets(self):
if self.comp['development']:
reload(TRIANGLE)
# start settings
if not self.settingsExited:
self.aaValue.set('')
self.baValue.set('')
self.caValue.set('')
self.alValue.set('')
self.blValue.set('')
self.clValue.set('')
self.aValue.set('')
# connections
self.ctButton['command'] = lambda:self.cut_type_clicked()
self.previewC['command'] = lambda:preview(self)
# add to layout
self.matLabel.grid(column=0, row=0, pady=(4,0), sticky='e')
self.matCombo.grid(column=1, row=0, pady=(4,0), columnspan=3, sticky='ew')
self.ctLabel.grid(column=2, row=1, pady=(4,0), sticky='e')
self.ctButton.grid(column=3, row=1, pady=(4,0))
self.xsLabel.grid(column=0, row=2, pady=(4,0), sticky='e')
self.xsEntry.grid(column=1, row=2, pady=(4,0))
self.ysLabel.grid(column=2, row=2, pady=(4,0), sticky='e')
self.ysEntry.grid(column=3, row=2, pady=(4,0))
self.liLabel.grid(column=0, row=3, pady=(4,0), sticky='e')
self.liEntry.grid(column=1, row=3, pady=(4,0))
self.loLabel.grid(column=2, row=3, pady=(4,0), sticky='e')
self.loEntry.grid(column=3, row=3, pady=(4,0))
self.aaLabel.grid(column=0, row=4, pady=(4,0), sticky='e')
self.aaEntry.grid(column=1, row=4, pady=(4,0))
self.alLabel.grid(column=2, row=4, pady=(4,0), sticky='e')
self.alEntry.grid(column=3, row=4, pady=(4,0))
self.baLabel.grid(column=0, row=5, pady=(4,0), sticky='e')
self.baEntry.grid(column=1, row=5, pady=(4,0))
self.blLabel.grid(column=2, row=5, pady=(4,0), sticky='e')
self.blEntry.grid(column=3, row=5, pady=(4,0))
self.caLabel.grid(column=0, row=6, pady=(4,0), sticky='e')
self.caEntry.grid(column=1, row=6, pady=(4,0))
self.clLabel.grid(column=2, row=6, pady=(4,0), sticky='e')
self.clEntry.grid(column=3, row=6, pady=(4,0))
self.aLabel.grid(column=0, row=7, pady=(4,0), sticky='e')
self.aEntry.grid(column=1, row=7, pady=(4,0))
# finish setup
self.aaEntry.focus()
self.settingsExited = False

View File

@@ -0,0 +1,881 @@
'''
conversational.py
Copyright (C) 2019, 2020, 2021, 2022 Phillip A Carter
Copyright (C) 2020, 2021, 2022 Gregory D Carl
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, write to the Free Software Foundation, Inc
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
'''
import os, sys
import gettext
import tkinter as tk
from tkinter import ttk
from tkinter.filedialog import asksaveasfilename
from importlib import reload
from shutil import copy as COPY
import conv_settings as CONVSET
import conv_line as CONVLINE
import conv_circle as CONVCIRC
import conv_ellipse as CONVELLI
import conv_triangle as CONVTRIA
import conv_rectangle as CONVRECT
import conv_polygon as CONVPOLY
import conv_bolt as CONVBOLT
import conv_slot as CONVSLOT
import conv_star as CONVSTAR
import conv_gusset as CONVGUST
import conv_sector as CONVSECT
import conv_block as CONVBLCK
for f in sys.path:
if '/lib/python' in f:
if '/usr' in f:
localeDir = 'usr/share/locale'
else:
localeDir = os.path.join(f"{f.split('/lib')[0]}",'share','locale')
break
gettext.install("linuxcnc", localedir=localeDir)
class Conv(tk.Tk):
def __init__(self, convFirstRun, root, toolFrame, convFrame, combobox, \
imagePath, tmpPath, pVars, unitsPerMm, comp, prefs, getprefs, \
putprefs, fileOpener, wcs_rotation, conv_toggle, color_change, \
plasmacPopUp, o):
self.r = root
self.rE = root.tk.eval
self.toolFrame = toolFrame
self.convFrame = convFrame
self.unitsPerMm = unitsPerMm
self.prefs = prefs
self.getPrefs = getprefs
self.putPrefs = putprefs
self.comp = comp
self.fileOpener = fileOpener
self.wcs_rotation = wcs_rotation
self.pVars = pVars
self.conv_toggle = conv_toggle
self.plasmacPopUp = plasmacPopUp
self.o = o
self.shapeLen = {'x':None, 'y':None}
self.combobox = combobox
self.fTmp = os.path.join(tmpPath, 'temp.ngc')
self.fNgc = os.path.join(tmpPath, 'shape.ngc')
self.fNgcBkp = os.path.join(tmpPath, 'backup.ngc')
self.fNgcSent = os.path.join(tmpPath, 'sent_shape.ngc')
self.filteredBkp = os.path.join(tmpPath, 'filtered_bkp.ngc')
self.savedSettings = {'start_pos':None, 'cut_type':None, 'lead_in':None, 'lead_out':None}
self.buttonState = {'newC':False, 'saveC':False, 'sendC':False, 'settingsC':False}
self.oldConvButton = False
self.module = None
self.oldModule = None
if self.unitsPerMm == 1:
smallHole = 32
leadin = 5
preAmble = 'G21 G64P0.25'
else:
smallHole = 1.25
leadin = 0.2
preAmble = 'G20 G64P0.01'
preAmble = f"{preAmble} G40 G49 G80 G90 G92.1 G94 G97"
self.xOrigin = 0.000
self.yOrigin = 0.000
if self.comp['development']:
reload(CONVSET)
CONVSET.load(self, preAmble, leadin, smallHole, preAmble)
if convFirstRun or self.comp['development']:
self.create_widgets(imagePath)
self.show_common_widgets()
color_change()
self.polyCombo['values'] = (_('CIRCUMSCRIBED'), _('INSCRIBED'), _('SIDE LENGTH'))
self.lineCombo['values'] = (_('LINE POINT ~ POINT'), _('LINE BY ANGLE'), _('ARC 3P'),\
_('ARC 2P +RADIUS'), _('ARC ANGLE +RADIUS'))
self.addC['command'] = lambda:self.add_shape_to_file()
self.undoC['command'] = lambda:self.undo_shape()
self.newC['command'] = lambda:self.new_pressed(True)
self.saveC['command'] = lambda:self.save_pressed()
self.settingsC['command'] = lambda:self.settings_pressed()
self.sendC['command'] = lambda:self.send_pressed()
for entry in self.entries:
#entry.bind('<KeyRelease>', self.auto_preview) # plays havoc with good error detection
#entry.bind('<Return>', self.auto_preview, add='+')
#entry.bind('<KP_Enter>', self.auto_preview, add='+')
entry.bind('<Return>', self.preview, add='+')
entry.bind('<KP_Enter>', self.preview, add='+')
for entry in self.buttons: entry.bind('<space>', self.button_key_pressed)
self.entry_validation()
def start(self, materialFileDict, matIndex, existingFile, g5xIndex, setViewZ):
sDiff = 40 + int(self.pVars.fontSize.get()) - 7
for i in range(len(self.convShapes)):
self.toolButton[i]['width'] = sDiff
self.toolButton[i]['height'] = sDiff
self.materials = materialFileDict
self.matIndex = matIndex
self.existingFile = existingFile
self.g5xIndex = g5xIndex
self.setViewZ = setViewZ
self.previewActive = False
self.settingsExited = False
self.validShape = False
self.invalidLeads = 0
self.ocEntry['state'] = 'disabled'
self.undoC['text'] = _('RELOAD')
self.addC['state'] = 'disabled'
self.newC['state'] = 'normal'
self.saveC['state'] = 'disabled'
self.sendC['state'] = 'disabled'
self.settingsC['state'] = 'normal'
self.polyCombo.setvalue('first')
self.lineCombo.setvalue('first')
self.convLine = {}
self.convBlock = [False, False]
for m in self.materials:
values = [str(m) + ': ' + self.materials[m]['name'] for m in self.materials]
self.matCombo['values'] = values
self.matCombo.setvalue(f"@{self.matIndex}")
longest = max(values, key=len)
tmpLabel = tk.Label(text=longest)
self.matCombo['listboxwidth'] = tmpLabel.winfo_reqwidth() + 20
if self.oldConvButton:
self.toolButton[self.convShapes.index(self.oldConvButton)].select()
self.shape_request(self.oldConvButton)
else:
self.toolButton[0].select()
self.shape_request('line')
if self.existingFile:
if 'shape.ngc' not in self.existingFile:
COPY(self.filteredBkp, self.fNgc)
COPY(self.filteredBkp, self.fNgcBkp)
else:
self.new_pressed(False)
self.l3Entry.focus()
def entry_validation(self):
self.vcmd = (self.r.register(self.validate_entries))
for w in self.uInts:
w.configure(validate='key', validatecommand=(self.vcmd, 'int', '%P', '%W'))
for w in self.sFloats:
w.configure(validate='key', validatecommand=(self.vcmd, 'flt', '%P', '%W'))
for w in self.uFloats:
w.configure(validate='key', validatecommand=(self.vcmd, 'pos', '%P', '%W'))
def validate_entries(self, style, value, widget):
widget = self.r.nametowidget(widget)
# determine the type of circle
if self.convButton.get() == 'circle' and (widget == self.dEntry or widget == self.shEntry):
circleType = 'circle'
elif self.convButton.get() == 'boltcircle' and (widget == self.hdEntry or widget == self.shEntry):
circleType = 'boltcircle'
else:
circleType = None
# blank is valid
if value == '':
if circleType:
self.circle_check(circleType, value)
return True
# period in a int is invalid and more than one period is invalid
if ('.' in value and style == 'int') or value.count('.') > 1:
return False
# a negative in a posfloat or int is invalid and more than one negative is invalid
if ('-' in value and (style == 'pos' or style == 'int')) or value.count('-') > 1:
return False
# cannot do math on "-", ".", or "-." but they are valid
if value == '.' or value == '-' or value == '-.':
if circleType:
self.circle_check(circleType, value)
return True
# if a float cannot be calculated from value then it is invalid
try:
v = float(value)
except:
return False
# must be a valid value
if circleType:
self.circle_check(circleType, value)
return True
def preview(self, event):
# # this stops focus moving to the root when return pressed
# self.rE(f"after 5 focus {event.widget}")
self.module.preview(self)
def auto_preview(self, event):
# this stops focus moving to the root when return pressed
self.rE(f"after 5 focus {event.widget}")
# we have no interest in this list of keys
if event.keysym in ['Tab']:
return
# not enough info for an auto_preview yet
if event.widget.get() in ['.','-','-.']:
print('return due to . - -.')
return
# if auto preview is valid
if self.previewC['state'] == 'normal' and self.convButton.get() != 'settings':
self.module.auto_preview(self)
def button_key_pressed(self, event):
# dummy function for:
# press a button widget via the keyboard spacebar
pass
def circle_check(self, circleType, dia):
self.invalidLeads = 0
try:
dia = float(dia)
except:
dia = 0
# cannot do overcut if large hole, no hole, or external circle
if dia >= self.smallHoleDia or dia == 0 or (self.ctbValue.get() == _('EXTERNAL') and circleType == 'circle'):
self.ocbValue.set(_('OFF'))
self.ocButton['state'] = 'disabled'
self.ocEntry['state'] = 'disabled'
else:
self.ocButton['state'] = 'normal'
self.ocEntry['state'] = 'normal'
# cannot do leadout if small hole
if self.ctbValue.get() == _('INTERNAL') or circleType == 'boltcircle':
if dia < self.smallHoleDia:
self.loLabel['state'] = 'disabled'
self.loEntry['state'] = 'disabled'
self.invalidLeads = 2
else:
# test for large leadin or leadout
try:
lIn = float(self.liValue.get())
except:
lIn = 0
try:
lOut = float(self.loValue.get())
except:
lOut = 0
if lIn and lIn > dia / 4:
self.loLabel['state'] = 'disabled'
self.loEntry['state'] = 'disabled'
self.invalidLeads = 2
elif lOut and lOut > dia / 4:
self.loLabel['state'] = 'disabled'
self.invalidLeads = 1
else:
self.loLabel['state'] = 'normal'
self.loEntry['state'] = 'normal'
self.invalidLeads = 0
else:
self.loLabel['state'] = 'normal'
self.loEntry['state'] = 'normal'
self.invalidLeads = 0
# dialog call from shapes
def dialog_show_ok(self, title, text):
reply = self.plasmacPopUp('error', title, text).reply
return reply
def new_pressed(self, buttonPressed):
if buttonPressed and (self.saveC['state'] or self.sendC['state'] or self.previewActive):
title = _('Unsaved Shape')
msg0 = _('You have an unsaved, unsent, or active previewed shape')
msg1 = _('If you continue it will be deleted')
if not self.plasmacPopUp('yesno', title, f"{msg0}\n\n{msg1}\n").reply:
return
if self.oldConvButton == 'line':
if self.lineCombo.get() == _('LINE POINT ~ POINT'):
CONVLINE.set_line_point_to_point(self)
elif self.lineCombo.get() == _('LINE BY ANGLE'):
CONVLINE.set_line_by_angle(self)
elif self.lineCombo.get() == _('ARC 3P'):
CONVLINE.set_arc_3_points(self)
elif self.lineCombo.get() == _('ARC 2P +RADIUS'):
CONVLINE.set_arc_2_points_radius(self)
elif self.lineCombo.get() == _('ARC ANGLE +RADIUS'):
CONVLINE.set_arc_by_angle_radius(self)
with open(self.fNgc, 'w') as outNgc:
outNgc.write('(new conversational file)\nM2\n')
COPY(self.fNgc, self.fTmp)
COPY(self.fNgc, self.fNgcBkp)
self.fileOpener(self.fNgc, True, False)
self.saveC['state'] = 'disabled'
self.sendC['state'] = 'disabled'
self.validShape = False
self.convLine['xLineStart'] = self.convLine['xLineEnd'] = 0
self.convLine['yLineStart'] = self.convLine['yLineEnd'] = 0
self.coValue.set('')
self.roValue.set('')
self.preview_button_pressed(False)
def save_pressed(self):
self.convFrame.unbind_all('<KeyRelease>')
self.convFrame.unbind_all('<Return>')
title = _('Save Error')
with open(self.fNgc, 'r') as inFile:
for line in inFile:
if '(new conversational file)' in line:
msg0 = _('An empty file cannot be saved')
self.plasmacPopUp('error', title, msg0)
return
# self.vkb_show() if we add a virtual keyboard ??????????????????????????
fileTypes = [('G-Code Files', '*.ngc *.nc *.tap'),
('All Files', '*.*')]
defaultExt = '.ngc'
file = asksaveasfilename(filetypes=fileTypes, defaultextension=defaultExt)
if file:
COPY(self.fNgc, file)
self.saveC['state'] = 'disabled'
# self.vkb_show(True) if we add a virtual keyboard ??????????????????????
for entry in self.entries:
#entry.bind('<KeyRelease>', self.auto_preview) # plays havoc with good error detection
#entry.bind('<Return>', self.auto_preview, add='+')
#entry.bind('<KP_Enter>', self.auto_preview, add='+')
entry.bind('<Return>', self.preview, add='+')
entry.bind('<KP_Enter>', self.preview, add='+')
def settings_pressed(self):
self.savedSettings['lead_in'] = self.liValue.get()
self.savedSettings['lead_out'] = self.loValue.get()
self.savedSettings['start_pos'] = self.spbValue.get()
self.savedSettings['cut_type'] = self.ctbValue.get()
self.buttonState['newC'] = self.newC['state']
self.buttonState['sendC'] = self.sendC['state']
self.buttonState['saveC'] = self.saveC['state']
self.buttonState['settingsC'] = self.settingsC['state']
self.newC['state'] = 'disabled'
self.sendC['state'] = 'disabled'
self.saveC['state'] = 'disabled'
self.settingsC['state'] = 'disabled'
self.clear_widgets()
if self.comp['development']:
reload(CONVSET)
for child in self.toolFrame.winfo_children():
if child.winfo_class() == 'Radiobutton':
child['state'] = 'disabled'
CONVSET.widgets(self)
CONVSET.show(self)
def send_pressed(self):
COPY(self.fNgc, self.fNgcSent)
#COPY(self.fNgc, self.filteredBkp)
self.existingFile = self.fNgc
self.saveC['state'] = 'disabled'
self.sendC['state'] = 'disabled'
self.fileOpener(self.fNgc, False, False)
self.conv_toggle(0, True)
def block_request(self):
# may need to add this halpin for wcs rotation on abort etc.
# self.convBlockLoaded = self.h.newpin('conv_block_loaded', hal.HAL_BIT, hal.HAL_IN)
if not self.settingsExited:
if self.previewActive and self.active_shape():
return True
title = _('Array Error')
with open(self.fNgc) as inFile:
for line in inFile:
if '(new conversational file)' in line:
msg0 = _('An empty file cannot be arrayed, rotated, or scaled')
self.plasmacPopUp('error', title, msg0)
return True
# see if we can do something about NURBS blocks down the track
elif 'g5.2' in line.lower() or 'g5.3' in line.lower():
msg0 = _('Cannot scale a GCode NURBS block')
self.plasmacPopUp('error', title, msg0)
return True
elif 'M3' in line or 'm3' in line:
break
return
def shape_request(self, shape): #, material):
if shape == 'closer':
self.conv_toggle(0)
return
self.oldModule = self.module
if shape == 'block':
if self.o.canon is not None:
unitsMultiplier = 25.4 if self.unitsPerMm == 1 else 1
self.shapeLen['x'] = (self.o.canon.max_extents[0] - self.o.canon.min_extents[0]) * unitsMultiplier
self.shapeLen['y'] = (self.o.canon.max_extents[1] - self.o.canon.min_extents[1]) * unitsMultiplier
self.module = CONVBLCK
if self.block_request():
self.toolButton[self.convShapes.index(self.oldConvButton)].invoke()
return
elif shape == 'line': self.module = CONVLINE
elif shape == 'circle': self.module = CONVCIRC
elif shape == 'ellipse': self.module = CONVELLI
elif shape == 'triangle': self.module = CONVTRIA
elif shape == 'rectangle': self.module = CONVRECT
elif shape == 'polygon': self.module = CONVPOLY
elif shape == 'boltcircle': self.module = CONVBOLT
elif shape == 'slot': self.module = CONVSLOT
elif shape == 'star': self.module = CONVSTAR
elif shape == 'gusset': self.module = CONVGUST
elif shape == 'sector': self.module = CONVSECT
else: return
if self.comp['development']:
reload(self.module)
if not self.settingsExited:
if self.previewActive and self.active_shape():
return
self.preview_button_pressed(False)
self.oldConvButton = shape
self.settingsC['state'] = 'normal'
self.previewC['state'] = 'normal'
self.loLabel['state'] = 'normal'
self.loEntry['state'] = 'normal'
if self.validShape:
self.undoC['state'] = 'normal'
self.addC['state'] = 'disabled'
self.clear_widgets()
self.ocButton.config(relief="raised", bg=self.bBackColor)
if self.settingsExited:
self.liValue.set(self.savedSettings['lead_in'])
self.loValue.set(self.savedSettings['lead_out'])
self.spbValue.set(self.savedSettings['start_pos'])
self.ctbValue.set(self.savedSettings['cut_type'])
else:
self.ctbValue.set(_('EXTERNAL'))
if self.origin:
self.spbValue.set(_('CENTER'))
else:
self.spbValue.set(_('BTM LEFT'))
self.liValue.set(f"{self.leadIn}")
self.loValue.set(f"{self.leadOut}")
self.module.widgets(self)
self.settingsExited = False
def preview_button_pressed(self, state):
self.previewActive = state
if state:
self.saveC['state'] = 'disabled'
self.sendC['state'] = 'disabled'
self.undoC['text'] = _('UNDO')
else:
if self.validShape:
self.saveC['state'] = 'normal'
self.sendC['state'] = 'normal'
self.undoC['text'] = _('RELOAD')
self.addC['state'] = 'disabled'
self.setViewZ()
def active_shape(self):
for child in self.toolFrame.winfo_children():
child.deselect()
title = _('Active Preview')
msg0 = _('Cannot continue with an active previewed shape')
reply = self.plasmacPopUp('warn', title, f"{msg0}\n").reply
if self.oldConvButton:
self.toolButton[self.convShapes.index(self.oldConvButton)].select()
self.module = self.oldModule
return reply
def restore_buttons(self):
self.newC['state'] = self.buttonState['newC']
self.sendC['state'] = self.buttonState['sendC']
self.saveC['state'] = self.buttonState['saveC']
self.settingsC['state'] = self.buttonState['settingsC']
def conv_is_float(self, entry):
try:
return True, float(entry)
except:
reply = -1 if entry else 0
return False, reply
def conv_is_int(self, entry):
try:
return True, int(entry)
except:
reply = -1 if entry else 0
return False, reply
def undo_shape(self):
if not self.previewActive:
title = _('Reload Request')
if self.existingFile:
name = os.path.basename(self.existingFile)
msg0 = _('The original file will be loaded')
msg1 = _('If you continue all changes will be deleted')
if not self.plasmacPopUp('yesno', title, f"{msg0}:\n\n{name}\n\n{msg1}\n").reply:
return(True)
else:
msg0 = _('An empty file will be loaded')
msg1 = _('If you continue all changes will be deleted')
if not self.plasmacPopUp('yesno', title, f"{msg0}\n\n{msg1}\n").reply:
return(True)
if self.existingFile:
COPY(self.existingFile, self.fNgcBkp)
else:
with open(self.fNgcBkp, 'w') as outNgc:
outNgc.write('(new conversational file)\nM2\n')
self.validShape = False
self.previewC['state'] = 'normal'
self.undoC['state'] = 'disabled'
self.saveC['state'] = 'disabled'
self.sendC['state'] = 'disabled'
if self.convButton.get() == 'line':
if self.previewActive:
if self.convLine['addSegment'] > 1:
self.convLine['addSegment'] = 1
self.module.line_type_changed(self, True)
else:
self.convLine['addSegment'] = 0
self.module.line_type_changed(self, False)
if self.undoC['text'] == _('RELOAD'):
self.convLine['xLineStart'] = 0.000
self.convLine['yLineStart'] = 0.000
self.l1Value.set('0.000')
self.l2Value.set('0.000')
self.convLine['xLineEnd'] = self.convLine['xLineStart']
self.convLine['yLineEnd'] = self.convLine['yLineStart']
if len(self.convLine['gcodeSave']):
self.convLine['gcodeLine'] = self.convLine['gcodeSave']
self.previewActive = False
# undo the shape
if os.path.exists(self.fNgcBkp):
COPY(self.fNgcBkp, self.fNgc)
self.fileOpener(self.fNgc, True, False)
self.addC['state'] = 'disabled'
if not self.validShape:
self.undoC['state'] = 'disabled'
if not self.convBlock[1]:
self.convBlock[0] = False
self.preview_button_pressed(False)
def add_shape_to_file(self):
COPY(self.fNgc, self.fNgcBkp)
self.validShape = True
self.addC['state'] = 'disabled'
self.saveC['state'] = 'normal'
self.sendC['state'] = 'normal'
self.preview_button_pressed(False)
if self.convButton.get() == 'line':
self.convLine['convAddSegment'] = self.convLine['gcodeLine']
self.convLine['xLineStart'] = self.convLine['xLineEnd']
self.convLine['yLineStart'] = self.convLine['yLineEnd']
self.l1Value.set(f"{self.convLine['xLineEnd']:0.3f}")
self.l2Value.set(f"{self.convLine['yLineEnd']:0.3f}")
self.convLine['addSegment'] = 1
self.module.line_type_changed(self, True)
self.addC['state'] = 'disabled'
self.previewActive = False
def clear_widgets(self):
for child in self.convFrame.winfo_children():
if not self.settingsExited and isinstance(child, tk.Entry):
if child.winfo_name() == str(getattr(self, 'liEntry')).rsplit('.',1)[1]:
pass
elif child.winfo_name() == str(getattr(self, 'loEntry')).rsplit('.',1)[1]:
pass
elif child.winfo_name() == str(getattr(self, 'liEntry')).rsplit('.',1)[1]:
pass
elif child.winfo_name() == str(getattr(self, 'liEntry')).rsplit('.',1)[1]:
pass
elif child.winfo_name() == str(getattr(self, 'caEntry')).rsplit('.',1)[1]:
self.caValue.set('360')
elif child.winfo_name() == str(getattr(self, 'cnEntry')).rsplit('.',1)[1]:
self.cnValue.set('1')
elif child.winfo_name() == str(getattr(self, 'rnEntry')).rsplit('.',1)[1]:
self.rnValue.set('1')
elif child.winfo_name() == str(getattr(self, 'scEntry')).rsplit('.',1)[1]:
self.scValue.set('1.0')
elif child.winfo_name() == str(getattr(self, 'ocEntry')).rsplit('.',1)[1]:
self.ocValue.set(f"{4 * self.unitsPerMm}")
child.grid_remove()
self.show_common_widgets()
def cut_type_clicked(self, circle=False):
if self.ctbValue.get() == _('EXTERNAL'):
self.ctbValue.set(_('INTERNAL'))
else:
self.ctbValue.set(_('EXTERNAL'))
if circle:
try:
dia = float(self.dValue.get())
except:
dia = 0
if dia >= self.smallHoleDia or dia == 0 or self.ctbValue.get() == _('EXTERNAL'):
self.ocButton.config(relief='raised', bg=self.bBackColor, state='disabled')
self.ocEntry['state'] = 'disabled'
else:
self.ocButton['state'] = 'normal'
self.ocEntry['state'] = 'normal'
self.module.auto_preview(self)
def start_point_clicked(self):
if self.spbValue.get() == _('BTM LEFT'):
self.spbValue.set(_('CENTER'))
else:
self.spbValue.set(_('BTM LEFT'))
self.module.auto_preview(self)
def material_changed(self):#, event):
# self.matCombo.selection_clear()
self.module.auto_preview(self)
def show_common_widgets(self):
self.convFrame.rowconfigure(11, weight=1)
self.spacer.grid(column=0, row=11, sticky='ns')
self.previewC.grid(column=0, row=12, padx=(4,0))
self.addC.grid(column=1, row=12, columnspan=2)
self.undoC.grid(column=3, row=12)
self.sepline.grid(column=0, row=13, columnspan=4, sticky='ew', pady=8, padx=8)
self.newC.grid(column=0, row=14, padx=(4,0), pady=(0,4))
self.saveC.grid(column=1, row=14, padx=(4,0), pady=(0,4))
self.settingsC.grid(column=2, row=14, padx=(4,0), pady=(0,4))
self.sendC.grid(column=3, row=14, padx=(4,0), pady=(0,4))
def create_widgets(self, imagePath):
for s in self.toolFrame.pack_slaves():
s.destroy()
for s in self.convFrame.grid_slaves():
s.destroy()
self.convShapes = ['line','circle','ellipse','triangle','rectangle','polygon',\
'boltcircle','slot','star','gusset','sector','block','closer']
self.convButton = tk.StringVar()
self.toolButton = []
self.images = []
# toolbar buttons
for i in range(len(self.convShapes)):
self.toolButton.append(tk.Radiobutton(self.toolFrame, text=self.convShapes[i], \
command=lambda i=i: self.shape_request(self.convShapes[i]), anchor='center', \
indicatoron=0, selectcolor='gray60', highlightthickness=0, bd=2, \
variable=self.convButton, value=self.convShapes[i], takefocus=0))
self.images.append(tk.PhotoImage(file = os.path.join(imagePath, self.convShapes[i]) + '.png'))
self.toolButton[i]['image'] = self.images[i]
self.toolButton[i]['width'] = 40
self.toolButton[i]['height'] = 40
if self.convShapes[i] == 'line':
self.toolButton[i].pack(side='left', padx=(2,0), pady=1)
elif self.convShapes[i] == 'closer':
self.toolButton[i].pack(side='right', padx=(0,2), pady=1)
else:
self.toolButton[i].pack(side='left', padx=(4,0), pady=1)
lLength = 10
eLength = 10
self.matLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('MATERIAL'))
self.matCombo = self.combobox(self.convFrame, width=lLength, justify='left', bd=1, editable=False)
self.matCombo['modifycmd'] = self.material_changed
self.spLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('START'))
self.spbValue = tk.StringVar()
self.spButton = tk.Button(self.convFrame, width=eLength, textvariable=self.spbValue, padx=1, pady=1)
self.ctLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('CUT TYPE'))
self.ctbValue = tk.StringVar()
self.ctButton = tk.Button(self.convFrame, width=eLength, textvariable=self.ctbValue, padx=1, pady=1)
self.xsLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('X ORIGIN'))
self.xsValue = tk.StringVar()
self.xsEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.xsValue, justify='right', bd=1)
self.ysLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('Y ORIGIN'))
self.ysValue = tk.StringVar()
self.ysEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.ysValue, justify='right', bd=1)
self.liLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('LEAD IN'))
self.liValue = tk.StringVar()
self.liEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.liValue, justify='right', bd=1)
self.loLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('LEAD OUT'))
self.loValue = tk.StringVar()
self.loEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.loValue, justify='right', bd=1)
self.polyLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('TYPE'))
self.polyCombo = self.combobox(self.convFrame, width=lLength, justify='left', bd=1, editable=False)
self.sLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('SIDES'))
self.sValue = tk.StringVar()
self.sEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.sValue, justify='right', bd=1)
self.dLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('DIAMETER'))
self.dValue = tk.StringVar()
self.dEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.dValue, justify='right', bd=1)
self.lLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('LENGTH'))
self.lValue = tk.StringVar()
self.lEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.lValue, justify='right', bd=1)
self.wLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('WIDTH'))
self.wValue = tk.StringVar()
self.wEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.wValue, justify='right', bd=1)
self.hLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('HEIGHT'))
self.hValue = tk.StringVar()
self.aaLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('A ANGLE'))
self.aaValue = tk.StringVar()
self.aaEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.aaValue, justify='right', bd=1)
self.alLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('a LENGTH'))
self.alValue = tk.StringVar()
self.alEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.alValue, justify='right', bd=1)
self.baLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('B ANGLE'))
self.baValue = tk.StringVar()
self.baEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.baValue, justify='right', bd=1)
self.blLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('b LENGTH'))
self.blValue = tk.StringVar()
self.blEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.blValue, justify='right', bd=1)
self.caLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('C ANGLE'))
self.caValue = tk.StringVar()
self.caEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.caValue, justify='right', bd=1)
self.clLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('c LENGTH'))
self.clValue = tk.StringVar()
self.clEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.clValue, justify='right', bd=1)
self.hEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.hValue, justify='right', bd=1)
self.hdLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('HOLE DIA'))
self.hdValue = tk.StringVar()
self.hdEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.hdValue, justify='right', bd=1)
self.hoLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('# HOLES'))
self.hoValue = tk.StringVar()
self.hoEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.hoValue, justify='right', bd=1)
self.bcaLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('CIRCLE ANG'))
self.bcaValue = tk.StringVar()
self.bcaEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.bcaValue, justify='right', bd=1)
self.ocLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('OVERCUT'))
self.ocValue = tk.StringVar()
self.ocEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.ocValue, justify='right', bd=1)
self.ocbValue = tk.StringVar(self.r, _('OFF'))
self.ocButton = tk.Button(self.convFrame, width=eLength, textvariable=self.ocbValue, padx=1, pady=1)
self.pLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('POINTS'))
self.pValue = tk.StringVar()
self.pEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.pValue, justify='right', bd=1)
self.odLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('OUTER DIA'))
self.odValue = tk.StringVar()
self.odEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.odValue, justify='right', bd=1)
self.idLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('INNER DIA'))
self.idValue = tk.StringVar()
self.idEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.idValue, justify='right', bd=1)
self.rLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('RADIUS'))
self.rbValue = tk.StringVar(self.r, _('RADIUS'))
self.rButton = tk.Button(self.convFrame, width=eLength, textvariable=self.rbValue, padx=1, pady=1)
self.rValue = tk.StringVar()
self.rEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.rValue, justify='right', bd=1)
self.saLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('SEC ANGLE'))
self.saValue = tk.StringVar()
self.saEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.saValue, justify='right', bd=1)
self.aLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('ANGLE'))
self.aValue = tk.StringVar()
self.aEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.aValue, justify='right', bd=1)
self.r1bValue = tk.StringVar()
self.r1Button = tk.Button(self.convFrame, width=eLength, textvariable=self.r1bValue, padx=1, pady=1)
self.r1Value = tk.StringVar()
self.r1Entry = tk.Entry(self.convFrame, width=eLength, textvariable=self.r1Value, justify='right', bd=1)
self.r2bValue = tk.StringVar()
self.r2Button = tk.Button(self.convFrame, width=eLength, textvariable=self.r2bValue, padx=1, pady=1)
self.r2Value = tk.StringVar()
self.r2Entry = tk.Entry(self.convFrame, width=eLength, textvariable=self.r2Value, justify='right', bd=1)
self.r3bValue = tk.StringVar()
self.r3Button = tk.Button(self.convFrame, width=eLength, textvariable=self.r3bValue, padx=1, pady=1)
self.r3Value = tk.StringVar()
self.r3Entry = tk.Entry(self.convFrame, width=eLength, textvariable=self.r3Value, justify='right', bd=1)
self.r4bValue = tk.StringVar()
self.r4Button = tk.Button(self.convFrame, width=eLength, textvariable=self.r4bValue, padx=1, pady=1)
self.r4Value = tk.StringVar()
self.r4Entry = tk.Entry(self.convFrame, width=eLength, textvariable=self.r4Value, justify='right', bd=1)
# block
self.ccLabel = tk.Label(self.convFrame, width=lLength, text=_('COLUMNS'))
self.cnLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('NUMBER'))
self.cnValue = tk.StringVar()
self.cnEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.cnValue, justify='right', bd=1)
self.coLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('OFFSET'))
self.coValue = tk.StringVar()
self.coEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.coValue, justify='right', bd=1)
self.rrLabel = tk.Label(self.convFrame, width=lLength, text=_('ROWS'))
self.rnLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('NUMBER'))
self.rnValue = tk.StringVar()
self.rnEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.rnValue, justify='right', bd=1)
self.roLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('OFFSET'))
self.roValue = tk.StringVar()
self.roEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.roValue, justify='right', bd=1)
self.bsLabel = tk.Label(self.convFrame, width=lLength, text=_('SHAPE'))
self.scLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('SCALE'))
self.scValue = tk.StringVar()
self.scEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.scValue, justify='right', bd=1)
self.rtLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('ROTATION'))
self.rtValue = tk.StringVar()
self.rtEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.rtValue, justify='right', bd=1)
self.mirror = tk.Button(self.convFrame, width=eLength, padx=1, pady=1, text=_('MIRROR'))
self.flip = tk.Button(self.convFrame, width=eLength, padx=1, pady=1, text=_('FLIP'))
self.oLabel = tk.Label(self.convFrame, width=lLength, text=_('ORIGIN OFFSET'))
# lines and arcs
self.lnLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('TYPE'))
self.lineCombo = self.combobox(self.convFrame, width=lLength, justify='left', bd=1, editable=False)
self.l1Label = tk.Label(self.convFrame, width=lLength, anchor='e', text='')
self.l1Value = tk.StringVar()
self.l1Entry = tk.Entry(self.convFrame, width=eLength, textvariable=self.l1Value, justify='right', bd=1)
self.l2Label = tk.Label(self.convFrame, width=lLength, anchor='e', text='')
self.l2Value = tk.StringVar()
self.l2Entry = tk.Entry(self.convFrame, width=eLength, textvariable=self.l2Value, justify='right', bd=1)
self.l3Label = tk.Label(self.convFrame, width=lLength, anchor='e', text='')
self.l3Value = tk.StringVar()
self.l3Entry = tk.Entry(self.convFrame, width=eLength, textvariable=self.l3Value, justify='right', bd=1)
self.l4Label = tk.Label(self.convFrame, width=lLength, anchor='e', text='')
self.l4Value = tk.StringVar()
self.l4Entry = tk.Entry(self.convFrame, width=eLength, textvariable=self.l4Value, justify='right', bd=1)
self.l5Label = tk.Label(self.convFrame, width=lLength, anchor='e', text='')
self.l5Value = tk.StringVar()
self.l5Entry = tk.Entry(self.convFrame, width=eLength, textvariable=self.l5Value, justify='right', bd=1)
self.l6Label = tk.Label(self.convFrame, width=lLength, anchor='e', text='')
self.l6Value = tk.StringVar()
self.l6Entry = tk.Entry(self.convFrame, width=eLength, textvariable=self.l6Value, justify='right', bd=1)
self.g23bValue = tk.StringVar()
self.g23Arc = tk.Button(self.convFrame, width=eLength, textvariable=self.g23bValue, padx=1, pady=1)
# settings
self.preLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('PREAMBLE'))
self.preValue = tk.StringVar()
self.preEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.preValue, bd=1)
self.pstLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('POSTAMBLE'))
self.pstValue = tk.StringVar()
self.pstEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.pstValue, bd=1)
self.llLabel = tk.Label(self.convFrame, width=lLength, text=_('LEAD LENGTHS'))
self.shLabel = tk.Label(self.convFrame, width=lLength, text=_('SMALL HOLES'))
self.shValue = tk.StringVar()
self.shEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.shValue, justify='right', bd=1)
self.hsValue = tk.StringVar()
self.hsEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.hsValue, justify='right', bd=1)
self.hsLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('SPEED %'))
self.pvLabel = tk.Label(self.convFrame, width=lLength, text=_('PREVIEW'))
self.saveS = tk.Button(self.convFrame, width=eLength, padx=1, pady=1, text=_('SAVE'))
self.reloadS = tk.Button(self.convFrame, width=eLength, padx=1, pady=1, text=_('RELOAD'))
self.exitS = tk.Button(self.convFrame, width=eLength, padx=1, pady=1, text=_('EXIT'))
# bottom
self.previewC = tk.Button(self.convFrame, width=eLength, padx=1, pady=1, text=_('PREVIEW'))
self.addC = tk.Button(self.convFrame, width=eLength, padx=1, pady=1, text=_('ADD'))
self.undoC = tk.Button(self.convFrame, width=eLength, padx=1, pady=1, text=_('UNDO'))
self.newC = tk.Button(self.convFrame, width=eLength, padx=1, pady=1, text=_('NEW'))
self.saveC = tk.Button(self.convFrame, width=eLength, padx=1, pady=1, text=_('SAVE'))
self.settingsC = tk.Button(self.convFrame, width=eLength, padx=1, pady=1, text=_('SETTINGS'))
self.sendC = tk.Button(self.convFrame, width=eLength, padx=1, pady=1, text=_('SEND'))
# spacer and separator
self.spacer = tk.Label(self.convFrame)
self.sepline = ttk.Separator(self.convFrame, orient='horizontal')
# get default background color
self.bBackColor = self.sendC.cget('bg')
# create lists of entries
self.uInts = [self.hoEntry, self.sEntry, self.pEntry, self.cnEntry, self.rnEntry]
self.sFloats = [self.xsEntry, self.ysEntry, self.aEntry, self.caEntry, \
self.coEntry, self.roEntry, self.rtEntry]
self.uFloats = [self.liEntry, self.loEntry, self.dEntry, self.ocEntry, self.hdEntry, \
self.wEntry, self.rEntry, self.saEntry, self.hEntry, self.r1Entry, \
self.r2Entry, self.r3Entry, self.r4Entry, self.lEntry, self.odEntry, \
self.idEntry, self.aaEntry, self.baEntry, self.caEntry, self.alEntry, \
self.blEntry, self.clEntry, self.scEntry, self.shEntry, self.hsEntry, \
self.l1Entry, self.l2Entry, self.l3Entry, self.l4Entry, self.l5Entry, \
self.l6Entry, ]
self.entries = []
for entry in self.uInts: self.entries.append(entry)
for entry in self.sFloats: self.entries.append(entry)
for entry in self.uFloats: self.entries.append(entry)
self.buttons = [self.spButton, self.ctButton, self.ocButton, self.rButton, self.r1Button, \
self.r2Button, self.r3Button, self.r4Button, self.mirror, self.flip, \
self.g23Arc, self.saveS, self.reloadS, self.exitS, self.previewC, \
self.addC, self.undoC, self.newC, self.saveC, self.settingsC, self.sendC]
for button in self.buttons:
button.configure(takefocus=0)
self.combos = [self.matCombo, self.polyCombo, self.lineCombo]
for combo in self.combos:
combo.configure(takefocus=0)

View File

@@ -0,0 +1,4 @@
# CUSTOM PYTHON CODE, RUNS ONCE AT STARTUP
# example to change the color of the arc voltage digits
#rC(fplasma + '.arc-voltage','configure','-fg','#ff00aa')

View File

@@ -0,0 +1,4 @@
# CUSTOM HAL PINS, RUNS ONCE AT STARTUP
# example hal pin named my-halpin
#comp.newpin('my-halpin', hal.HAL_FLOAT, hal.HAL_IN)

View File

@@ -0,0 +1,5 @@
# CUSTOM PERIODIC CODE, RUNS ONCE EVERY CYCLE
# example to print value of custom hal pin if not zero
#if comp['my-halpin']:
# print(comp['my-halpin'])

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 511 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 539 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 310 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 428 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 425 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 307 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 310 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 402 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 432 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 420 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 480 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 398 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 449 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 459 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 278 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 689 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 419 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 459 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 442 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 337 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 420 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 419 B

View File

@@ -0,0 +1,86 @@
<?xml version="1.0" ?>
<!--
Copyright © 2020 Phillip A Carter. This file is part of LinuxCNC.
LinuxCNC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
Onboard is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<keyboard format="3.2" id="keyboard" section="system" summary="Keyboard for plasmac2">
<include file="key_defs.xml"/>
<box border="0.5" orientation="vertical" spacing="1.5">
<panel filename="keyboard.svg" layer="alpha">
<key group="alphanumeric" id="AB01"/>
<key group="alphanumeric" id="AE02"/>
<key group="alphanumeric" id="AE03"/>
<key group="alphanumeric" id="AD09"/>
<key group="alphanumeric" id="AE01"/>
<key group="alphanumeric" id="AE06"/>
<key group="alphanumeric" id="AE07"/>
<key group="alphanumeric" id="AE04"/>
<key group="alphanumeric" id="AE05"/>
<key group="alphanumeric" id="AD03"/>
<key group="alphanumeric" id="AD02"/>
<key group="alphanumeric" id="AD01"/>
<key group="alphanumeric" id="AE09"/>
<key group="alphanumeric" id="AD07"/>
<key group="alphanumeric" id="AD06"/>
<key group="alphanumeric" id="AD05"/>
<key group="alphanumeric" id="AD04"/>
<key group="alphanumeric" id="AB10"/>
<key group="alphanumeric" id="AC11"/>
<key group="alphanumeric" id="AC10"/>
<key group="alphanumeric" id="TLDE"/>
<key group="alphanumeric" id="LSGT"/>
<key group="alphanumeric" id="BKSL"/>
<key group="alphanumeric" id="AD10"/>
<key group="alphanumeric" id="AD11"/>
<key group="alphanumeric" id="AD12"/>
<key group="alphanumeric" id="AB08"/>
<key group="alphanumeric" id="AE11"/>
<key group="alphanumeric" id="AE10"/>
<key group="alphanumeric" id="AE12"/>
<key group="alphanumeric" id="AC04"/>
<key group="alphanumeric" id="AC05"/>
<key group="alphanumeric" id="AC06"/>
<key group="alphanumeric" id="AC07"/>
<key group="alphanumeric" id="AB09"/>
<key group="alphanumeric" id="AC01"/>
<key group="alphanumeric" id="AC02"/>
<key group="alphanumeric" id="AC03"/>
<key group="alphanumeric" id="AB05"/>
<key group="alphanumeric" id="AB04"/>
<key group="alphanumeric" id="AE08"/>
<key group="alphanumeric" id="AB06"/>
<key group="alphanumeric" id="AC08"/>
<key group="alphanumeric" id="AC09"/>
<key group="alphanumeric" id="AB03"/>
<key group="alphanumeric" id="AB02"/>
<key group="alphanumeric" id="AD08"/>
<key group="alphanumeric" id="AB07"/>
<key group="misc" id="CAPS"/>
<key group="shifts" id="LFSH"/>
<key group="shifts" id="RTSH"/>
<key group="bottomrow" id="LCTL"/>
<key group="bottomrow" id="LALT"/>
<key group="bottomrow" id="RALT"/>
<key group="bottomrow" id="LWIN"/>
<key group="bottomrow" id="SPCE"/>
<key group="bottomrow" id="DELE.next-to-backspace"/>
<key group="bottomrow" id="BKSP"/>
<key group="bottomrow" id="move"/>
<key group="misc" id="TAB"/>
<key group="misc" id="RTRN" label_x_align="0.65"/>
<key group="directions_alpha" id="LEFT"/>
<key group="directions_alpha" id="RGHT"/>
<key group="directions_alpha" id="UP"/>
<key group="directions_alpha" id="DOWN"/>
</panel>
</box>
</keyboard>

View File

@@ -0,0 +1,581 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created for Onboard -->
<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:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
id="svg2"
height="115"
width="330"
version="1.0"
inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)"
sodipodi:docname="keyboard.svg">
<defs
id="defs90" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1680"
inkscape:window-height="993"
id="namedview88"
showgrid="false"
inkscape:zoom="4.2249561"
inkscape:cx="151.95424"
inkscape:cy="47.5"
inkscape:window-x="0"
inkscape:window-y="29"
inkscape:window-maximized="1"
inkscape:current-layer="svg2"
inkscape:snap-bbox="true"
inkscape:bbox-nodes="true"
inkscape:bbox-paths="true"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
showguides="true"
inkscape:guide-bbox="true"
inkscape:snap-global="true"
inkscape:object-paths="false"
inkscape:object-nodes="true">
<sodipodi:guide
orientation="1,0"
position="-8.8560886,101.84502"
id="guide3833"
inkscape:locked="false" />
</sodipodi:namedview>
<metadata
id="metadata3346">
<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>Compact-Alpha.svg</dc:title>
<cc:license
rdf:resource="https://www.gnu.org/licenses/gpl.txt" />
<dc:creator>
<cc:Agent>
<dc:title>Onboard Devel Team at https://launchpad.net/~onboard</dc:title>
</cc:Agent>
</dc:creator>
<dc:rights>
<cc:Agent>
<dc:title>GPL-3+ license</dc:title>
</cc:Agent>
</dc:rights>
<dc:publisher>
<cc:Agent>
<dc:title>Onboard Devel Team</dc:title>
</cc:Agent>
</dc:publisher>
<dc:source>https://launchpad.net/onboard</dc:source>
<dc:relation>This file is part of Onboard</dc:relation>
<dc:contributor>
<cc:Agent>
<dc:title>Copyright © 2013, 2016, Francesco Fumanti &lt;francesco.fumanti@gmx.net&gt;
Copyright © 2011-2014, marmuta &lt;marmvta@gmail.com&gt;</dc:title>
</cc:Agent>
</dc:contributor>
</cc:Work>
</rdf:RDF>
</metadata>
<rect
id="AB01"
style="fill:#e5d8b2;stroke:#000000"
height="18"
width="18"
y="77.5"
x="47.5" />
<rect
id="AE02"
style="fill:#e5d8b2;stroke:#000000"
height="18"
width="18"
y="20.5"
x="38" />
<rect
id="AE03"
style="fill:#e5d8b2;stroke:#000000"
height="18"
width="18"
y="20.5"
x="57" />
<rect
id="AD09"
style="fill:#e5d8b2;stroke:#000000"
height="18"
width="18"
y="39.5"
x="183" />
<rect
id="AE01"
style="fill:#e5d8b2;stroke:#000000"
height="18"
width="18"
y="20.5"
x="19" />
<rect
id="AE06"
style="fill:#e5d8b2;stroke:#000000"
height="18"
width="18"
y="20.5"
x="114" />
<rect
id="AE07"
style="fill:#e5d8b2;stroke:#000000"
height="18"
width="18"
y="20.5"
x="133" />
<rect
id="AE04"
style="fill:#e5d8b2;stroke:#000000"
height="18"
width="18"
y="20.5"
x="76" />
<rect
id="AE05"
style="fill:#e5d8b2;stroke:#000000"
height="18"
width="18"
y="20.5"
x="95" />
<rect
id="AD03"
style="fill:#e5d8b2;stroke:#000000"
height="18"
width="18"
y="39.5"
x="69" />
<rect
id="AD02"
style="fill:#e5d8b2;stroke:#000000"
height="18"
width="18"
y="39.5"
x="50" />
<rect
id="AD01"
style="fill:#e5d8b2;stroke:#000000"
height="18"
width="18"
y="39.5"
x="31" />
<rect
id="AE09"
style="fill:#e5d8b2;stroke:#000000"
height="18"
width="18"
y="20.5"
x="171" />
<rect
id="AD07"
style="fill:#e5d8b2;stroke:#000000"
height="18"
width="18"
y="39.5"
x="145" />
<rect
id="AD06"
style="fill:#e5d8b2;stroke:#000000"
height="18"
width="18"
y="39.5"
x="126" />
<rect
id="AD05"
style="fill:#e5d8b2;stroke:#000000"
height="18"
width="18"
y="39.5"
x="107" />
<rect
id="AD04"
style="fill:#e5d8b2;stroke:#000000"
height="18"
width="18"
y="39.5"
x="88" />
<rect
id="AB10"
style="fill:#e5d8b2;stroke:#000000"
height="18"
width="18"
y="77.5"
x="218.5" />
<rect
id="AC11"
style="fill:#e5d8b2;stroke:#000000"
height="18"
width="18"
y="58.5"
x="225.49995" />
<rect
id="AC10"
style="fill:#e5d8b2;stroke:#000000"
height="18"
width="18"
y="58.5"
x="206.49995" />
<rect
id="TLDE"
style="fill:#e5d8b2;stroke:#000000;stroke-width:0.99999994"
height="18"
width="17.5"
y="20.5"
x="0.5" />
<rect
id="LSGT"
style="fill:#e5d8b2;stroke:#000000"
height="18"
width="18"
y="77.5"
x="28.5" />
<rect
id="BKSL"
style="fill:#e5d8b2;stroke:#000000;stroke-width:0.99999994"
height="18"
width="18"
y="58.5"
x="244.49995" />
<rect
id="AD10"
style="fill:#e5d8b2;stroke:#000000"
height="18"
width="18"
y="39.5"
x="202" />
<rect
id="AD11"
style="fill:#e5d8b2;stroke:#000000"
height="18"
width="18"
y="39.5"
x="221" />
<rect
id="AD12"
style="fill:#e5d8b2;stroke:#000000"
height="18"
width="18"
y="39.5"
x="240" />
<rect
id="AB08"
style="fill:#e5d8b2;stroke:#000000"
height="18"
width="18"
y="77.5"
x="180.5" />
<rect
id="AE11"
style="fill:#e5d8b2;stroke:#000000"
height="18"
width="18"
y="20.5"
x="209" />
<rect
id="AE10"
style="fill:#e5d8b2;stroke:#000000"
height="18"
width="18"
y="20.5"
x="190" />
<rect
id="AE12"
style="fill:#e5d8b2;stroke:#000000"
height="18"
width="18"
y="20.5"
x="228" />
<rect
id="AC04"
style="fill:#e5d8b2;stroke:#000000"
height="18"
width="18"
y="58.5"
x="92.499962" />
<rect
id="AC05"
style="fill:#e5d8b2;stroke:#000000"
height="18"
width="18"
y="58.5"
x="111.49996" />
<rect
id="AC06"
style="fill:#e5d8b2;stroke:#000000"
height="18"
width="18"
y="58.5"
x="130.49995" />
<rect
id="AC07"
style="fill:#e5d8b2;stroke:#000000"
height="18"
width="18"
y="58.5"
x="149.49995" />
<rect
id="AB09"
style="fill:#e5d8b2;stroke:#000000"
height="18"
width="18"
y="77.5"
x="199.5" />
<rect
id="AC01"
style="fill:#e5d8b2;stroke:#000000"
height="18"
width="18"
y="58.5"
x="35.499962" />
<rect
id="AC02"
style="fill:#e5d8b2;stroke:#000000"
height="18"
width="18"
y="58.5"
x="54.499962" />
<rect
id="AC03"
style="fill:#e5d8b2;stroke:#000000"
height="18"
width="18"
y="58.5"
x="73.499962" />
<rect
id="AB05"
style="fill:#e5d8b2;stroke:#000000"
height="18"
width="18"
y="77.5"
x="123.5" />
<rect
id="AB04"
style="fill:#e5d8b2;stroke:#000000"
height="18"
width="18"
y="77.5"
x="104.5" />
<rect
id="AE08"
style="fill:#e5d8b2;stroke:#000000"
height="18"
width="18"
y="20.5"
x="152" />
<rect
id="AB06"
style="fill:#e5d8b2;stroke:#000000"
height="18"
width="18"
y="77.5"
x="142.5" />
<rect
id="AC08"
style="fill:#e5d8b2;stroke:#000000"
height="18"
width="18"
y="58.5"
x="168.49995" />
<rect
id="AC09"
style="fill:#e5d8b2;stroke:#000000"
height="18"
width="18"
y="58.5"
x="187.49995" />
<rect
id="AB03"
style="fill:#e5d8b2;stroke:#000000"
height="18"
width="18"
y="77.5"
x="85.5" />
<rect
id="AB02"
style="fill:#e5d8b2;stroke:#000000"
height="18"
width="18"
y="77.5"
x="66.5" />
<rect
id="AD08"
style="fill:#e5d8b2;stroke:#000000"
height="18"
width="18"
y="39.5"
x="164" />
<rect
id="AB07"
style="fill:#e5d8b2;stroke:#000000"
height="18"
width="18"
y="77.5"
x="161.5" />
<rect
id="RCTL"
style="fill:#f2e5d8;stroke:#000000"
height="18"
width="23"
y="96.5"
x="261" />
<rect
id="LCTL"
style="fill:#f2e5d8;stroke:#000000"
height="18"
width="27"
y="96.5"
x="0.5" />
<rect
id="LALT"
style="fill:#f2e5d8;stroke:#000000"
height="18"
width="23"
y="96.5"
x="52.5" />
<rect
id="MENU"
style="fill:#d8cca5;stroke:#000000"
height="18"
width="23"
y="96.5"
x="237" />
<rect
id="RWIN"
style="fill:#d8cca5;stroke:#000000"
height="18"
width="23"
y="96.5"
x="213" />
<rect
id="LWIN"
style="fill:#f2e5d8;stroke:#000000"
height="18"
width="23"
y="96.5"
x="28.5" />
<rect
id="BKSP"
style="fill:#d8cca5;stroke:#000000;stroke-width:0.99999994"
height="18"
width="18"
y="20.5"
x="247" />
<rect
id="DELE"
style="fill:#d8cca5;stroke:#000000;stroke-width:0.99999988"
height="18"
width="18"
y="20.5"
x="266" />
<rect
id="TAB"
style="fill:#d8cca5;stroke:#000000;stroke-width:1"
height="18"
width="29.5"
y="39.5"
x="0.5" />
<rect
id="CAPS"
style="fill:#f2e5d8;stroke:#000000;stroke-width:1"
height="18"
width="34"
y="58.5"
x="0.5" />
<rect
id="LFSH"
style="fill:#f2e5d8;stroke:#000000;stroke-width:0.99999994"
height="18"
width="26.999998"
y="77.5"
x="0.49999997" />
<rect
id="RTSH"
style="fill:#f2e5d8;stroke:#000000;stroke-width:0.99999994"
height="18"
width="46.5"
y="77.5"
x="237.5" />
<rect
id="SPCE"
style="fill:#e5d8b2;stroke:#000000;stroke-width:1"
height="18"
width="108.5"
y="96.5"
x="76.5" />
<rect
id="RALT"
style="fill:#f2e5d8;stroke:#000000"
height="18"
width="22"
y="96.5"
x="186" />
<rect
id="LEFT"
style="fill:#d8cca5;stroke:#000000"
height="18"
width="18"
y="96.5"
x="209" />
<rect
id="RGHT"
style="fill:#d8cca5;stroke:#000000"
height="18"
width="18"
y="96.5"
x="228" />
<rect
id="UP"
style="fill:#d8cca5;stroke:#000000"
height="18"
width="18"
y="96.5"
x="247" />
<rect
id="DOWN"
style="fill:#d8cca5;stroke:#000000"
height="18"
width="18"
y="96.5"
x="266" />
<g
id="RTRN">
<path
inkscape:label="#RTRN_100pct"
sodipodi:nodetypes="ccccccc"
inkscape:connector-curvature="0"
id="RTRN_100pct"
d="m 259,39.5 25,0 0,37 -20.50001,0 0,-19 -4.49999,0 z"
style="fill:#e5d8b2;fill-opacity:1;stroke:#000000;stroke-width:1" />
<path
style="opacity:0.2;fill:#e5d8b2;fill-opacity:1;stroke:#000000;stroke-width:1"
d="m 263.75,44.25 15.5,0 0,27.5 -11,0 0,-19 -4.5,0 z"
id="RTRN_50pct"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccc"
inkscape:label="#RTRN_50pct" />
</g>
<rect
id="move"
style="fill:#d8cca5;stroke:#000000;stroke-width:0.99999988"
height="18"
width="18"
y="20.5"
x="285" />
</svg>

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -0,0 +1,43 @@
<?xml version="1.0" ?>
<!--
Copyright © 2020 Phillip A Carter. This file is part of LinuxCNC.
LinuxCNC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
Onboard is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<keyboard format="3.2" id="numpad" section="system" summary="Number pad for plasmac2">
<include file="key_defs.xml"/>
<box border="0.5" orientation="vertical" spacing="1.5">
<panel filename="numpad.svg" layer="alpha">
<key id="TAB" action="single-stroke" label_x_align="0.5"/>
<key id="AE01" action="single-stroke"/>
<key id="AE02" action="single-stroke"/>
<key id="AE03" action="single-stroke"/>
<key id="move" action="single-stroke"/>
<key id="bktb" action="single-stroke" keysym="0xfe20" label="⇤"/>
<key id="AE04" action="single-stroke"/>
<key id="AE05" action="single-stroke"/>
<key id="AE06" action="single-stroke"/>
<key id="LEFT" action="single-stroke"/>
<key id="AE07" action="single-stroke"/>
<key id="AE08" action="single-stroke"/>
<key id="AE09" action="single-stroke"/>
<key id="UP" action="single-stroke"/>
<key id="RGHT" action="single-stroke"/>
<key id="AE11" action="single-stroke"/>
<key id="AE10" action="single-stroke"/>
<key id="AB09" action="single-stroke"/>
<key id="DOWN" action="single-stroke"/>
<key id="BKSP" action="single-stroke"/>
<key id="DELE" action="single-stroke"/>
<key id="RTRN" action="single-stroke" label_x_align="0.5"/>
</panel>
</box>
</keyboard>

View File

@@ -0,0 +1,256 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<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:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
sodipodi:docname="numpad.svg"
inkscape:version="1.0 (4035a4f, 2020-05-01)"
version="1.0"
width="190"
height="115"
id="scan-base">
<defs
id="defs49" />
<sodipodi:namedview
inkscape:document-rotation="0"
inkscape:guide-bbox="true"
showguides="true"
inkscape:current-layer="scan-base"
inkscape:window-maximized="1"
inkscape:window-y="29"
inkscape:window-x="0"
inkscape:cy="44.480223"
inkscape:cx="23.907395"
inkscape:zoom="7.9473443"
inkscape:bbox-nodes="true"
inkscape:snap-bbox="true"
showgrid="false"
id="namedview47"
inkscape:window-height="993"
inkscape:window-width="1680"
inkscape:pageshadow="2"
inkscape:pageopacity="0"
guidetolerance="10"
gridtolerance="10"
objecttolerance="10"
borderopacity="1"
bordercolor="#666666"
pagecolor="#ffffff" />
<metadata
id="metadata7">
<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>Grid-Alpha.svg</dc:title>
<cc:license
rdf:resource="https://www.gnu.org/licenses/gpl.txt" />
<dc:creator>
<cc:Agent>
<dc:title>Onboard Devel Team at https://launchpad.net/~onboard</dc:title>
</cc:Agent>
</dc:creator>
<dc:rights>
<cc:Agent>
<dc:title>GPL-3+ license</dc:title>
</cc:Agent>
</dc:rights>
<dc:publisher>
<cc:Agent>
<dc:title>Onboard Devel Team</dc:title>
</cc:Agent>
</dc:publisher>
<dc:source>https://launchpad.net/onboard</dc:source>
<dc:relation>This file is part of Onboard</dc:relation>
<dc:contributor>
<cc:Agent>
<dc:title>Copyright © 2016, Francesco Fumanti &lt;francesco.fumanti@gmx.net&gt;
Copyright © 2011-2014, marmuta &lt;marmvta@gmail.com&gt;</dc:title>
</cc:Agent>
</dc:contributor>
</cc:Work>
</rdf:RDF>
</metadata>
<rect
inkscape:label=""
id="AE01"
style="fill:#a97679;stroke:#000000;stroke-width:1.00000036;stroke-miterlimit:4;stroke-dasharray:none"
height="18"
width="18"
y="20.499756"
x="0.50010478" />
<rect
inkscape:label=""
id="AE07"
style="fill:#a97679;stroke:#000000;stroke-width:0.99999994;stroke-miterlimit:4;stroke-dasharray:none"
height="18.000097"
width="18.000084"
y="58.499851"
x="0.50002104" />
<rect
inkscape:label=""
id="AE02"
style="fill:#a97679;stroke:#000000;stroke-width:0.99999994;stroke-miterlimit:4;stroke-dasharray:none"
height="18"
width="18.000084"
y="20.499756"
x="19.500105" />
<rect
inkscape:label=""
id="AE04"
style="fill:#a97679;stroke:#000000;stroke-width:0.99999994;stroke-miterlimit:4;stroke-dasharray:none"
height="18.000097"
width="18.000084"
y="39.499756"
x="0.50002104" />
<rect
inkscape:label=""
id="AE03"
style="fill:#a97679;stroke:#000000;stroke-width:0.99999994;stroke-miterlimit:4;stroke-dasharray:none"
height="18"
width="18.000084"
y="20.499756"
x="38.500187" />
<rect
inkscape:label=""
id="AE06"
style="fill:#a97679;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none"
height="18.000006"
width="18.000084"
y="39.499756"
x="38.500187" />
<rect
inkscape:label=""
id="AE08"
style="fill:#a97679;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none"
height="18.000006"
width="18.000084"
y="58.499943"
x="19.500105" />
<rect
inkscape:label=""
id="AB09"
style="fill:#a97679;stroke:#000000;stroke-width:0.99999994;stroke-miterlimit:4;stroke-dasharray:none"
height="18"
width="18.000084"
y="77.499947"
x="38.500187" />
<rect
inkscape:label=""
id="AE11"
style="fill:#a97679;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none"
height="18.000006"
width="18.000084"
y="77.499931"
x="0.50002098" />
<rect
inkscape:label=""
id="AE10"
style="fill:#a97679;stroke:#000000;stroke-width:0.99999994;stroke-miterlimit:4;stroke-dasharray:none"
height="18"
width="18.000084"
y="77.499947"
x="19.500105" />
<rect
inkscape:label=""
id="AE09"
style="fill:#a97679;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none"
height="18.000006"
width="18.000084"
y="58.499943"
x="38.500191" />
<rect
inkscape:label=""
id="AE05"
style="fill:#a97679;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none"
height="18.000006"
width="18.000084"
y="39.499756"
x="19.500105" />
<rect
inkscape:label=""
id="BKSP"
style="fill:#b7ad8b;stroke:#000000;stroke-width:0.99999988;stroke-miterlimit:4;stroke-dasharray:none"
height="18"
width="18.000105"
y="96.499939"
x="-18.500084" />
<rect
inkscape:label=""
id="RTRN"
style="fill:#b7ad8b;stroke:#000000;stroke-width:0.99999988;stroke-miterlimit:4;stroke-dasharray:none"
height="18.000097"
width="36.999641"
y="96.499947"
x="19.500629" />
<rect
inkscape:label=""
id="LEFT"
style="fill:#a97679;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none"
height="18.000006"
width="18.000084"
y="58.499756"
x="-18.499979" />
<rect
inkscape:label=""
id="RGHT"
style="fill:#a97679;stroke:#000000;stroke-width:0.99999994;stroke-miterlimit:4;stroke-dasharray:none"
height="18"
width="18.000084"
y="77.499939"
x="-18.500063" />
<rect
inkscape:label=""
id="TAB"
style="fill:#a97679;stroke:#000000;stroke-width:1.00000036;stroke-miterlimit:4;stroke-dasharray:none"
height="18"
width="18"
y="20.499756"
x="-18.499895" />
<rect
inkscape:label=""
id="bktb"
style="fill:#a97679;stroke:#000000;stroke-width:1.00000036;stroke-miterlimit:4;stroke-dasharray:none"
height="18"
width="18"
y="39.499756"
x="-18.499979" />
<rect
inkscape:label=""
id="DELE"
style="fill:#b7ad8b;stroke:#000000;stroke-width:0.99999988;stroke-miterlimit:4;stroke-dasharray:none"
height="18"
width="18.000105"
y="96.499939"
x="0.50002086" />
<rect
inkscape:label="#move"
id="move"
style="fill:#a97679;stroke:#000000;stroke-width:0.99999994;stroke-miterlimit:4;stroke-dasharray:none"
height="18"
width="18.000084"
y="20.499756"
x="57.500271" />
<rect
inkscape:label=""
id="DOWN"
style="fill:#a97679;stroke:#000000;stroke-width:0.99999994;stroke-miterlimit:4;stroke-dasharray:none"
height="18"
width="18.000084"
y="77.499947"
x="57.500271" />
<rect
x="57.500271"
y="58.499947"
width="18.000084"
height="18"
style="fill:#a97679;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none"
id="UP"
inkscape:label="" />
</svg>

After

Width:  |  Height:  |  Size: 7.5 KiB

View File

@@ -0,0 +1,74 @@
# GENERIC HAL TCL FILE FOR PLASMAC2 SIM CONFIGS WITHOUT STEPGENS
# ---SET CONSTANTS---
set numJoints $::KINS(JOINTS)
set zAxis [string first "z" [string tolower $::TRAJ(COORDINATES)]]
# ---LOAD COMPONENTS---
loadrt $::KINS(KINEMATICS)
loadrt $::EMCMOT(EMCMOT) servo_period_nsec=$::EMCMOT(SERVO_PERIOD) num_joints=$numJoints num_spindles=$::TRAJ(SPINDLES)
loadrt plasmac
for {set jNum 0} {$jNum < $numJoints} {incr jNum} {
loadrt pid names=sim-joint.${jNum}.pid
loadrt mux2 names=sim-joint.${jNum}.mux
loadrt ddt names=sim-joint.${jNum}.vel
loadrt sim_home_switch names=sim-joint.${jNum}.home-switch
}
# ---LINK TO THREADS---
addf motion-command-handler servo-thread
addf motion-controller servo-thread
addf plasmac servo-thread
for {set jNum 0} {$jNum < $numJoints} {incr jNum} {
addf sim-joint.${jNum}.pid.do-pid-calcs servo-thread
addf sim-joint.${jNum}.mux servo-thread
addf sim-joint.${jNum}.vel servo-thread
}
for {set jNum 0} {$jNum < $numJoints} {incr jNum} {
addf sim-joint.${jNum}.home-switch servo-thread
}
# ---SET UNCONNECTED INPUT PINS---
for {set jNum 0} {$jNum < $numJoints} {incr jNum} {
setp sim-joint.${jNum}.pid.Pgain 0
setp sim-joint.${jNum}.pid.Dgain 0
setp sim-joint.${jNum}.pid.Igain 0
setp sim-joint.${jNum}.pid.FF0 1.0
setp sim-joint.${jNum}.pid.FF1 0
setp sim-joint.${jNum}.pid.FF2 0
}
# ---JOINT CONNECTIONS---
for {set jNum 0} {$jNum < $numJoints} {incr jNum} {
net sim:joint${jNum}.enable joint.${jNum}.amp-enable-out => sim-joint.${jNum}.pid.enable
net sim:joint${jNum}.homesw sim-joint.${jNum}.home-switch.home-sw => joint.${jNum}.home-sw-in
net sim:joint${jNum}.on-pos sim-joint.${jNum}.pid.output => sim-joint.${jNum}.mux.in1
net sim:joint${jNum}.pos-cmd joint.${jNum}.motor-pos-cmd => sim-joint.${jNum}.pid.command
net sim:joint${jNum}.pos-fb sim-joint.${jNum}.mux.out => sim-joint.${jNum}.mux.in0 sim-joint.${jNum}.home-switch.cur-pos sim-joint.${jNum}.vel.in joint.${jNum}.motor-pos-fb
}
net sim:enabled motion.motion-enabled
for {set jNum 0} {$jNum < $numJoints} {incr jNum} {
net sim:enabled sim-joint.${jNum}.mux.sel
}
# ---INPUT DEBOUNCE---
loadrt dbounce names=db_breakaway,db_float,db_ohmic,db_arc-ok
addf db_float servo-thread
addf db_ohmic servo-thread
addf db_breakaway servo-thread
addf db_arc-ok servo-thread
# ---Z JOINT CONNECTION---
net plasmac:axis-position joint.${zAxis}.pos-fb => plasmac.axis-z-position
# ---TOOL CHANGE PASSTHROUGH
net sim:tool-number <= iocontrol.0.tool-prep-number
net sim:tool-change-loopback iocontrol.0.tool-change => iocontrol.0.tool-changed
net sim:tool-prepare-loopback iocontrol.0.tool-prepare => iocontrol.0.tool-prepared
# ---ESTOP COMPONENTS FOR PLASMAC2---
loadrt or2 names=estop_or
loadrt not names=estop_not,estop_not_1
addf estop_or servo-thread
addf estop_not servo-thread
addf estop_not_1 servo-thread

View File

@@ -0,0 +1,258 @@
#!/usr/bin/python3
'''
SIMULATOR PANEL FOR PLASMAC CONFIGS
'''
from tkinter import *
from tkinter.constants import *
from subprocess import call as CALL
import linuxcnc
import hal
import signal
import time
def unload(e, method):
raise SystemExit(f'\nplasmac2 sim panel unloaded:\n{e}\nerror in {method}\n')
def time_out(signum, frame):
unload('axis gui was closed')
def arc_voltage_changed(value):
try:
hal.set_p('sim-torch.offset-in', value)
except Exception as e:
unload(e, 'arc_voltage_changed')
def button_changed(event, button, pin):
try:
global buttonStart, arcOkPressed
if event.type == EventType.Button:
buttonStart = time.time()
hal.set_p(pin, '1')
if mode > 0:
if button == arcOkB:
arcOkPressed = True
if button == breakB:
button.configure(background=buttonRd)
button.configure(activebackground=buttonRd)
else:
button.configure(background=buttonGn)
button.configure(activebackground=buttonGn)
elif time.time() - buttonStart < 1:
hal.set_p(pin, '0')
if mode > 0:
if button == arcOkB:
arcOkPressed = False
button.configure(background=buttonBg)
button.configure(activebackground=buttonBg)
except Exception as e:
unload(e, 'button_changed')
def mode_change(mode):
arcF.pack_forget()
switchF.pack_forget()
okF.pack_forget()
moveF.pack_forget()
if mode == 0:
arcF.pack(padx=2,pady=2,fill='x')
switchF.pack(padx=2,pady=2,fill='x')
if mode == 1:
arcF.pack(padx=2,pady=2,fill='x')
switchF.pack(padx=2,pady=2,fill='x')
okF.pack(padx=2,pady=2,fill='x')
if mode == 2:
switchF.pack(padx=2,pady=2,fill='x')
okF.pack(padx=2,pady=2,fill='x')
moveF.pack(padx=2,pady=2,fill='x')#, expand=True)
def periodic():
try:
global mode
# handle window updates on mode changes
current_mode = hal.get_value('plasmac.mode')
if mode != current_mode:
mode = current_mode
mode_change(mode)
# activate float or ohmic when probing
if hal.get_value('plasmac.state-out') == 2 and \
hal.get_value('plasmac-sim.z-position') < probeHeight:
if selectedSensor.get():
hal.set_p('db_float.in', '1')
floatB.configure(activebackground=buttonGn)
floatB.configure(bg=buttonGn)
elif hal.get_value('plasmac.ohmic-probe-enable'):
hal.set_p('db_ohmic.in', '1')
ohmicB.configure(activebackground=buttonGn)
ohmicB.configure(bg=buttonGn)
elif hal.get_value('plasmac.state-out') == 2 or hal.get_value('plasmac.state-out') == 3 and \
hal.get_value('plasmac-sim.z-position') > probeHeight:
hal.set_p('db_float.in', '0')
floatB.configure(activebackground=buttonBg)
floatB.configure(bg=buttonBg)
hal.set_p('db_ohmic.in', '0')
ohmicB.configure(activebackground=buttonBg)
ohmicB.configure(bg=buttonBg)
# set arc ok if mode = 1 or 2
if mode > 0:
if not arcOkPressed:
if mode and hal.get_value('plasmac.torch-on'):
hal.set_p('db_arc-ok.in', '1')
arcOkB.configure(background=buttonGn)
arcOkB.configure(activebackground=buttonGn)
else:
hal.set_p('db_arc-ok.in', '0')
arcOkB.configure(background=buttonBg)
arcOkB.configure(activebackground=buttonBg)
# if axis is running do it all again in 100mS
if hal.component_exists('axisui') or hal.component_exists('qtplasmac'):
signal.alarm(1)
window.after(100, periodic)
except Exception as e:
unload(e, 'periodic')
def estop_pressed(event):
if hal.get_value('estop_or.in0') == 0:
hal.set_p('estop_or.in0', '1')
estopB.configure(background=buttonRd)
estopB.configure(activebackground=buttonRd)
else:
hal.set_p('estop_or.in0', '0')
estopB.configure(background=buttonGn)
estopB.configure(activebackground=buttonGn)
# MAIN
try:
window = Tk()
window.title('Plasmac Sim')
window.resizable(False,False)
window.attributes('-topmost', True)
S = linuxcnc.stat()
S.poll()
C = linuxcnc.command()
I = linuxcnc.ini(S.ini_filename)
# create new hal component
H = hal.component('plasmac-sim')
H.newpin('z-position', hal.HAL_FLOAT, hal.HAL_IN)
H.ready()
# disconnect any conflicting hal pins
if hal.pin_has_writer('db_arc-ok.in'):
CALL(['halcmd','unlinkp','db_arc-ok.in'])
if hal.pin_has_writer('db_float.in'):
CALL(['halcmd','unlinkp','db_float.in'])
if hal.pin_has_writer('db_ohmic.in'):
CALL(['halcmd','unlinkp','db_ohmic.in'])
if hal.pin_has_writer('db_breakaway.in'):
CALL(['halcmd','unlinkp','db_breakaway.in'])
if hal.pin_has_writer('plasmac.move-up'):
CALL(['halcmd','unlinkp','plasmac.move-up'])
if hal.pin_has_writer('plasmac.move-down'):
CALL(['halcmd','unlinkp','plasmac.move-down'])
# load the simulated torch
CALL(['halcmd', 'loadusr', '-Wn', 'sim-torch', 'sim-torch'])
# connect to existing plasmac connections
CALL(['halcmd', 'net', 'plasmac:torch-on', 'sim-torch.start'])
CALL(['halcmd', 'net', 'plasmac:cut-volts', 'sim-torch.voltage-in'])
# create new sim connection
CALL(['halcmd', 'net', 'sim:arc-voltage-in', 'sim-torch.voltage-out', 'plasmac.arc-voltage-in'])
# connect to existing z axis height
simStepConf = False
for sig in hal.get_info_signals():
if sig['NAME'] == 'Zjoint-pos-fb':
simStepconf = True
break
if simStepConf:
CALL(['halcmd', 'net', 'Zjoint-pos-fb', 'plasmac-sim.z-position'])
else:
CALL(['halcmd', 'net', 'plasmac:axis-position', 'plasmac-sim.z-position'])
# set button colors
buttonRd = '#dd0000'
buttonGn = '#00cc00'
# set python variables
arcOkPressed = False
buttonStart = 0.0
mode = None
units = I.find('TRAJ','LINEAR_UNITS') or 'mm'
if units == 'inch':
probeHeight = hal.get_value('ini.z.min_limit') + 0.8
else:
probeHeight = hal.get_value('ini.z.min_limit') + 20
# set tkinter variables
selectedSensor = IntVar()
# set up arc voltage frame
arcF = LabelFrame(window)
arcF.configure(relief='groove',text='Arc Voltage Offset',highlightbackground='#5e5e5e')
arc_voltage = Scale(arcF, from_=-10, to=10, resolution=0.1)
arc_voltage.configure(length='160',orient='horizontal',command=arc_voltage_changed, \
foreground='#0000dd',font='arial 14')
arc_voltage.pack(padx=2,pady=2,fill='x')
# set up sensor switch frame
switchF = LabelFrame(window)
switchF.configure(relief='groove',text='Switches')
ohmicB = Button(switchF)
ohmicB.configure(borderwidth='2',compound='left',padx=4,width=5,text='OHMIC')
ohmicB.grid(row=0,column=0,sticky='ew')
ohmicB.bind('<Button-1>',lambda e:button_changed(e,ohmicB,'db_ohmic.in'))
ohmicB.bind('<ButtonRelease-1>',lambda e:button_changed(e,ohmicB,'db_ohmic.in'))
floatB = Button(switchF)
floatB.configure(borderwidth='2',compound='left',padx=4,width=5,text='FLOAT')
floatB.grid(row=0,column=1,sticky='ew')
floatB.bind('<Button-1>',lambda e:button_changed(e,floatB,'db_float.in'))
floatB.bind('<ButtonRelease-1>',lambda e:button_changed(e,floatB,'db_float.in'))
breakB = Button(switchF)
breakB.configure(borderwidth='2',compound='left',padx=4,width=5,text='BREAK')
breakB.grid(row=0,column=2,sticky='ew')
breakB.bind('<Button-1>',lambda e:button_changed(e,breakB,'db_breakaway.in'))
breakB.bind('<ButtonRelease-1>',lambda e:button_changed(e,breakB,'db_breakaway.in'))
ohmicC = Radiobutton(switchF)
ohmicC.configure(value='0',indicatoron='0',selectcolor=buttonGn)
ohmicC.configure(variable=selectedSensor)
ohmicC.grid(row=1,column=0,padx=16,pady=4,sticky='ew')
floatC = Radiobutton(switchF)
floatC.configure(value='1',indicatoron='0',selectcolor=buttonGn)
floatC.configure(variable=selectedSensor)
floatC.grid(row=1,column=1,padx=16,pady=4,sticky='ew')
switchF.columnconfigure(0,weight=1)
switchF.columnconfigure(1,weight=1)
switchF.columnconfigure(2,weight=1)
# set up arc ok frame
okF = LabelFrame(window)
okF.configure(relief='groove',text='Arc OK')
arcOkB = Button(okF)
arcOkB.configure(borderwidth='2',compound='left',text='ARC OK')
arcOkB.pack(fill='x')
arcOkB.bind('<Button-1>',lambda e:button_changed(e,arcOkB,'db_arc-ok.in'))
arcOkB.bind('<ButtonRelease-1>',lambda e:button_changed(e,arcOkB,'db_arc-ok.in'))
# set up external thc frame
moveF = LabelFrame(window)
moveF.configure(relief='groove',text='Move')
upB = Button(moveF)
upB.configure(borderwidth='2',compound='left',text='UP',width=4)
upB.grid(row=0,column=0,sticky='ew')
upB.bind('<Button-1>',lambda e:button_changed(e,upB,'plasmac.move-up'))
upB.bind('<ButtonRelease-1>',lambda e:button_changed(e,upB,'plasmac.move-up'))
downB = Button(moveF)
downB.configure(borderwidth='2',compound='left',text='DOWN',width=4)
downB.grid(row=0,column=1,sticky='ew')
downB.bind('<Button-1>',lambda e:button_changed(e,downB,'plasmac.move-down'))
downB.bind('<ButtonRelease-1>',lambda e:button_changed(e,downB,'plasmac.move-down'))
moveF.columnconfigure(0,weight=1)
moveF.columnconfigure(1,weight=1)
# basic estop for axis
CALL(['halcmd', 'net', 'sim:estop-loop', 'iocontrol.0.user-enable-out', 'iocontrol.0.emc-enable-in'])
# set default button color
buttonBg = ohmicB['activebackground']
# default to ohmic if ohmic probe is enabled
if hal.get_value('plasmac.ohmic-probe-enable'):
ohmicC.select()
else:
floatC.select()
# for termination if axis not found
signal.signal(signal.SIGALRM, time_out)
# start periodic running
periodic()
window.mainloop()
except KeyboardInterrupt:
pass
except Exception as e:
unload(e, 'MAIN')

View File

@@ -0,0 +1,65 @@
# GENERIC HAL TCL FILE FOR PLASMAC2 SIM CONFIGS WITH STEPGENS
# ---SET CONSTANTS---
set numJoints $::KINS(JOINTS)
set zAxis [string first "z" [string tolower $::TRAJ(COORDINATES)]]
# ---LOAD COMPONENTS---
loadrt $::KINS(KINEMATICS)
loadrt $::EMCMOT(EMCMOT) base_period_nsec=$::EMCMOT(BASE_PERIOD) servo_period_nsec=$::EMCMOT(SERVO_PERIOD) num_joints=$numJoints num_spindles=$::TRAJ(SPINDLES)
loadrt plasmac
set stepType "0"
for {set jNum 0} {$jNum < $numJoints} {incr jNum} {
if {$jNum > 0} {
append stepType "," "0"
}
loadrt sim_home_switch names=sim-joint.${jNum}.home-switch
}
loadrt stepgen step_type=$stepType
# ---LINK TO THREADS---
addf stepgen.make-pulses base-thread
addf stepgen.capture-position servo-thread
addf motion-command-handler servo-thread
addf motion-controller servo-thread
addf plasmac servo-thread
addf stepgen.update-freq servo-thread
for {set jNum 0} {$jNum < $numJoints} {incr jNum} {
addf sim-joint.${jNum}.home-switch servo-thread
}
# ---JOINT CONNECTIONS---
for {set jNum 0} {$jNum < $numJoints} {incr jNum} {
setp stepgen.${jNum}.maxaccel [set ::JOINT_[set jNum](STEPGEN_MAXACCEL)]
setp stepgen.${jNum}.position-scale [set ::JOINT_[set jNum](STEP_SCALE)]
setp stepgen.${jNum}.steplen [set ::JOINT_[set jNum](STEPLEN)]
setp stepgen.${jNum}.stepspace [set ::JOINT_[set jNum](STEPSPACE)]
setp stepgen.${jNum}.dirsetup [set ::JOINT_[set jNum](DIRSETUP)]
setp stepgen.${jNum}.dirhold [set ::JOINT_[set jNum](DIRHOLD)]
net sim:joint${jNum}.enable joint.${jNum}.amp-enable-out => stepgen.${jNum}.enable
net sim:joint${jNum}.pos-cmd joint.${jNum}.motor-pos-cmd => stepgen.${jNum}.position-cmd
net sim:joint${jNum}.pos-fb stepgen.${jNum}.position-fb => joint.${jNum}.motor-pos-fb sim-joint.${jNum}.home-switch.cur-pos
net sim:joint${jNum}.homesw sim-joint.${jNum}.home-switch.home-sw => joint.${jNum}.home-sw-in
}
# ---INPUT DEBOUNCE---
loadrt dbounce names=db_breakaway,db_float,db_ohmic,db_arc-ok
addf db_float servo-thread
addf db_ohmic servo-thread
addf db_breakaway servo-thread
addf db_arc-ok servo-thread
# ---Z JOINT CONNECTION---
net plasmac:axis-position joint.${zAxis}.pos-fb => plasmac.axis-z-position
# ---TOOL CHANGE PASSTHROUGH
net sim:tool-number <= iocontrol.0.tool-prep-number
net sim:tool-change-loopback iocontrol.0.tool-change => iocontrol.0.tool-changed
net sim:tool-prepare-loopback iocontrol.0.tool-prepare => iocontrol.0.tool-prepared
# ---ESTOP COMPONENTS FOR PLASMAC2---
loadrt or2 names=estop_or
loadrt not names=estop_not,estop_not_1
addf estop_or servo-thread
addf estop_not servo-thread
addf estop_not_1 servo-thread

View File

@@ -0,0 +1,469 @@
#!/usr/bin/python3
'''
migrate.py
'''
import sys
import os
from shutil import *
from tkinter import *
from tkinter import filedialog
import configparser
import gettext
if os.path.dirname(__file__).startswith('/usr/share'):
localeDir = '/usr/share/locale'
INSTYPE = ['pkg', 'linuxcnc']
HALLIB = '/usr/share/linuxcnc/hallib'
else:
path = os.path.dirname(__file__).split('configs')[0]
localeDir = os.path.join(path, 'share/locale')
INSTYPE = ['rip', os.path.join(path, 'scripts/linuxcnc')]
HALLIB = os.path.join(path, 'lib/hallib')
iconPath = os.path.join(os.path.dirname(__file__), 'lib/images/chips_plasma.png')
gettext.install("linuxcnc", localedir=localeDir)
_ = gettext.gettext
class Dialog(Toplevel):
def __init__(self, parent, title, text, buttons=1, insType=False, entry=None):
super().__init__()
# self.transient(parent)
self.grab_set()
self.attributes('-type', 'popup_menu')
self.overrideredirect(True)
self.resizable(False, False)
self.reply = False
self.value = StringVar()
self.entry = entry
self.parent = parent
self.focus_set()
justify = 'left' if 'Migration Log' in title else 'center'
f = Frame(self, relief='ridge', borderwidth=4)
f.grid(row=0, column=1, padx=1, pady=1)
t = Label(f, text=title)
t.grid(row=0, column=0, columnspan=3, sticky='ew')
l = Label(f, text=f"{text}\n", justify=justify)
l.grid(row=1, column=0, columnspan=3, padx=8, pady=(8,0))
if entry:
e = Entry(f, textvariable=self.value, justify='center')
e.grid(row=2, column=0, columnspan=3, sticky='ew', padx=8, pady=(0,8))
e.insert(END, entry)
e.icursor(END)
e.focus_set()
if insType:
text = 'Copy Command'
key = '<c>'
else:
text = 'Cancel'
key = '<Key-Escape>'
b1 = Button(f, text='OK', width=12, command=lambda:self.on_button(1))
self.bb1 = self.bind('<Key-Return>', lambda e:self.on_button(1))
if buttons == 3:
b2 = Button(f, text='View Log', width=12, command=lambda:self.on_button(2))
self.bb2 = self.bind('<v>', lambda e:self.on_button(2))
b2.grid(row=3, column=1, pady=(0,8))
if buttons > 1:
b0 = Button(f, text=text, width=12, command=lambda:self.on_button(0))
self.bb0 = self.bind(key, lambda e:self.on_button(0))
b1.grid(row=3, column=0, sticky='w', padx=(8,0), pady=(0,8))
b0.grid(row=3, column=2, sticky='e', padx=(0,8), pady=(0,8))
else:
b1.grid(row=3, column=1, padx=(0,8), pady=(0,8))
parent.eval(f"tk::PlaceWindow {self} center")
def on_button(self, button):
if button == 2:
title = 'plasmac2 Migration Log'
text = ''
with open(self.parent.logFile, 'r') as inFile:
for line in inFile:
text += line
Dialog(self.parent, title, text).show()
self.reply = 'log'
elif button and self.entry:
self.reply = self.value.get()
else:
self.reply = button
self.parent.focus_set()
self.destroy()
def show(self):
self.wm_deiconify()
self.wait_window()
return self.reply
class Migrate(Tk):
def __init__(self):
super().__init__()
icon = PhotoImage(file=iconPath)
self.eval(f"wm iconphoto . {icon}")
self.title('plasmac2 Migrate')
text = _('Migration utility for plasmac2')
l = Label(self, text=text)
self.label = Label(self, justify='left')
self.migrate_text()
b = Frame(self)
bm = Button(b, text=_('Migrate'), width=10, command=self.migrate, padx=0)
bq = Button(b, text=_('Quit'), width=10, command=self.shutdown, padx=0)
bm.grid(row=0, column=0)
bq.grid(row=0, column=2)
l.grid(row=0, column=0, sticky='ew', padx=8, pady=(8,0))
self.label.grid(row=1, column=0, sticky='ew', padx=8, pady=(8,0))
b.grid(row=3, column=0, sticky='ew', padx=8, pady=(16,8))
b.columnconfigure((0,1,2), weight=1)
self.lcnc = os.path.expanduser('~/linuxcnc')
if not os.path.isdir(self.lcnc):
title = _('Directory Error')
msg1 = _('The directory ~/linuxcnc does not exist')
msg2 = _('It needs to have been created by LinuxCNC')
msg3 = _('and have a working QtPlasmaC configuration')
msg4 = _('to ensure that the structure is correct')
Dialog(self, title, f"{msg1}.\n{msg2}\n{msg3}\n{msg4}.\n").show()
raise SystemExit
if 'root' in self.lcnc:
title = _('User Error')
msg = _('plasmac2 setup can not be run as a root user')
Dialog(self, title, f"{msg}.\n").show()
raise SystemExit
self.configDir = os.path.join(self.lcnc, 'configs')
self.currentDir = os.path.dirname(__file__)
self.prefs = configparser.ConfigParser()
self.prefs.optionxform=str
self.eval(f"tk::PlaceWindow {self} center")
self.bind('<m>', lambda e:self.migrate())
self.bind('<q>', lambda e:self.shutdown())
def migrate(self):
self.migrate_text()
ini = filedialog.askopenfilename(
title='QtPlasmaC INI File',
initialdir=self.configDir,
filetypes=(('ini files', '*.ini'),))
if not ini:
return
iniFile = os.path.basename(ini)
self.oldDir = os.path.dirname(ini)
path, base = self.oldDir.rsplit('/',1)
newBase = f"{base}_plasmac2"
title = _('Directory Name')
msg1 = _('The new directory name will be')
msg2 = _('If you change it to the same name as the QtPlasmaC config')
msg3 = _('then the QtPlasmaC config directory will be renamed to:')
msg4 = _('Accept it or change it then accept')
reply = Dialog(self, title, f"{msg1}: {newBase}\n\n{msg2}\n{msg3}\n{base}_qtplasmac\n\n{msg4}\n", buttons=2, entry=newBase).show()
if reply == base:
try:
orgDir = self.oldDir
self.oldDir = f"{self.oldDir}_qtplasmac"
os.rename(orgDir, self.oldDir)
except Exception as e:
title = 'Directory Error'
msg1 = _('Error while renaming')
Dialog(self, title, f"{msg1}: {orgDir}\n\nto: {self.oldDir}\n\n{e}").show()
return
elif not reply:
return
self.newDir = os.path.join(path, reply)
self.newIni = os.path.join(self.newDir, iniFile)
self.logFile = os.path.join(self.newDir, 'migrate.log')
self.log = []
if os.path.isfile(self.logFile):
os.remove(self.logFile)
if os.path.exists(self.newDir):
title = _('Directory Exists')
msg1 = _('already exists')
msg2 = _('Overwrite')
reply = Dialog(self, title, f"{self.newDir} {msg1}\n\n{msg2}?\n", buttons=2).show()
if not reply:
return
if os.path.isfile(self.newDir) or os.path.islink(self.newDir):
os.remove(self.newDir)
elif os.path.isdir(self.newDir):
rmtree(self.newDir)
try:
ignores = ignore_patterns('qtplasmac','backups','machine_log*.txt', \
'*.qss','*.py','*.bak','qtvcp.prefs','M190', \
'qtplasmac.prefs')
# copy required files
p2Path = os.path.join(self.newDir, 'plasmac2')
copytree(self.oldDir, self.newDir, ignore=ignores)
# remove any existing plasmac2
if os.path.islink(p2Path):
os.remove(p2Path)
elif os.path.exists(p2Path):
os.remove(p2Path)
# create a link to plasmac2
os.symlink(self.currentDir, p2Path)
# copy user custom files
self.copy_custom_files(self.newDir)
self.do_ini_file()
self.do_hal_files()
self.do_prefs_file()
# all done...
path = os.path.join(self.newDir, iniFile)
title = _('Migration Complete')
msg1 = _('The INI file for the plasmac2 config is')
msg2 = _('Copy Command will copy the complete command required to run LinuxCNC using this config')
msg = f"{msg1}:\n\n{path}\n\n{msg2}.\n"
clip = False
btns = 2
if self.log:
with open(self.logFile, 'w') as outFile:
for line in self.log:
outFile.write(line)
msg1 = '-------------------------------------------------'
msg2 = _('Some hal files contain references to qtplasmac and they were commented out in the file')
msg3 = _('There is a log of these files in')
msg4 = _('in the new config directory')
msg += f"\n{msg1}\n\n{msg2}.\n\n{msg3} {os.path.basename(self.logFile)} {msg4}.\n"
btns = 3
while 1:
reply = Dialog(self, title, msg, buttons=btns, insType=INSTYPE[0]).show()
if reply == 1:
if clip:
text1 = _('Warning')
text2 = _('The copied command will be removed from the')
text3 = _('system clipboard when this window is closed')
self.label['text'] = f"{text1}:\n{text2}\n{text3}.\n"
break
elif reply == 0:
clip = True
self.clipboard_clear()
self.clipboard_append(f"{INSTYPE[1]} {path}")
self.update()
except Exception as e:
title = _('Migration error')
line = sys.exc_info()[-1].tb_lineno
msg1 = _('Migration was unsuccessful')
msg2 = _('Error in line')
Dialog(self, title, f"{msg1}.\n\n{msg2}: {line}\n{str(e)}").show()
def do_ini_file(self):
with open(self.newIni, 'r') as inFile:
config = inFile.readlines()
# [DISPLAY] section
section = {}
for lNum in range(config.index('[DISPLAY]\n') + 1, len(config)):
if config[lNum].startswith('['):
break
section[lNum] = config[lNum]
insert = lNum - 1 if config[lNum - 1] == '\n' else lNum
done = []
for lNum in section:
if section[lNum].startswith('DISPLAY') and 'd' not in done:
config[lNum] = 'DISPLAY = axis\n'
done.append('d')
elif section[lNum].startswith('OPEN_FILE') and 'of' not in done:
config[lNum] = 'OPEN_FILE = ""\n'
done.append('of')
elif section[lNum].startswith('TOOL_EDITOR') and 'te' not in done:
config[lNum] = 'TOOL_EDITOR = tooledit x y\n'
done.append('te')
elif section[lNum].startswith('CYCLE_TIME') and 'ct' not in done:
config[lNum] = 'CYCLE_TIME = 100\n'
done.append('ct')
elif section[lNum].startswith('USER_COMMAND_FILE') and 'uc' not in done:
config[lNum] = 'USER_COMMAND_FILE = ./plasmac2/plasmac2.py\n'
done.append('uc')
elif section[lNum].startswith('POSITION_OFFSET') and 'po' not in done:
config[lNum] = 'POSITION_OFFSET = RELATIVE\n'
done.append('po')
elif section[lNum].startswith('POSITION_FEEDBACK') and 'pf' not in done:
config[lNum] = 'POSITION_FEEDBACK = ACTUAL\n'
done.append('pf')
for option in ['d','of','te','ct','uc','po','pf']:
if option == 'd' and option not in done:
config.insert(insert,'DISPLAY = axis\n')
elif option == 'of' and option not in done:
config.insert(insert,'OPEN_FILE = ""\n')
elif option == 'te' and option not in done:
config.insert(insert,'TOOL_EDITOR = tooledit x y\n')
elif option == 'ct' and option not in done:
config.insert(insert,'CYCLE_TIME = 100\n')
elif option == 'uc' and option not in done:
config.insert(insert,'USER_COMMAND_FILE = ./plasmac2/plasmac2.py\n')
elif option == 'po' and option not in done:
config.insert(insert,'POSITION_OFFSET = RELATIVE\n')
elif option == 'pf' and option not in done:
config.insert(insert,'POSITION_FEEDBACK = ACTUAL\n')
# [RS274NGC] section
section = {}
for lNum in range(config.index('[RS274NGC]\n') + 1, len(config)):
if config[lNum].startswith('['):
break
section[lNum] = config[lNum]
insert = lNum - 1 if config[lNum - 1] == '\n' else lNum
done = []
for lNum in section:
if section[lNum].startswith('USER_M_PATH') and 'u' not in done:
mPath = config[lNum].split('=')[1].strip()
config[lNum] = f"USER_M_PATH = ./plasmac2:{mPath}\n"
done.append('u')
for option in ['u']:
if option == 'u' and option not in done:
config.insert(insert,'USER_M_PATH = ./plasmac2:./\n')
# [EMC] section - to get machine name
section = {}
for lNum in range(config.index('[EMC]\n') + 1, len(config)):
if config[lNum].startswith('['):
break
section[lNum] = config[lNum]
insert = lNum - 1 if config[lNum - 1] == '\n' else lNum
done = []
for lNum in section:
if section[lNum].startswith('MACHINE'):
self.machineName = config[lNum].split('=')[1].strip()
# [FILTER] section
section = {}
for lNum in range(config.index('[FILTER]\n') + 1, len(config)):
if config[lNum].startswith('['):
break
section[lNum] = config[lNum]
insert = lNum - 1 if config[lNum - 1] == '\n' else lNum
done = []
for lNum in section:
if section[lNum].startswith('PROGRAM_EXTENSION') and 'p' not in done:
config[lNum] = 'PROGRAM_EXTENSION = .ngc,.nc,.tap (filter gcode files)\n'
done.append('p')
if section[lNum].startswith('ngc') and 'g' not in done:
config[lNum] = 'ngc = qtplasmac_gcode\n'
done.append('g')
if section[lNum].startswith('nc') and 'c' not in done:
config[lNum] = 'nc = qtplasmac_gcode\n'
done.append('c')
if section[lNum].startswith('tap') and 'a' not in done:
config[lNum] = 'tap = qtplasmac_gcode\n'
done.append('a')
for option in ['a','c','g','p']:
if option == 'a' and option not in done:
config.insert(insert,'tap = qtplasmac_gcode\n')
elif option == 'c' and option not in done:
config.insert(insert,'nc = qtplasmac_gcode\n')
elif option == 'g' and option not in done:
config.insert(insert,'ngc = qtplasmac_gcode\n')
elif option == 'p' and option not in done:
config.insert(insert,'PROGRAM_EXTENSION = .ngc,.nc,.tap (filter gcode files)\n')
# [HAL] section
section = {}
self.halList = []
sim = False
self.qtplasmacHal = []
for lNum in range(config.index('[HAL]\n') + 1, len(config)):
if config[lNum].startswith('['):
break
section[lNum] = config[lNum]
for lNum in section:
if section[lNum].startswith('HALFILE') or \
section[lNum].startswith('POSTGUI_HALFILE') or \
section[lNum].startswith('SHUTDOWN'):
halFileRaw = config[lNum].split('=')[1].strip()
if os.path.isfile(os.path.join(HALLIB, halFileRaw)):
halFile = os.path.join(HALLIB, halFileRaw)
else:
halFile = os.path.realpath(os.path.join(self.oldDir, halFileRaw))
self.halList.append(halFileRaw)
# if existing config is a sim
if 'sim_postgui' in halFile:
sim = True
config[lNum] = ''
elif 'sim_no_stepgen.tcl' in halFile:
config[lNum] = 'HALFILE = plasmac2/lib/sim/sim_no_stepgen.tcl\n'
sim = True
elif 'sim_stepgen.tcl' in halFile:
config[lNum] = 'HALFILE = plasmac2/lib/sim/sim_stepgen.tcl\n'
sim = True
elif 'sim_' in halFile:
sim = True
# add sim panel if required
if sim:
app1 = '[APPLICATIONS]'
app2 = 'DELAY = 2'
app3 = 'APP = plasmac2/lib/sim/sim_panel.py'
config.insert(0, f"{app1}\n{app2}\n{app3}\n\n")
# write the ini file
with open(self.newIni, 'w') as outFile:
for line in config:
outFile.write(line)
def do_hal_files(self):
validPins = ['out_0', 'out_1', 'out_2', 'abort','frame-job','pause', \
'power','probe','pulse','run','run-pause','touchoff']
for file in self.halList:
if not os.path.dirname(file):
halFile = os.path.join(self.newDir, file)
edit = False
logged = False
with open(halFile, 'r') as inFile:
config = inFile.readlines()
for lNum in range(len(config)):
if 'qtplasmac.ext_' in config[lNum]:
for pin in validPins:
if f"qtplasmac.ext_{pin}" in config[lNum]:
config[lNum] = config[lNum].replace(f"qtplasmac.ext_{pin}", f"axisui.ext.{pin}")
edit = True
if 'qtplasmac' in config[lNum] or 'sim-torch' in config[lNum]:
config[lNum] = f"# MIGRATION: {config[lNum]}"
edit = True
if not logged:
self.log.append(f"\n{file}\n")
logged = True
self.log.append(f"{lNum+1} - {config[lNum]}")
# write the hal fil
if edit:
with open(halFile, 'w') as outFile:
for line in config:
outFile.write(line)
def do_prefs_file(self):
prefsFile = os.path.join(self.newDir, f"{self.machineName}.prefs")
with open(prefsFile, 'r') as inFile:
config = inFile.readlines()
# [BUTTONS] section
edit = False
section = {}
for lNum in range(config.index('[BUTTONS]\n') + 1, len(config)):
if config[lNum].startswith('['):
break
section[lNum] = config[lNum]
for lNum in section:
if 'Name =' in section[lNum]:
name, value = config[lNum].split('=')
value = value.replace('\\',' ').replace('&&', '& ')
config[lNum] = f"{name}={value}"
edit = True
if 'Code =' in section[lNum] and 'offsets-view' in section[lNum]:
config[lNum-1] = f"{config[lNum-1].split('=')[0]}= \n"
config[lNum] = f"{config[lNum].split('=')[0]}= \n"
self.log.append(f"\n{self.machineName}.prefs\n")
text1 = _('is not available in plasmac2')
text2 = _('it has been removed from the prefs file')
self.log.append(f"{lNum} & {lNum+1} - offsets-view {text1}, {text2}.\n")
edit = True
elif 'qtplasmac.ext_' in config[lNum]:
config[lNum] = config[lNum].replace('qtplasmac.ext_','axisui.ext.')
edit = True
# write the prefs file
if edit:
with open(prefsFile, 'w') as outFile:
for line in config:
outFile.write(line)
def copy_custom_files(self, dir):
for f in ['commands', 'hal', 'periodic']:
src = os.path.join(self.currentDir, 'lib/custom', f"user_{f}.py")
copy(src, os.path.join(dir, '.'))
def migrate_text(self):
text1 = _('Makes a copy of an existing working QtPlasmaC config')
text2 = _('Then converts that copy to a working plasmac2 config')
self.label['text'] = f"{text1}.\n\n{text2}.\n"
def shutdown(self):
raise SystemExit
if __name__ == "__main__":
migrate = Migrate()
migrate.mainloop()

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,153 @@
<!DOCTYPE html>
<html>
<head>
<h2>plasmac2 Version History</h2>
</head>
<body>
<!--- ****** ADD NEXT VERSION BELOW THESE LINES ****** --->
<!--- ****** THE MAJOR VERSION WILL ALWAYS BE 2 ****** --->
<!--- ------------------------------------------------ --->
<br><b><u>v2.21</b> 2024 Oct 18</u>
<ul style="margin:0;">
<li>move m190 and fix pathing</li>
<li>update prefs files</li>
<li>change comments in tcl hal files</li>
<li>add error prints in sim panel</li>
<li>delete some menu entries</li>
<li>remove menu tearoffs</li>
</ul>
<br><b><u>v2.20</b> 2024 May 01</u>
<ul style="margin:0;">
<li>add single cutpath to run from line</li>
<li>add dry run button and dry run without probing</li>
<li>make conversational tab order more consistent with qtplasmac</li>
</ul>
<br><b><u>v2.19</b> 2024 Mar 24</u>
<ul style="margin:0;">
<li>use real USER_M_PATH in package configs</li>
</ul>
<br><b><u>v2.18</b> 2024 Mar 15</u>
<ul style="margin:0;">
<li>fix table view for all coordinates</li>
<li>add materials to conversational preview</li>
<li>add clear program to file menu</li>
</ul>
<br><b><u>v2.17</b> 2024 Feb 05</u>
<ul style="margin:0;">
<li>fix file reload</li>
</ul>
<br><b><u>v2.16</b> 2024 Feb 03</u>
<ul style="margin:0;">
<li>disable g92 offsets</li>
</ul>
<br><b><u>v2.15</b> 2024 Jan 30</u>
<ul style="margin:0;">
<li>set user_m_path to include /nc_files/plasmac/m_files</li>
<li>reset moving pierce on program end</li>
<li>make offsets_text a function</li>
</ul>
<br><b><u>v2.14</b> 2024 Jan 15</u>
<ul style="margin:0;">
<li>fix alternate text for toggle halpin</li>
<li>add runcritical toggle pins to manual cut</li>
<li>allow "cutcritical" from qtplasmac configs</li>
<li>stop using auto preview in conversational</li>
</ul>
<br><b><u>v2.13</b> 2023 Nov 05</u>
<ul style="margin:0;">
<li>add dual code user button</li>
<li>allow alternate text on toggle halpin buttons</li>
<li>make dro overlay transparent</li>
<li>fix help/about text</li>
<li>allow negative x/y pierce offsets</li>
</ul>
<br><b><u>v2.12</b> 2023 Oct 31</u>
<ul style="margin:0;">
<li>add x/y offsets for pierce only mode</li>
</ul>
<br><b><u>v2.11</b> 2023 Oct 28</u>
<ul style="margin:0;">
<li>add adjustable x/y axes velocity for offset probing</li>
</ul>
<br><b><u>v2.10</b> 2023 Oct 23</u>
<ul style="margin:0;">
<li>fix zoom with right click</li>
</ul>
<br><b><u>v2.9</b> 2023 Sep 22</u>
<ul style="margin:0;">
<li>changes to modules for consistency</li>
</ul>
<br><b><u>v2.8</b> 2023 Sep 22</u>
<ul style="margin:0;">
<li>use eval instead of call for tcl commands</li>
<li>code consistencies for f strings</li>
<li>add comments for patched functions</li>
<li>remove some redundencies</li>
<li>some code tidying</li>
</ul>
<br><b><u>v2.7</b> 2023 Sep 19</u>
<ul style="margin:0;">
<li>allow abort during mdi from user buttons</li>
<li>declutter notifications</li>
<li>improve user button parameter handling</li>
</ul>
<br><b><u>v2.6</b> 2023 Aug 28</u>
<ul style="margin:0;">
<li>make material handling more consistent with QtPlasmaC</li>
<li>more sane conversational defaults</li>
<li>fix translations in conversational settings</li>
<li>suppress pylance errors in vscode</li>
</ul>
<br><b><u>v2.5</b> 2023 Aug 20</u>
<ul style="margin:0;">
<li>variable user button width</li>
<li>fix hidden startup notifications</li>
<li>ensure correct types in preferences</li>
</ul>
<br><b><u>v2.4</b> 2023 Aug 18</u>
<ul style="margin:0;">
<li>allow prefs file options in user buttons code</li>
</ul>
<br><b><u>v2.3</b> 2023 Jul 26</u>
<ul style="margin:0;">
<li>fix default material selection from g-code</li>
</ul>
<br><b><u>v2.2</b> 2023 May 13</u>
<ul style="margin:0;">
<li>enable halpin toggle/pulse user buttons while not idle</li>
<li>powermax comms rework</li>
<li>fix some message capitalization</li>
<li>show the user manual in a web browser</li>
<li>make feed rate not mandatory for consumable change</li>
</ul>
<br><b><u>v2.1</b> 2023 Apr 24</u>
<ul style="margin:0;">
<li>remove unneeded bounds check</li>
</ul>
<br><b><u>v2.0</b> 2023 Mar 29</u>
<ul style="margin:0;">
<li>initial upload to configs/sim/axis/</li>
</ul>
</body>
</html>

View File

@@ -0,0 +1,5 @@
# CUSTOM PYTHON CODE, RUNS ONCE AT STARTUP
# see the file customizing.html for some tips
# example to hide the height override frame
#rE(f"grid forget {foverride}")

View File

@@ -0,0 +1,6 @@
# CUSTOM HAL PINS, RUNS ONCE AT STARTUP
# see the file customizing.html for some tips
# example to create a HAL floating point input pin and a HAL bit input pin
#comp.newpin('my-halfloat', hal.HAL_FLOAT, hal.HAL_IN)
#comp.newpin('my-halbit', hal.HAL_BIT, hal.HAL_IN)

View File

@@ -0,0 +1,9 @@
# CUSTOM PERIODIC CODE, RUNS ONCE EVERY CYCLE
# see the file customizing.html for some tips
# example to create a file with all the widget names if a hal pin is not zero
#if comp['my-halbit']:
# widgets = get_all_children('.')
# with open('./widgets.txt', 'w') as outFile:
# for widget in sorted(widgets):
# outFile.write(f'{widget}\n')