#!/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