#!/usr/bin/python
"""
K40 Whisperer Now with CLI!!!
Copyright (C) <2018>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
"""
version = '0.19'
title_text = "K40 Whisperer V"+version
import matplotlib
matplotlib.use('Agg')
import sys
from math import *
from egv import egv
from nano_library import K40_CLASS
from dxf import DXF_CLASS
from svg_reader import SVG_READER
from svg_reader import SVG_TEXT_EXCEPTION
from g_code_library import G_Code_Rip
from interpolate import interpolate
import inkex
import simplestyle
import simpletransform
import cubicsuperpath
import cspsubdiv
import traceback
#DEBUG = True
DEBUG = False
VERSION = sys.version_info[0]
LOAD_MSG = ""
if VERSION == 3:
from tkinter import *
from tkinter.filedialog import *
import tkinter.messagebox
MAXINT = sys.maxsize
else:
from Tkinter import *
from tkFileDialog import *
import tkMessageBox
MAXINT = sys.maxint
if VERSION < 3 and sys.version_info[1] < 6:
def next(item):
return item.next()
try:
import psyco
psyco.full()
LOAD_MSG = LOAD_MSG+"\nPsyco Loaded\n"
except:
pass
import math
from time import time
import os
import re
import binascii
import getopt
import operator
import webbrowser
from PIL import Image
from PIL import ImageOps
try:
Image.warnings.simplefilter('ignore', Image.DecompressionBombWarning)
except:
pass
try:
from PIL import ImageTk
from PIL import _imaging
except:
pass #Don't worry everything will still work
QUIET = False
class ECoord():
def __init__(self):
self.reset()
def reset(self):
self.image = None
self.reset_path()
def reset_path(self):
self.ecoords = []
self.len = 0
self.move = 0
self.sorted = False
self.bounds = (0,0,0,0)
self.gcode_time = 0
def make_ecoords(self,coords,scale=1):
self.reset()
self.len = 0
self.move = 0
xmax, ymax = -1e10, -1e10
xmin, ymin = 1e10, 1e10
self.ecoords=[]
Acc=.001
oldx = oldy = -99990.0
first_stroke = True
loop=0
for line in coords:
XY = line
x1 = XY[0]*scale
y1 = XY[1]*scale
x2 = XY[2]*scale
y2 = XY[3]*scale
dxline= x2-x1
dyline= y2-y1
len_line=sqrt(dxline*dxline + dyline*dyline)
dx = oldx - x1
dy = oldy - y1
dist = sqrt(dx*dx + dy*dy)
# check and see if we need to move to a new discontinuous start point
if (dist > Acc) or first_stroke:
loop = loop+1
self.ecoords.append([x1,y1,loop])
if not first_stroke:
self.move = self.move + dist
first_stroke = False
self.len = self.len + len_line
self.ecoords.append([x2,y2,loop])
oldx, oldy = x2, y2
xmax=max(xmax,x1,x2)
ymax=max(ymax,y1,y2)
xmin=min(xmin,x1,x2)
ymin=min(ymin,y1,y2)
self.bounds = (xmin,xmax,ymin,ymax)
def set_ecoords(self,ecoords,data_sorted=False):
self.ecoords = ecoords
self.computeEcoordsLen()
self.data_sorted=data_sorted
def set_image(self,PIL_image):
self.image = PIL_image
def computeEcoordsLen(self):
xmax, ymax = -1e10, -1e10
xmin, ymin = 1e10, 1e10
if self.ecoords == [] :
return
on = 0
move = 0
time = 0
for i in range(2,len(self.ecoords)):
x1 = self.ecoords[i-1][0]
y1 = self.ecoords[i-1][1]
x2 = self.ecoords[i][0]
y2 = self.ecoords[i][1]
loop = self.ecoords[i ][2]
loop_last = self.ecoords[i-1][2]
xmax=max(xmax,x1,x2)
ymax=max(ymax,y1,y2)
xmin=min(xmin,x1,x2)
ymin=min(ymin,y1,y2)
dx = x2-x1
dy = y2-y1
dist = sqrt(dx*dx + dy*dy)
if len(self.ecoords[i]) > 3:
feed = self.ecoords[i][3]
time = time + dist/feed*60
if loop == loop_last:
on = on + dist
else:
move = move + dist
#print "on= ",on," move= ",move
self.bounds = (xmin,xmax,ymin,ymax)
self.len = on
self.move = move
self.gcode_time = time
################################################################################
class Application(Frame):
def __init__(self, master):
Frame.__init__(self, master)
self.w = 780
self.h = 490
frame = Frame(master, width= self.w, height=self.h)
self.master = master
self.x = -1
self.y = -1
self.createWidgets()
def resetPath(self):
self.RengData = ECoord()
self.VengData = ECoord()
self.VcutData = ECoord()
self.GcodeData = ECoord()
self.SCALE = 1
self.Design_bounds = (0,0,0,0)
self.UI_image = None
#if self.HomeUR.get():
self.move_head_window_temporary([0.0,0.0])
#else:
# self.move_head_window_temporary([0.0,0.0])
self.pos_offset=[0.0,0.0]
def createWidgets(self):
self.initComplete = 0
self.stop=[]
self.stop.append(False)
self.k40 = None
self.master.bind("", self.Master_Configure)
self.master.bind('', self.bindConfigure)
self.master.bind('', self.KEY_F1)
self.master.bind('', self.KEY_F5)
self.master.bind('' , self.Move_Left)
self.master.bind('', self.Move_Right)
self.master.bind('' , self.Move_Up)
self.master.bind('' , self.Move_Down)
self.include_Reng = BooleanVar()
self.include_Rpth = BooleanVar()
self.include_Veng = BooleanVar()
self.include_Vcut = BooleanVar()
self.include_Gcde = BooleanVar()
self.include_Time = BooleanVar()
self.advanced = BooleanVar()
self.halftone = BooleanVar()
self.mirror = BooleanVar()
self.rotate = BooleanVar()
self.inputCSYS = BooleanVar()
self.HomeUR = BooleanVar()
self.engraveUP = BooleanVar()
self.init_home = BooleanVar()
self.pre_pr_crc = BooleanVar()
self.inside_first = BooleanVar()
self.ht_size = StringVar()
self.Reng_feed = StringVar()
self.Veng_feed = StringVar()
self.Vcut_feed = StringVar()
self.Reng_passes = StringVar()
self.Veng_passes = StringVar()
self.Vcut_passes = StringVar()
self.Gcde_passes = StringVar()
self.board_name = StringVar()
self.units = StringVar()
self.jog_step = StringVar()
self.rast_step = StringVar()
self.funits = StringVar()
self.bezier_M1 = StringVar()
self.bezier_M2 = StringVar()
self.bezier_weight = StringVar()
self.LaserXsize = StringVar()
self.LaserYsize = StringVar()
self.LaserXscale = StringVar()
self.LaserYscale = StringVar()
self.gotoX = StringVar()
self.gotoY = StringVar()
self.inkscape_path = StringVar()
self.t_timeout = StringVar()
self.n_timeouts = StringVar()
self.Reng_time = StringVar()
self.Veng_time = StringVar()
self.Vcut_time = StringVar()
self.Gcde_time = StringVar()
###########################################################################
# INITILIZE VARIABLES #
# if you want to change a default setting this is the place to do it #
###########################################################################
self.include_Reng.set(1)
self.include_Rpth.set(0)
self.include_Veng.set(1)
self.include_Vcut.set(1)
self.include_Gcde.set(1)
self.include_Time.set(0)
self.advanced.set(0)
self.halftone.set(0)
self.mirror.set(0)
self.rotate.set(0)
self.inputCSYS.set(0)
self.HomeUR.set(0)
self.engraveUP.set(0)
self.init_home.set(1)
self.pre_pr_crc.set(1)
self.inside_first.set(1)
self.ht_size.set(500)
self.Reng_feed.set("100")
self.Veng_feed.set("20")
self.Vcut_feed.set("10")
self.Reng_passes.set("1")
self.Veng_passes.set("1")
self.Vcut_passes.set("1")
self.Gcde_passes.set("1")
self.jog_step.set("10.0")
self.rast_step.set("0.002")
self.bezier_weight.set("3.5")
self.bezier_M1.set("2.5")
self.bezier_M2.set("0.50")
self.bezier_weight_default = float(self.bezier_weight.get())
self.bezier_M1_default = float(self.bezier_M1.get())
self.bezier_M2_default = float(self.bezier_M2.get())
self.board_name.set("LASER-M2") # Options are
# "LASER-M2",
# "LASER-M1",
# "LASER-M",
# "LASER-B2",
# "LASER-B1",
# "LASER-B",
# "LASER-A"
self.units.set("mm") # Options are "in" and "mm"
self.t_timeout.set("2000")
self.n_timeouts.set("30")
self.HOME_DIR = os.path.expanduser("~")
if not os.path.isdir(self.HOME_DIR):
self.HOME_DIR = ""
self.DESIGN_FILE = (self.HOME_DIR+"/None")
self.aspect_ratio = 0
self.segID = []
self.LaserXsize.set("325")
self.LaserYsize.set("220")
self.LaserXscale.set("1.000")
self.LaserYscale.set("1.000")
self.gotoX.set("0.0")
self.gotoY.set("0.0")
self.laserX = 0.0
self.laserY = 0.0
self.PlotScale = 1.0
# PAN and ZOOM STUFF
self.panx = 0
self.panx = 0
self.lastx = 0
self.lasty = 0
self.move_start_x = 0
self.move_start_y = 0
self.RengData = ECoord()
self.VengData = ECoord()
self.VcutData = ECoord()
self.GcodeData = ECoord()
self.SCALE = 1
self.Design_bounds = (0,0,0,0)
self.UI_image = None
self.pos_offset=[0.0,0.0]
# Derived variables
if self.units.get() == 'in':
self.funits.set('in/min')
self.units_scale = 1.0
else:
self.units.set('mm')
self.funits.set('mm/s')
self.units_scale = 25.4
self.statusMessage = StringVar()
self.statusMessage.set("Welcome to K40 Whisperer")
self.Reng_time.set("0")
self.Veng_time.set("0")
self.Vcut_time.set("0")
self.Gcde_time.set("0")
##########################################################################
### END INITILIZING VARIABLES ###
##########################################################################
# make a Status Bar
self.statusbar = Label(self.master, textvariable=self.statusMessage, \
bd=1, relief=SUNKEN , height=1)
self.statusbar.pack(anchor=SW, fill=X, side=BOTTOM)
# Canvas
lbframe = Frame( self.master )
self.PreviewCanvas_frame = lbframe
self.PreviewCanvas = Canvas(lbframe, width=self.w-(220+20), height=self.h-200, background="grey")
self.PreviewCanvas.pack(side=LEFT, fill=BOTH, expand=1)
self.PreviewCanvas_frame.place(x=230, y=10)
self.PreviewCanvas.tag_bind('LaserTag',"<1>" , self.mousePanStart)
self.PreviewCanvas.tag_bind('LaserTag',"" , self.mousePan)
self.PreviewCanvas.tag_bind('LaserTag',"", self.mousePanStop)
# Left Column #
self.separator1 = Frame(self.master, height=2, bd=1, relief=SUNKEN)
self.separator2 = Frame(self.master, height=2, bd=1, relief=SUNKEN)
self.separator3 = Frame(self.master, height=2, bd=1, relief=SUNKEN)
self.separator4 = Frame(self.master, height=2, bd=1, relief=SUNKEN)
self.Label_Reng_feed_u = Label(self.master,textvariable=self.funits, anchor=W)
self.Entry_Reng_feed = Entry(self.master,width="15")
self.Entry_Reng_feed.configure(textvariable=self.Reng_feed,justify='center',fg="black")
self.Reng_feed.trace_variable("w", self.Entry_Reng_feed_Callback)
self.NormalColor = self.Entry_Reng_feed.cget('bg')
self.Label_Veng_feed_u = Label(self.master,textvariable=self.funits, anchor=W)
self.Entry_Veng_feed = Entry(self.master,width="15")
self.Entry_Veng_feed.configure(textvariable=self.Veng_feed,justify='center',fg="blue")
self.Veng_feed.trace_variable("w", self.Entry_Veng_feed_Callback)
self.NormalColor = self.Entry_Veng_feed.cget('bg')
self.Label_Vcut_feed_u = Label(self.master,textvariable=self.funits, anchor=W)
self.Entry_Vcut_feed = Entry(self.master,width="15")
self.Entry_Vcut_feed.configure(textvariable=self.Vcut_feed,justify='center',fg="red")
self.Vcut_feed.trace_variable("w", self.Entry_Vcut_feed_Callback)
self.NormalColor = self.Entry_Vcut_feed.cget('bg')
# Buttons
self.Reng_Button = Button(self.master,text="Raster Engrave", command=self.Raster_Eng)
self.Veng_Button = Button(self.master,text="Vector Engrave", command=self.Vector_Eng)
self.Vcut_Button = Button(self.master,text="Vector Cut" , command=self.Vector_Cut)
self.Grun_Button = Button(self.master,text="Run G-Code" , command=self.Gcode_Cut)
self.Label_Position_Control = Label(self.master,text="Position Controls:", anchor=W)
self.Initialize_Button = Button(self.master,text="Initialize Laser Cutter", command=self.Initialize_Laser)
self.Open_Button = Button(self.master,text="Open\nDesign File", command=self.menu_File_Open_Design)
self.Reload_Button = Button(self.master,text="Reload\nDesign File", command=self.menu_Reload_Design)
self.Home_Button = Button(self.master,text="Home", command=self.Home)
self.UnLock_Button = Button(self.master,text="Unlock Rail", command=self.Unlock)
self.Stop_Button = Button(self.master,text="Stop", command=self.Stop)
try:
self.left_image = self.Imaging_Free(Image.open("left.png"),bg=None)
self.right_image = self.Imaging_Free(Image.open("right.png"),bg=None)
self.up_image = self.Imaging_Free(Image.open("up.png"),bg=None)
self.down_image = self.Imaging_Free(Image.open("down.png"),bg=None)
self.Right_Button = Button(self.master,image=self.right_image, command=self.Move_Right)
self.Left_Button = Button(self.master,image=self.left_image, command=self.Move_Left)
self.Up_Button = Button(self.master,image=self.up_image, command=self.Move_Up)
self.Down_Button = Button(self.master,image=self.down_image, command=self.Move_Down)
self.UL_image = self.Imaging_Free(Image.open("UL.png"),bg=None)
self.UR_image = self.Imaging_Free(Image.open("UR.png"),bg=None)
self.LR_image = self.Imaging_Free(Image.open("LR.png"),bg=None)
self.LL_image = self.Imaging_Free(Image.open("LL.png"),bg=None)
self.CC_image = self.Imaging_Free(Image.open("CC.png"),bg=None)
self.UL_Button = Button(self.master,image=self.UL_image, command=self.Move_UL)
self.UR_Button = Button(self.master,image=self.UR_image, command=self.Move_UR)
self.LR_Button = Button(self.master,image=self.LR_image, command=self.Move_LR)
self.LL_Button = Button(self.master,image=self.LL_image, command=self.Move_LL)
self.CC_Button = Button(self.master,image=self.CC_image, command=self.Move_CC)
except:
self.Right_Button = Button(self.master,text=">", command=self.Move_Right)
self.Left_Button = Button(self.master,text="<", command=self.Move_Left)
self.Up_Button = Button(self.master,text="^", command=self.Move_Up)
self.Down_Button = Button(self.master,text="v", command=self.Move_Down)
self.UL_Button = Button(self.master,text=" ", command=self.Move_UL)
self.UR_Button = Button(self.master,text=" ", command=self.Move_UR)
self.LR_Button = Button(self.master,text=" ", command=self.Move_LR)
self.LL_Button = Button(self.master,text=" ", command=self.Move_LL)
self.CC_Button = Button(self.master,text=" ", command=self.Move_CC)
self.Label_Step = Label(self.master,text="Jog Step", anchor=CENTER )
self.Label_Step_u = Label(self.master,textvariable=self.units, anchor=W)
self.Entry_Step = Entry(self.master,width="15")
self.Entry_Step.configure(textvariable=self.jog_step, justify='center')
self.jog_step.trace_variable("w", self.Entry_Step_Callback)
###########################################################################
self.GoTo_Button = Button(self.master,text="Move To", command=self.GoTo)
self.Entry_GoToX = Entry(self.master,width="15",justify='center')
self.Entry_GoToX.configure(textvariable=self.gotoX)
self.gotoX.trace_variable("w", self.Entry_GoToX_Callback)
self.Entry_GoToY = Entry(self.master,width="15",justify='center')
self.Entry_GoToY.configure(textvariable=self.gotoY)
self.gotoY.trace_variable("w", self.Entry_GoToY_Callback)
self.Label_GoToX = Label(self.master,text="X", anchor=CENTER )
self.Label_GoToY = Label(self.master,text="Y", anchor=CENTER )
###########################################################################
# End Left Column #
# Advanced Column #
self.separator_vert = Frame(self.master, height=2, bd=1, relief=SUNKEN)
self.Label_Advanced_column = Label(self.master,text="Advanced Settings",anchor=CENTER)
self.separator_adv = Frame(self.master, height=2, bd=1, relief=SUNKEN)
self.Label_Halftone_adv = Label(self.master,text="Halftone (Dither)")
self.Checkbutton_Halftone_adv = Checkbutton(self.master,text=" ", anchor=W)
self.Checkbutton_Halftone_adv.configure(variable=self.halftone)
self.halftone.trace_variable("w", self.menu_View_Refresh_Callback)
self.Label_Mirror_adv = Label(self.master,text="Mirror Design")
self.Checkbutton_Mirror_adv = Checkbutton(self.master,text=" ", anchor=W)
self.Checkbutton_Mirror_adv.configure(variable=self.mirror)
self.mirror.trace_variable("w", self.menu_View_Mirror_Refresh_Callback)
self.Label_Rotate_adv = Label(self.master,text="Rotate Design")
self.Checkbutton_Rotate_adv = Checkbutton(self.master,text=" ", anchor=W)
self.Checkbutton_Rotate_adv.configure(variable=self.rotate)
self.rotate.trace_variable("w", self.menu_View_Mirror_Refresh_Callback)
self.Label_inputCSYS_adv = Label(self.master,text="Use Input CSYS")
self.Checkbutton_inputCSYS_adv = Checkbutton(self.master,text=" ", anchor=W)
self.Checkbutton_inputCSYS_adv.configure(variable=self.inputCSYS)
self.inputCSYS.trace_variable("w", self.menu_View_inputCSYS_Refresh_Callback)
self.Label_Inside_First_adv = Label(self.master,text="Cut Inside First")
self.Checkbutton_Inside_First_adv = Checkbutton(self.master,text=" ", anchor=W)
self.Checkbutton_Inside_First_adv.configure(variable=self.inside_first)
self.inside_first.trace_variable("w", self.menu_Inside_First_Callback)
self.Label_Reng_passes = Label(self.master,text="Raster Eng. Passes")
self.Entry_Reng_passes = Entry(self.master,width="15")
self.Entry_Reng_passes.configure(textvariable=self.Reng_passes,justify='center',fg="black")
self.Reng_passes.trace_variable("w", self.Entry_Reng_passes_Callback)
self.NormalColor = self.Entry_Reng_passes.cget('bg')
self.Label_Veng_passes = Label(self.master,text="Vector Eng. Passes")
self.Entry_Veng_passes = Entry(self.master,width="15")
self.Entry_Veng_passes.configure(textvariable=self.Veng_passes,justify='center',fg="blue")
self.Veng_passes.trace_variable("w", self.Entry_Veng_passes_Callback)
self.NormalColor = self.Entry_Veng_passes.cget('bg')
self.Label_Vcut_passes = Label(self.master,text="Vector Cut Passes")
self.Entry_Vcut_passes = Entry(self.master,width="15")
self.Entry_Vcut_passes.configure(textvariable=self.Vcut_passes,justify='center',fg="red")
self.Vcut_passes.trace_variable("w", self.Entry_Vcut_passes_Callback)
self.NormalColor = self.Entry_Vcut_passes.cget('bg')
self.Label_Gcde_passes = Label(self.master,text="G-Code Passes")
self.Entry_Gcde_passes = Entry(self.master,width="15")
self.Entry_Gcde_passes.configure(textvariable=self.Gcde_passes,justify='center',fg="black")
self.Gcde_passes.trace_variable("w", self.Entry_Gcde_passes_Callback)
self.NormalColor = self.Entry_Gcde_passes.cget('bg')
self.Hide_Adv_Button = Button(self.master,text="Hide Advanced", command=self.Hide_Advanced)
# End Right Column #
#GEN Setting Window Entry initializations
self.Entry_Sspeed = Entry()
self.Entry_BoxGap = Entry()
self.Entry_ContAngle = Entry()
# Make Menu Bar
self.menuBar = Menu(self.master, relief = "raised", bd=2)
top_File = Menu(self.menuBar, tearoff=0)
top_File.add("command", label = "Save Settings File", command = self.menu_File_Save)
top_File.add("command", label = "Read Settings File", command = self.menu_File_Open_Settings_File)
top_File.add_separator()
top_File.add("command", label = "Open Design (SVG/DXF/G-Code)" , command = self.menu_File_Open_Design)
top_File.add("command", label = "Reload Design" , command = self.menu_Reload_Design)
if DEBUG:
top_File.add_separator()
top_File.add("command", label = "Open EGV File" , command = self.menu_File_Open_EGV)
top_File.add_separator()
top_File.add("command", label = "Exit" , command = self.menu_File_Quit)
self.menuBar.add("cascade", label="File", menu=top_File)
#top_Edit = Menu(self.menuBar, tearoff=0)
#self.menuBar.add("cascade", label="Edit", menu=top_Edit)
top_View = Menu(self.menuBar, tearoff=0)
top_View.add("command", label = "Refresh ", command = self.menu_View_Refresh)
top_View.add_separator()
top_View.add_checkbutton(label = "Show Raster Image" , variable=self.include_Reng ,command= self.menu_View_Refresh)
if DEBUG:
top_View.add_checkbutton(label = "Show Raster Paths" , variable=self.include_Rpth ,command= self.menu_View_Refresh)
top_View.add_checkbutton(label = "Show Vector Engrave", variable=self.include_Veng ,command= self.menu_View_Refresh)
top_View.add_checkbutton(label = "Show Vector Cut" , variable=self.include_Vcut ,command= self.menu_View_Refresh)
top_View.add_checkbutton(label = "Show G-Code Paths" , variable=self.include_Gcde ,command= self.menu_View_Refresh)
top_View.add_checkbutton(label = "Show Time Estimates", variable=self.include_Time ,command= self.menu_View_Refresh)
#top_View.add_separator()
#top_View.add("command", label = "computeAccurateReng",command= self.computeAccurateReng)
#top_View.add("command", label = "computeAccurateVeng",command= self.computeAccurateVeng)
#top_View.add("command", label = "computeAccurateVcut",command= self.computeAccurateVcut)
self.menuBar.add("cascade", label="View", menu=top_View)
top_USB = Menu(self.menuBar, tearoff=0)
top_USB.add("command", label = "Reset USB", command = self.Reset)
top_USB.add("command", label = "Release USB", command = self.Release_USB)
top_USB.add("command", label = "Initialize Laser", command = self.Initialize_Laser)
self.menuBar.add("cascade", label="USB", menu=top_USB)
top_Settings = Menu(self.menuBar, tearoff=0)
top_Settings.add("command", label = "General Settings", command = self.GEN_Settings_Window)
top_Settings.add("command", label = "Raster Settings", command = self.RASTER_Settings_Window)
top_Settings.add_separator()
top_Settings.add_checkbutton(label = "Advanced Settings", variable=self.advanced ,command= self.menu_View_Refresh)
self.menuBar.add("cascade", label="Settings", menu=top_Settings)
top_Help = Menu(self.menuBar, tearoff=0)
top_Help.add("command", label = "About (e-mail)", command = self.menu_Help_About)
top_Help.add("command", label = "Web Page", command = self.menu_Help_Web)
self.menuBar.add("cascade", label="Help", menu=top_Help)
self.master.config(menu=self.menuBar)
##########################################################################
# Config File and command line options #
##########################################################################
config_file = "k40_whisperer.txt"
home_config1 = self.HOME_DIR + "/" + config_file
if ( os.path.isfile(config_file) ):
self.Open_Settings_File(config_file)
elif ( os.path.isfile(home_config1) ):
self.Open_Settings_File(home_config1)
arguments = len(sys.argv) - 1
if arguments >=1:
# read commandline arguments, first
fullCmdArguments = sys.argv
# - further arguments
argumentList = fullCmdArguments[1:]
#opts, args = getopt.getopt(sys.argv[1:], "ho:v", ["help", "output="])
unixOptions = "cghHio:rsnvVux:y:"
gnuOptions = ["help","go","stop","home","init","open","cut","raster", "vector", "verbose","unlock"]
try:
arguments, values = getopt.getopt(argumentList, unixOptions, gnuOptions)
except getopt.error as err:
# output error, and return with an error code
print (str(err))
sys.exit(2)
# evaluate given options
for currentArgument, currentValue in arguments:
if currentArgument in ("-i", "--init"):
print ("initializing the laser")
self.Initialize_Laser()
#sage()
#command=self.Initialize_Laser
elif currentArgument in ("-H", "--home"):
print ("move to the home position")
self.Home()
elif currentArgument in ("-h", "--help"):
print ("CLI arguments are as follows")
print ("-g --go Starts the job with whatever other arguments")
print ("-s --stop Stops the job, doesnt go home, or un initialize")
print ("-H --home Sends the cutting head to the home [0,0] position")
print ("-i --init Initializes the laser, or prints errors if it fails")
print ("-o --open Requires an SVG file to open")
print ("-h --help Prints this dialog")
print ("-c --cut Tell the laser to cut")
print ("-r --raster Raster Engrave")
print ("-v --vector Vector Engrave")
print ("-V Verbose mode lo U wish.. I guess I could set debug mode")
print ("-u --unlock Unlock the print head")
print ("-x move to X-Cordinate ")
print ("-y move to Y-Cordinate ")
print (" ")
print (" ")
print ("Example Useage: $python k40_whisperer.py -i -H -o c.svg -r ")
exit()
elif currentArgument in ("-o", "--open"):
print (("opening an svg (%s)") % (currentValue))
self.Open_SVG(currentValue)
elif currentArgument in ("-g", "--go"):
print ("Start cutting or moving the head")
#This option doesn't translate into a direct action like the other functions do.
elif currentArgument in ("-s", "--stop"):
print ("Stop Cutting::dont check or make a pop up, just stop")
self.CLI_Stop()
#self.Stop()
elif currentArgument in ("-u", "--unlock"):
print ("unlocked the print head")
self.Unlock()
elif currentArgument in ("-c", "cut"):
print ("cuts the open svg file")
self.Vector_Cut()
elif currentArgument in ("-r", "--raster"):
print ("raster Engraves the opened file")
self.Raster_Eng()
elif currentArgument in ("-v", "--vector"):
print ("Vector Engraves the opend file")
self.Vector_Eng()
elif currentArgument in ("-V"):
print ("Verbose mode lol u wish, well, there is debug mode")
print ("Version 0.19 K40_whisperer source")
print ("Version 0.0 K40 CLI source")
elif currentArgument in ("x"):
print ("Move to X Coordinate " % (currentValue))
self.gotoX.set(currentValue)
self.GoTo()
elif currentArgument in ("y"):
print("Move to Y Coordnate %s" % (currentValue))
self.gotoY.set(currentValue)
self.GoTo()
else:
print ("FOILED! put in some args if you want CLI mode")
####Original DEV-OPS be liek: close if you have CLI arguments.
#
# opts, args = None, None
# try:
# opts, args = getopt.getopt(sys.argv[1:], "ho:",["help", "other_option"])
# print args[1:]
# except:
# debug_message('Unable to interpret command line options')
# sys.exit()
## for option, value in opts:
## if option in ('-h','--help'):
## fmessage(' ')
## fmessage('Usage: python .py [-g file]')
## fmessage('-o : unknown other option (also --other_option)')
## fmessage('-h : print this help (also --help)\n')
## sys.exit()
## if option in ('-o','--other_option'):
## pass
##########################################################################
################################################################################
def entry_set(self, val2, calc_flag=0, new=0):
if calc_flag == 0 and new==0:
try:
self.statusbar.configure( bg = 'yellow' )
val2.configure( bg = 'yellow' )
self.statusMessage.set(" Recalculation required.")
except:
pass
elif calc_flag == 3:
try:
val2.configure( bg = 'red' )
self.statusbar.configure( bg = 'red' )
self.statusMessage.set(" Value should be a number. ")
except:
pass
elif calc_flag == 2:
try:
self.statusbar.configure( bg = 'red' )
val2.configure( bg = 'red' )
except:
pass
elif (calc_flag == 0 or calc_flag == 1) and new==1 :
try:
self.statusbar.configure( bg = 'white' )
self.statusMessage.set(" ")
val2.configure( bg = 'white' )
except:
pass
elif (calc_flag == 1) and new==0 :
try:
self.statusbar.configure( bg = 'white' )
self.statusMessage.set(" ")
val2.configure( bg = 'white' )
except:
pass
elif (calc_flag == 0 or calc_flag == 1) and new==2:
return 0
return 1
################################################################################
def Write_Config_File(self, event):
config_data = self.WriteConfig()
config_file = "k40_whisperer.txt"
configname_full = self.HOME_DIR + "/" + config_file
win_id=self.grab_current()
if ( os.path.isfile(configname_full) ):
if not message_ask_ok_cancel("Replace", "Replace Exiting Configuration File?\n"+configname_full):
try:
win_id.withdraw()
win_id.deiconify()
except:
pass
return
try:
fout = open(configname_full,'w')
except:
self.statusMessage.set("Unable to open file for writing: %s" %(configname_full))
self.statusbar.configure( bg = 'red' )
return
for line in config_data:
try:
fout.write(line+'\n')
except:
fout.write('(skipping line)\n')
fout.close
self.statusMessage.set("Configuration File Saved: %s" %(configname_full))
self.statusbar.configure( bg = 'white' )
try:
win_id.withdraw()
win_id.deiconify()
except:
pass
################################################################################
def WriteConfig(self):
global Zero
header = []
header.append('( K40 Whisperer Settings: '+version+' )')
header.append('( by Scorch - 2017 )')
header.append("(=========================================================)")
# BOOL
header.append('(k40_whisperer_set include_Reng %s )' %( int(self.include_Reng.get()) ))
header.append('(k40_whisperer_set include_Veng %s )' %( int(self.include_Veng.get()) ))
header.append('(k40_whisperer_set include_Vcut %s )' %( int(self.include_Vcut.get()) ))
header.append('(k40_whisperer_set include_Gcde %s )' %( int(self.include_Gcde.get()) ))
header.append('(k40_whisperer_set include_Time %s )' %( int(self.include_Time.get()) ))
header.append('(k40_whisperer_set halftone %s )' %( int(self.halftone.get()) ))
header.append('(k40_whisperer_set HomeUR %s )' %( int(self.HomeUR.get()) ))
header.append('(k40_whisperer_set inputCSYS %s )' %( int(self.inputCSYS.get()) ))
header.append('(k40_whisperer_set advanced %s )' %( int(self.advanced.get()) ))
header.append('(k40_whisperer_set mirror %s )' %( int(self.mirror.get()) ))
header.append('(k40_whisperer_set rotate %s )' %( int(self.rotate.get()) ))
header.append('(k40_whisperer_set engraveUP %s )' %( int(self.engraveUP.get()) ))
header.append('(k40_whisperer_set init_home %s )' %( int(self.init_home.get()) ))
header.append('(k40_whisperer_set pre_pr_crc %s )' %( int(self.pre_pr_crc.get()) ))
header.append('(k40_whisperer_set inside_first %s )' %( int(self.inside_first.get()) ))
# STRING.get()
header.append('(k40_whisperer_set board_name %s )' %( self.board_name.get() ))
header.append('(k40_whisperer_set units %s )' %( self.units.get() ))
header.append('(k40_whisperer_set Reng_feed %s )' %( self.Reng_feed.get() ))
header.append('(k40_whisperer_set Veng_feed %s )' %( self.Veng_feed.get() ))
header.append('(k40_whisperer_set Vcut_feed %s )' %( self.Vcut_feed.get() ))
header.append('(k40_whisperer_set jog_step %s )' %( self.jog_step.get() ))
header.append('(k40_whisperer_set Reng_passes %s )' %( self.Reng_passes.get() ))
header.append('(k40_whisperer_set Veng_passes %s )' %( self.Veng_passes.get() ))
header.append('(k40_whisperer_set Vcut_passes %s )' %( self.Vcut_passes.get() ))
header.append('(k40_whisperer_set Gcde_passes %s )' %( self.Gcde_passes.get() ))
header.append('(k40_whisperer_set rast_step %s )' %( self.rast_step.get() ))
header.append('(k40_whisperer_set ht_size %s )' %( self.ht_size.get() ))
header.append('(k40_whisperer_set LaserXsize %s )' %( self.LaserXsize.get() ))
header.append('(k40_whisperer_set LaserYsize %s )' %( self.LaserYsize.get() ))
header.append('(k40_whisperer_set LaserXscale %s )' %( self.LaserXscale.get() ))
header.append('(k40_whisperer_set LaserYscale %s )' %( self.LaserYscale.get() ))
header.append('(k40_whisperer_set gotoX %s )' %( self.gotoX.get() ))
header.append('(k40_whisperer_set gotoY %s )' %( self.gotoY.get() ))
header.append('(k40_whisperer_set bezier_M1 %s )' %( self.bezier_M1.get() ))
header.append('(k40_whisperer_set bezier_M2 %s )' %( self.bezier_M2.get() ))
header.append('(k40_whisperer_set bezier_weight %s )' %( self.bezier_weight.get() ))
header.append('(k40_whisperer_set t_timeout %s )' %( self.t_timeout.get() ))
header.append('(k40_whisperer_set n_timeouts %s )' %( self.n_timeouts.get() ))
header.append('(k40_whisperer_set designfile \042%s\042 )' %( self.DESIGN_FILE ))
header.append('(k40_whisperer_set inkscape_path \042%s\042 )' %( self.inkscape_path.get() ))
self.jog_step
header.append("(=========================================================)")
return header
######################################################
def Quit_Click(self, event):
self.statusMessage.set("Exiting!")
root.destroy()
def mousePanStart(self,event):
self.panx = event.x
self.pany = event.y
self.move_start_x = event.x
self.move_start_y = event.y
def mousePan(self,event):
all = self.PreviewCanvas.find_all()
dx = event.x-self.panx
dy = event.y-self.pany
self.PreviewCanvas.move('LaserTag', dx, dy)
self.lastx = self.lastx + dx
self.lasty = self.lasty + dy
self.panx = event.x
self.pany = event.y
def mousePanStop(self,event):
Xold = round(self.laserX,3)
Yold = round(self.laserY,3)
can_dx = event.x-self.move_start_x
can_dy = -(event.y-self.move_start_y)
dx = can_dx*self.PlotScale
dy = can_dy*self.PlotScale
if self.HomeUR.get():
dx = -dx
self.laserX,self.laserY = self.XY_in_bounds(dx,dy)
DXmils = round((self.laserX - Xold)*1000.0,0)
DYmils = round((self.laserY - Yold)*1000.0,0)
self.Send_Rapid_Move(DXmils,DYmils)
self.menu_View_Refresh()
def LASER_Size(self):
MINX = 0.0
MAXY = 0.0
if self.units.get()=="in":
MAXX = float(self.LaserXsize.get())
MINY = -float(self.LaserYsize.get())
else:
MAXX = float(self.LaserXsize.get())/25.4
MINY = -float(self.LaserYsize.get())/25.4
return (MAXX-MINX,MAXY-MINY)
def XY_in_bounds(self,dx_inches,dy_inches):
MINX = 0.0
MAXY = 0.0
if self.units.get()=="in":
MAXX = float(self.LaserXsize.get())
MINY = -float(self.LaserYsize.get())
else:
MAXX = float(self.LaserXsize.get())/25.4
MINY = -float(self.LaserYsize.get())/25.4
if self.inputCSYS.get() and self.RengData.image == None:
xmin,xmax,ymin,ymax = 0.0,0.0,0.0,0.0
else:
xmin,xmax,ymin,ymax = self.Get_Design_Bounds()
X = self.laserX + dx_inches
X = min(MAXX-(xmax-xmin),X)
X = max(MINX,X)
Y = self.laserY + dy_inches
Y = max(MINY+(ymax-ymin),Y)
Y = min(MAXY,Y)
X = round(X,3)
Y = round(Y,3)
return X,Y
## def computeAccurateVeng(self):
## self.update_gui("Optimize vector engrave.")
## self.VengData.set_ecoords(self.optimize_paths(self.VengData.ecoords),data_sorted=True)
## self.refreshTime()
##
## def computeAccurateVcut(self):
## self.update_gui("Optimize vector cut.")
## self.VcutData.set_ecoords(self.optimize_paths(self.VcutData.ecoords),data_sorted=True)
## self.refreshTime()
##
## def computeAccurateReng(self):
## self.update_gui("Calculating Raster engrave.")
## if self.RengData.image != None:
## if self.RengData.ecoords == []:
## self.make_raster_coords()
## self.RengData.sorted = True
## self.refreshTime()
def format_time(self,time_in_seconds):
# format the duration from seconds to something human readable
if time_in_seconds >=0 :
s = round(time_in_seconds)
m,s=divmod(s,60)
h,m=divmod(m,60)
res = ""
if h > 0:
res = "%dh " %(h)
if m > 0:
res += "%dm " %(m)
if h == 0:
res += "%ds " %(s)
#L=len(res)
#for i in range(L,8):
# res = res+" "
return res
else :
return "?"
def refreshTime(self):
if not self.include_Time.get():
return
if self.units.get() == 'in':
factor = 60.0
else :
factor = 25.4
Raster_eng_feed = float(self.Reng_feed.get()) / factor
Vector_eng_feed = float(self.Veng_feed.get()) / factor
Vector_cut_feed = float(self.Vcut_feed.get()) / factor
Raster_eng_passes = float(self.Reng_passes.get())
Vector_eng_passes = float(self.Veng_passes.get())
Vector_cut_passes = float(self.Vcut_passes.get())
Gcode_passes = float(self.Gcde_passes.get())
rapid_feed = 100.0 / 25.4 # 100 mm/s move feed to be confirmed
#if self.RengData.sorted:
# wim, him = self.RengData.image.size
# Reng_time = ( (self.RengData.len)/Raster_eng_feed + (him/self.input_dpi)/rapid_feed) * Raster_eng_passes
#else:
try:
wim, him = self.RengData.image.size
Reng_time = ((wim/self.input_dpi * him/self.input_dpi)/ float(self.rast_step.get()) ) / Raster_eng_feed*Raster_eng_passes
except:
Reng_time = 0
Veng_time = (self.VengData.len / Vector_eng_feed + self.VengData.move / rapid_feed) * Vector_eng_passes
Vcut_time = (self.VcutData.len / Vector_cut_feed + self.VcutData.move / rapid_feed) * Vector_cut_passes
Gcode_time = self.GcodeData.gcode_time * Gcode_passes
self.Reng_time.set("Raster Engrave: %s" %(self.format_time(Reng_time)))
self.Veng_time.set("Vector Engrave: %s" %(self.format_time(Veng_time)))
self.Vcut_time.set(" Vector Cut: %s" %(self.format_time(Vcut_time)))
self.Gcde_time.set(" Gcode: %s" %(self.format_time(Gcode_time)))
##########################################
cszw = int(self.PreviewCanvas.cget("width"))
cszh = int(self.PreviewCanvas.cget("height"))
HUD_vspace = 15
HUD_X = cszw-5
HUD_Y = cszh-5
self.PreviewCanvas.delete("HUD")
if self.GcodeData.ecoords == []:
self.PreviewCanvas.create_text(HUD_X, HUD_Y , fill = "red" ,text =self.Vcut_time.get(), anchor="se",tags="HUD")
self.PreviewCanvas.create_text(HUD_X, HUD_Y-HUD_vspace , fill = "blue" ,text =self.Veng_time.get(), anchor="se",tags="HUD")
self.PreviewCanvas.create_text(HUD_X, HUD_Y-HUD_vspace*2, fill = "black",text =self.Reng_time.get(), anchor="se",tags="HUD")
else:
self.PreviewCanvas.create_text(HUD_X, HUD_Y, fill = "black",text =self.Gcde_time.get(), anchor="se",tags="HUD")
##########################################
def Settings_ReLoad_Click(self, event):
win_id=self.grab_current()
def Close_Current_Window_Click(self):
win_id=self.grab_current()
win_id.destroy()
# Left Column #
#############################
def Entry_Reng_feed_Check(self):
try:
value = float(self.Reng_feed.get())
if value <= 0.0:
self.statusMessage.set(" Feed Rate should be greater than 0.0 ")
return 2 # Value is invalid number
except:
return 3 # Value not a number
self.refreshTime()
return 0 # Value is a valid number
def Entry_Reng_feed_Callback(self, varName, index, mode):
self.entry_set(self.Entry_Reng_feed, self.Entry_Reng_feed_Check(), new=1)
#############################
def Entry_Veng_feed_Check(self):
try:
value = float(self.Veng_feed.get())
if value <= 0.0:
self.statusMessage.set(" Feed Rate should be greater than 0.0 ")
return 2 # Value is invalid number
except:
return 3 # Value not a number
self.refreshTime()
return 0 # Value is a valid number
def Entry_Veng_feed_Callback(self, varName, index, mode):
self.entry_set(self.Entry_Veng_feed, self.Entry_Veng_feed_Check(), new=1)
#############################
def Entry_Vcut_feed_Check(self):
try:
value = float(self.Vcut_feed.get())
if value <= 0.0:
self.statusMessage.set(" Feed Rate should be greater than 0.0 ")
return 2 # Value is invalid number
except:
return 3 # Value not a number
self.refreshTime()
return 0 # Value is a valid number
def Entry_Vcut_feed_Callback(self, varName, index, mode):
self.entry_set(self.Entry_Vcut_feed, self.Entry_Vcut_feed_Check(), new=1)
#############################
def Entry_Step_Check(self):
try:
value = float(self.jog_step.get())
if value <= 0.0:
self.statusMessage.set(" Step should be greater than 0.0 ")
return 2 # Value is invalid number
except:
return 3 # Value not a number
return 0 # Value is a valid number
def Entry_Step_Callback(self, varName, index, mode):
self.entry_set(self.Entry_Step, self.Entry_Step_Check(), new=1)
#############################
def Entry_GoToX_Check(self):
try:
value = float(self.gotoX.get())
if (value < 0.0) and (not self.HomeUR.get()):
self.statusMessage.set(" Value should be greater than 0.0 ")
return 2 # Value is invalid number
elif (value > 0.0) and self.HomeUR.get():
self.statusMessage.set(" Value should be less than 0.0 ")
return 2 # Value is invalid number
except:
return 3 # Value not a number
return 0 # Value is a valid number
def Entry_GoToX_Callback(self, varName, index, mode):
self.entry_set(self.Entry_GoToX, self.Entry_GoToX_Check(), new=1)
#############################
def Entry_GoToY_Check(self):
try:
value = float(self.gotoY.get())
if value > 0.0:
self.statusMessage.set(" Value should be less than 0.0 ")
return 2 # Value is invalid number
except:
return 3 # Value not a number
return 0 # Value is a valid number
def Entry_GoToY_Callback(self, varName, index, mode):
self.entry_set(self.Entry_GoToY, self.Entry_GoToY_Check(), new=1)
#############################
def Entry_Rstep_Check(self):
try:
value = self.get_raster_step_1000in()
if value <= 0 or value > 63:
self.statusMessage.set(" Step should be between 0.001 and 0.063 in")
return 2 # Value is invalid number
except:
return 3 # Value not a number
return 0 # Value is a valid number
def Entry_Rstep_Callback(self, varName, index, mode):
self.entry_set(self.Entry_Rstep, self.Entry_Rstep_Check(), new=1)
#############################
# End Left Column #
#############################
def bezier_weight_Callback(self, varName=None, index=None, mode=None):
self.bezier_plot()
def bezier_M1_Callback(self, varName=None, index=None, mode=None):
self.bezier_plot()
def bezier_M2_Callback(self, varName=None, index=None, mode=None):
self.bezier_plot()
def bezier_plot(self):
self.BezierCanvas.delete('bez')
#self.BezierCanvas.create_line( 5,260-0,260,260-255,fill="black", capstyle="round", width = 2, tags='bez')
M1 = float(self.bezier_M1.get())
M2 = float(self.bezier_M2.get())
w = float(self.bezier_weight.get())
num = 10
x,y = self.generate_bezier(M1,M2,w,n=num)
for i in range(0,num):
self.BezierCanvas.create_line( 5+x[i],260-y[i],5+x[i+1],260-y[i+1],fill="black", \
capstyle="round", width = 2, tags='bez')
self.BezierCanvas.create_text(128, 0, text="Output Level vs. Input Level",anchor="n", tags='bez')
#############################
def Entry_Timeout_Check(self):
try:
value = float(self.t_timeout.get())
if value <= 0.0:
self.statusMessage.set(" Timeout should be greater than 0 ")
return 2 # Value is invalid number
except:
return 3 # Value not a number
return 0 # Value is a valid number
def Entry_Timeout_Callback(self, varName, index, mode):
self.entry_set(self.Entry_Timeout,self.Entry_Timeout_Check(), new=1)
#############################
def Entry_N_Timeouts_Check(self):
try:
value = float(self.n_timeouts.get())
if value <= 0.0:
self.statusMessage.set(" N_Timeouts should be greater than 0 ")
return 2 # Value is invalid number
except:
return 3 # Value not a number
return 0 # Value is a valid number
def Entry_N_Timeouts_Callback(self, varName, index, mode):
self.entry_set(self.Entry_N_Timeouts,self.Entry_N_Timeouts_Check(), new=1)
#############################
def Entry_Laser_Area_Width_Check(self):
try:
value = float(self.LaserXsize.get())
if value <= 0.0:
self.statusMessage.set(" Width should be greater than 0 ")
return 2 # Value is invalid number
except:
return 3 # Value not a number
return 0 # Value is a valid number
def Entry_Laser_Area_Width_Callback(self, varName, index, mode):
self.entry_set(self.Entry_Laser_Area_Width,self.Entry_Laser_Area_Width_Check(), new=1)
#############################
def Entry_Laser_Area_Height_Check(self):
try:
value = float(self.LaserYsize.get())
if value <= 0.0:
self.statusMessage.set(" Height should be greater than 0 ")
return 2 # Value is invalid number
except:
return 3 # Value not a number
return 0 # Value is a valid number
def Entry_Laser_Area_Height_Callback(self, varName, index, mode):
self.entry_set(self.Entry_Laser_Area_Height,self.Entry_Laser_Area_Height_Check(), new=1)
#############################
def Entry_Laser_X_Scale_Check(self):
try:
value = float(self.LaserXscale.get())
if value <= 0.0:
self.statusMessage.set(" Scale should be greater than 0 ")
return 2 # Value is invalid number
except:
return 3 # Value not a number
return 0 # Value is a valid number
def Entry_Laser_X_Scale_Callback(self, varName, index, mode):
self.entry_set(self.Entry_Laser_X_Scale,self.Entry_Laser_X_Scale_Check(), new=1)
#############################
def Entry_Laser_Y_Scale_Check(self):
try:
value = float(self.LaserYscale.get())
if value <= 0.0:
self.statusMessage.set(" Height should be greater than 0 ")
return 2 # Value is invalid number
except:
return 3 # Value not a number
return 0 # Value is a valid number
def Entry_Laser_Y_Scale_Callback(self, varName, index, mode):
self.entry_set(self.Entry_Laser_Y_Scale,self.Entry_Laser_Y_Scale_Check(), new=1)
# Advanced Column #
#############################
def Entry_Reng_passes_Check(self):
try:
value = int(self.Reng_passes.get())
if value < 1:
self.statusMessage.set(" Number of passes should be greater than 0 ")
return 2 # Value is invalid number
except:
return 3 # Value not a number
self.refreshTime()
return 0 # Value is a valid number
def Entry_Reng_passes_Callback(self, varName, index, mode):
self.entry_set(self.Entry_Reng_passes, self.Entry_Reng_passes_Check(), new=1)
#############################
def Entry_Veng_passes_Check(self):
try:
value = int(self.Veng_passes.get())
if value < 1:
self.statusMessage.set(" Number of passes should be greater than 0 ")
return 2 # Value is invalid number
except:
return 3 # Value not a number
self.refreshTime()
return 0 # Value is a valid number
def Entry_Veng_passes_Callback(self, varName, index, mode):
self.entry_set(self.Entry_Veng_passes, self.Entry_Veng_passes_Check(), new=1)
#############################
def Entry_Vcut_passes_Check(self):
try:
value = int(self.Vcut_passes.get())
if value < 1:
self.statusMessage.set(" Number of passes should be greater than 0 ")
return 2 # Value is invalid number
except:
return 3 # Value not a number
self.refreshTime()
return 0 # Value is a valid number
def Entry_Vcut_passes_Callback(self, varName, index, mode):
self.entry_set(self.Entry_Vcut_passes, self.Entry_Vcut_passes_Check(), new=1)
#############################
def Entry_Gcde_passes_Check(self):
try:
value = int(self.Gcde_passes.get())
if value < 1:
self.statusMessage.set(" Number of passes should be greater than 0 ")
return 2 # Value is invalid number
except:
return 3 # Value not a number
return 0 # Value is a valid number
def Entry_Gcde_passes_Callback(self, varName, index, mode):
self.entry_set(self.Entry_Gcde_passes, self.Entry_Gcde_passes_Check(), new=1)
#############################
##########################################################################
##########################################################################
def Check_All_Variables(self):
pass
## MAIN_error_cnt= \
## self.entry_set(self.Entry_Yscale, self.Entry_Yscale_Check() ,2) +\
## self.entry_set(self.Entry_Toptol, self.Entry_Toptol_Check() ,2)
##
## GEN_error_cnt= \
## self.entry_set(self.Entry_ContAngle,self.Entry_ContAngle_Check(),2)
## ERROR_cnt = MAIN_error_cnt + GEN_error_cnt
##
## if (ERROR_cnt > 0):
## self.statusbar.configure( bg = 'red' )
## if (GEN_error_cnt > 0):
## self.statusMessage.set(\
## " Entry Error Detected: Check Entry Values in General Settings Window ")
## if (MAIN_error_cnt > 0):
## self.statusMessage.set(\
## " Entry Error Detected: Check Entry Values in Main Window ")
##
## return ERROR_cnt
#############################
def Inkscape_Path_Click(self, event):
win_id=self.grab_current()
newfontdir = askopenfilename(filetypes=[("Executable Files",("inkscape.exe","*inkscape*")),\
("All Files","*")],\
initialdir=self.inkscape_path.get())
if newfontdir != "" and newfontdir != ():
self.inkscape_path.set(newfontdir.encode("utf-8"))
try:
win_id.withdraw()
win_id.deiconify()
except:
pass
def Entry_units_var_Callback(self):
if (self.units.get() == 'in') and (self.funits.get()=='mm/s'):
self.funits.set('in/min')
self.Scale_Linear_Inputs('in')
elif (self.units.get() == 'mm') and (self.funits.get()=='in/min'):
self.funits.set('mm/s')
self.Scale_Linear_Inputs('mm')
def Scale_Linear_Inputs(self, new_units=None):
if new_units=='in':
self.units_scale = 1.0
factor = 1/25.4
vfactor = 60.0/25.4
elif new_units=='mm':
factor = 25.4
vfactor = 25.4/60.0
self.units_scale = 25.4
else:
return
self.LaserXsize.set( self.Scale_Text_Value('%.2f',self.LaserXsize.get(),factor) )
self.LaserYsize.set( self.Scale_Text_Value('%.2f',self.LaserYsize.get(),factor) )
self.jog_step.set ( self.Scale_Text_Value('%.3f',self.jog_step.get() ,factor) )
self.gotoX.set ( self.Scale_Text_Value('%.3f',self.gotoX.get() ,factor) )
self.gotoY.set ( self.Scale_Text_Value('%.3f',self.gotoY.get() ,factor) )
self.Reng_feed.set ( self.Scale_Text_Value('%.1f',self.Reng_feed.get() ,vfactor) )
self.Veng_feed.set ( self.Scale_Text_Value('%.1f',self.Veng_feed.get() ,vfactor) )
self.Vcut_feed.set ( self.Scale_Text_Value('%.1f',self.Vcut_feed.get() ,vfactor) )
def Scale_Text_Value(self,format_txt,Text_Value,factor):
try:
return format_txt %(float(Text_Value)*factor )
except:
return ''
def menu_File_Open_Settings_File(self):
init_dir = os.path.dirname(self.DESIGN_FILE)
if ( not os.path.isdir(init_dir) ):
init_dir = self.HOME_DIR
fileselect = askopenfilename(filetypes=[("Settings Files","*.txt"),\
("All Files","*")],\
initialdir=init_dir)
if fileselect != '' and fileselect != ():
self.Open_Settings_File(fileselect)
def menu_Reload_Design(self):
file_full = self.DESIGN_FILE
file_name = os.path.basename(file_full)
if ( os.path.isfile(file_full) ):
filname = file_full
elif ( os.path.isfile( file_name ) ):
filname = file_name
elif ( os.path.isfile( self.HOME_DIR+"/"+file_name ) ):
filname = self.HOME_DIR+"/"+file_name
else:
self.statusMessage.set("file not found: %s" %(os.path.basename(file_full)) )
self.statusbar.configure( bg = 'red' )
return
Name, fileExtension = os.path.splitext(filname)
TYPE=fileExtension.upper()
if TYPE=='.DXF':
self.Open_DXF(filname)
elif TYPE=='.SVG':
self.Open_SVG(filname)
else:
self.Open_G_Code(filname)
self.menu_View_Refresh()
def menu_File_Open_Design(self):
init_dir = os.path.dirname(self.DESIGN_FILE)
if ( not os.path.isdir(init_dir) ):
init_dir = self.HOME_DIR
fileselect = askopenfilename(filetypes=[("Design Files", ("*.svg","*.dxf")),
("G-Code Files", ("*.ngc","*.gcode","*.g","*.tap")),\
("DXF Files","*.dxf"),\
("SVG Files","*.svg"),\
("All Files","*"),\
("Design Files ", ("*.svg","*.dxf"))],\
initialdir=init_dir)
if ( not os.path.isfile(fileselect) ):
return
Name, fileExtension = os.path.splitext(fileselect)
self.update_gui("Opening '%s'" % fileselect )
TYPE=fileExtension.upper()
if TYPE=='.DXF':
self.Open_DXF(fileselect)
elif TYPE=='.SVG':
self.Open_SVG(fileselect)
else:
self.Open_G_Code(fileselect)
self.DESIGN_FILE = fileselect
self.menu_View_Refresh()
def menu_File_Open_EGV(self):
init_dir = os.path.dirname(self.DESIGN_FILE)
if ( not os.path.isdir(init_dir) ):
init_dir = self.HOME_DIR
fileselect = askopenfilename(filetypes=[("Engraver Files", ("*.egv","*.EGV")),\
("All Files","*")],\
initialdir=init_dir)
if fileselect != '' and fileselect != ():
self.DESIGN_FILE = fileselect
self.Open_EGV(fileselect)
self.menu_View_Refresh()
def Open_EGV(self,filemna