From 7469e58cdfb52fe710a296409f93d6ff4c1a0022 Mon Sep 17 00:00:00 2001 From: Marc-Antoine Lafreniere Date: Wed, 20 Mar 2019 13:48:58 -0400 Subject: [PATCH 1/5] #55-UI frame Refactor main the ease usage in the UI --- pcbdevice/main.py | 49 ++++++++++++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/pcbdevice/main.py b/pcbdevice/main.py index 38eaa16..0696132 100644 --- a/pcbdevice/main.py +++ b/pcbdevice/main.py @@ -8,6 +8,31 @@ from pcbdevice.utils.FileUtils import FileUtils import argparse import subprocess +def main(inputPath, outputPath, converterPath, isAscii, heightReal, widthReal, tool, unit): + if outputPath.rfind('\\') != -1: + asciiPbmPath = outputPath[0:outputPath.rfind('\\')] + '\\pcbImageAscii.pbm' + elif outputPath.rfind('/') != -1: + asciiPbmPath = outputPath[0:outputPath.rfind('/')] + '/pcbImageAscii.pbm' + else: + asciiPbmPath = '.\\pcbdevice\\resources\\output\\pcbImageAscii.pbm' + + if not isAscii: + subprocess.check_call([converterPath, inputPath, asciiPbmPath]) + + matrix, height, width = FileUtils.pbmToMatrix(asciiPbmPath) + + pxHeight, pxWidth = FileUtils.getPixelSize(height, width, heightReal, widthReal, unit = unit) + + if pxHeight > pxWidth: + rTool = int(math.ceil(tool * pxHeight)) + else: + rTool = int(math.ceil(tool * pxWidth)) + + matrixUpdated = path(matrix, rTool) + listIndexes = createSequence(matrixUpdated) + gcode = listToGCode(listIndexes, pxHeight, pxWidth) + FileUtils.saveStringListToFile(gcode, outputPath) + if __name__ == "__main__": parser = argparse.ArgumentParser(prog = 'main.py') parser.add_argument('-i', required = True, help = 'PCB image path') @@ -19,31 +44,15 @@ if __name__ == "__main__": parser.add_argument('-u', required = False, help = 'PCB dimension unit') args = parser.parse_args() - converterPath = '.\\pcbdevice\\utils\\convertiseur.exe' - asciiPbmPath = '.\\pcbdevice\\resources\\output\\pcbImageAscii.pbm' + converter = '.\\pcbdevice\\utils\\convertiseur.exe' unitValue = 'mm' isAscii = args.imgTypeisAscii - if isAscii: - asciiPbmPath = args.i - - if not isAscii: - subprocess.check_call([converterPath, args.i, asciiPbmPath]) - - matrix, height, width = FileUtils.pbmToMatrix(asciiPbmPath) - if args.u: unitValue = args.u - pxHeight, pxWidth = FileUtils.getPixelSize(height, width, args.he, args.wi, unit = unitValue) + if isAscii: + asciiPbmPath = args.i - if pxHeight > pxWidth: - rTool = int(math.ceil(args.t * pxHeight)) - else: - rTool = int(math.ceil(args.t * pxWidth)) - - matrixUpdated = path(matrix, rTool) - listIndexes = createSequence(matrixUpdated) - gcode = listToGCode(listIndexes, pxHeight, pxWidth) - FileUtils.saveStringListToFile(gcode, args.o) \ No newline at end of file + main(args.i, args.o, converter, isAscii, args.wi, args.he, args.t, unitValue) \ No newline at end of file From 7f85e028935c38f98a9a9d117100ac54cea55c5d Mon Sep 17 00:00:00 2001 From: Marc-Antoine Lafreniere Date: Wed, 20 Mar 2019 13:48:58 -0400 Subject: [PATCH 2/5] #55-UI frame Refactor main the ease usage in the UI --- pcbdevice/main.py | 51 ++++++++++++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 21 deletions(-) diff --git a/pcbdevice/main.py b/pcbdevice/main.py index 38eaa16..608ec35 100644 --- a/pcbdevice/main.py +++ b/pcbdevice/main.py @@ -8,6 +8,33 @@ from pcbdevice.utils.FileUtils import FileUtils import argparse import subprocess +def main(inputPath, outputPath, isAscii, heightReal, widthReal, tool, unit): + converterPath = '.\\pcbdevice\\utils\\convertiseur.exe' + + if outputPath.rfind('\\') != -1: + asciiPbmPath = outputPath[0:outputPath.rfind('\\')] + '\\pcbImageAscii.pbm' + elif outputPath.rfind('/') != -1: + asciiPbmPath = outputPath[0:outputPath.rfind('/')] + '/pcbImageAscii.pbm' + else: + asciiPbmPath = '.\\pcbdevice\\resources\\output\\pcbImageAscii.pbm' + + if not isAscii: + subprocess.check_call([converterPath, inputPath, asciiPbmPath]) + + matrix, height, width = FileUtils.pbmToMatrix(asciiPbmPath) + + pxHeight, pxWidth = FileUtils.getPixelSize(height, width, heightReal, widthReal, unit = unit) + + if pxHeight > pxWidth: + rTool = int(math.ceil(tool * pxHeight)) + else: + rTool = int(math.ceil(tool * pxWidth)) + + matrixUpdated = path(matrix, rTool) + listIndexes = createSequence(matrixUpdated) + gcode = listToGCode(listIndexes, pxHeight, pxWidth) + FileUtils.saveStringListToFile(gcode, outputPath) + if __name__ == "__main__": parser = argparse.ArgumentParser(prog = 'main.py') parser.add_argument('-i', required = True, help = 'PCB image path') @@ -19,31 +46,13 @@ if __name__ == "__main__": parser.add_argument('-u', required = False, help = 'PCB dimension unit') args = parser.parse_args() - converterPath = '.\\pcbdevice\\utils\\convertiseur.exe' - asciiPbmPath = '.\\pcbdevice\\resources\\output\\pcbImageAscii.pbm' - unitValue = 'mm' isAscii = args.imgTypeisAscii - if isAscii: - asciiPbmPath = args.i - - if not isAscii: - subprocess.check_call([converterPath, args.i, asciiPbmPath]) - - matrix, height, width = FileUtils.pbmToMatrix(asciiPbmPath) - if args.u: unitValue = args.u - pxHeight, pxWidth = FileUtils.getPixelSize(height, width, args.he, args.wi, unit = unitValue) + if isAscii: + asciiPbmPath = args.i - if pxHeight > pxWidth: - rTool = int(math.ceil(args.t * pxHeight)) - else: - rTool = int(math.ceil(args.t * pxWidth)) - - matrixUpdated = path(matrix, rTool) - listIndexes = createSequence(matrixUpdated) - gcode = listToGCode(listIndexes, pxHeight, pxWidth) - FileUtils.saveStringListToFile(gcode, args.o) \ No newline at end of file + main(args.i, args.o, isAscii, args.wi, args.he, args.t, unitValue) \ No newline at end of file From cf1ebd0e0fd9de225ace5d8a6cbe9ad8026eba72 Mon Sep 17 00:00:00 2001 From: Ian Date: Sun, 24 Mar 2019 20:48:45 -0400 Subject: [PATCH 3/5] #55 first version of a working Ui Can only work if given the right parameters, (no safety) --- pcbdevice/UI/UI.py | 54 +++++++++++++++++++++++++++++++++ pcbdevice/UI/__init__.py | 0 pcbdevice/gcode/GcodeCreator.py | 6 +++- 3 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 pcbdevice/UI/UI.py create mode 100644 pcbdevice/UI/__init__.py diff --git a/pcbdevice/UI/UI.py b/pcbdevice/UI/UI.py new file mode 100644 index 0000000..4145978 --- /dev/null +++ b/pcbdevice/UI/UI.py @@ -0,0 +1,54 @@ +from tkinter import * + +from pcbdevice.main import main + +root = Tk() +frame = Frame(root) +frame.pack() + +class textBox: + def __init__(self, master, parameter): + self.master = master + self.createWidget(master, parameter) + + def createWidget(self, master, parameter): + frame = Frame(master, width=500, height=30, ) + frame.pack(side=TOP) + frame.pack_propagate(0) + + Text = Label(frame, text=parameter) + Text.pack(side=LEFT) + self.Box = Entry(frame) + self.Box.pack(side=RIGHT) + +class button: + def __init__(self, master): + self.master = master + self.createWidget(master) + + def execution(self): + main(PCB.Box.get(), Gcode.Box.get(), bool(ascii.Box.get()), int(Width.Box.get()), int(Height.Box.get()), + int(radius.Box.get()), unit.Box.get()) + + def createWidget(self, master): + frame = Frame(master, width=500, height=30, ) + frame.pack(side=BOTTOM) + frame.pack_propagate(0) + Butt = Button(frame, text = 'execute program', command = self.execution) + Butt.pack(side = RIGHT) + +root.title('totally not a virus') +root.geometry("550x300") + +#path = textBox(root, 'Program path') +PCB = textBox(root, 'PCB image path') +Gcode = textBox(root, 'Gcode output path') +ascii = textBox(root, 'If the image is in ascii(True) or binary(False)') +Width = textBox(root, 'Width of the PCB') +Height = textBox(root, 'Height of the PCB') +radius = textBox(root, 'Tool\'s radius in mm') +unit = textBox(root, 'PCB dimension unit') + +button = button(root) + +root.mainloop() diff --git a/pcbdevice/UI/__init__.py b/pcbdevice/UI/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pcbdevice/gcode/GcodeCreator.py b/pcbdevice/gcode/GcodeCreator.py index e7778d5..8636052 100644 --- a/pcbdevice/gcode/GcodeCreator.py +++ b/pcbdevice/gcode/GcodeCreator.py @@ -77,7 +77,11 @@ def findDirection(image, line, column): def createSequence(image): - + """ + Create a sequence of index coordinates from a path matrix + :param image: matrix of the path the tool needs to take + :return: Array of class coordinates (X , Y) + """ width = len(image[0]) height = len(image) sequence = [] From f746e769fd20a9a3e6d83a4626d14d741e8e0620 Mon Sep 17 00:00:00 2001 From: Ian Date: Mon, 25 Mar 2019 21:15:20 -0400 Subject: [PATCH 4/5] #55 modification of the entries changing some entry boxes with other input methods to limit the choices of the user --- pcbdevice/UI/UI.py | 62 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 55 insertions(+), 7 deletions(-) diff --git a/pcbdevice/UI/UI.py b/pcbdevice/UI/UI.py index 4145978..6341226 100644 --- a/pcbdevice/UI/UI.py +++ b/pcbdevice/UI/UI.py @@ -1,4 +1,6 @@ from tkinter import * +from tkinter.filedialog import askdirectory, askopenfilename, asksaveasfilename +from tkinter.ttk import Combobox from pcbdevice.main import main @@ -18,36 +20,82 @@ class textBox: Text = Label(frame, text=parameter) Text.pack(side=LEFT) - self.Box = Entry(frame) + self.Box = Entry(frame, width = 20) self.Box.pack(side=RIGHT) +class menuBox: + def __init__(self, master, parameter, selection): + self.master = master + self.createWidget(master, parameter, selection) + + def createWidget(self, master, parameter, selection): + frame = Frame(master, width=500, height=30, ) + frame.pack(side=TOP) + frame.pack_propagate(0) + + Text = Label(frame, text=parameter) + Text.pack(side=LEFT) + self.Box = Combobox(frame, values = selection, width = 17) + self.Box.pack(side=RIGHT) + class button: def __init__(self, master): self.master = master self.createWidget(master) def execution(self): - main(PCB.Box.get(), Gcode.Box.get(), bool(ascii.Box.get()), int(Width.Box.get()), int(Height.Box.get()), + main(PCB.path, Gcode.path, bool(ascii.Box.current()), int(Width.Box.get()), int(Height.Box.get()), int(radius.Box.get()), unit.Box.get()) + def createWidget(self, master): frame = Frame(master, width=500, height=30, ) frame.pack(side=BOTTOM) frame.pack_propagate(0) - Butt = Button(frame, text = 'execute program', command = self.execution) + Butt = Button(frame, text = 'execute program', command = lambda: self.execution()) Butt.pack(side = RIGHT) +class pathFind: + + path = '' + + def __init__(self, master, parameter, openSave): + self.master = master + self.createWidget(master, parameter, openSave) + + def openDir(self): + self.path = str(askopenfilename(initialdir = "/",title = "Select file",filetypes = (("pbm files","*.pbm")))) + + def saveDir(self): + self.path = str(asksaveasfilename(initialdir = "/",title = "Select file",filetypes = (("pbm files","*.gcode")))) + + def createWidget(self, master, parameter, openSave): + frame = Frame(master, width=500, height=30, ) + frame.pack(side=TOP) + frame.pack_propagate(0) + + Text = Label(frame, text=parameter) + Text.pack(side=LEFT) + if openSave: + Butt = Button(frame, text = 'find path', command = lambda: self.openDir() ) + else: + Butt = Button(frame, text = 'find path', command = lambda: self.saveDir() ) + Butt.pack(side = RIGHT) + +def display(this): + print(this) + root.title('totally not a virus') root.geometry("550x300") #path = textBox(root, 'Program path') -PCB = textBox(root, 'PCB image path') -Gcode = textBox(root, 'Gcode output path') -ascii = textBox(root, 'If the image is in ascii(True) or binary(False)') +PCB = pathFind(root, 'PCB image path', TRUE) +Gcode = pathFind(root, 'Gcode output path', FALSE) +ascii = menuBox(root, 'If the image is in ascii or binary', ['binary','ascii']) Width = textBox(root, 'Width of the PCB') Height = textBox(root, 'Height of the PCB') radius = textBox(root, 'Tool\'s radius in mm') -unit = textBox(root, 'PCB dimension unit') +unit = menuBox(root, 'PCB dimension unit', ['mm', 'm', 'in']) button = button(root) From 22b632da9bcc609db3873a9d01c9baae57533cd7 Mon Sep 17 00:00:00 2001 From: Ian Date: Wed, 27 Mar 2019 13:13:48 -0400 Subject: [PATCH 5/5] #55 verify entries to be the right type verify the entries and tells the user when the wrong type is entered --- pcbdevice/UI/UI.py | 65 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 51 insertions(+), 14 deletions(-) diff --git a/pcbdevice/UI/UI.py b/pcbdevice/UI/UI.py index 6341226..2223b52 100644 --- a/pcbdevice/UI/UI.py +++ b/pcbdevice/UI/UI.py @@ -1,6 +1,8 @@ +import os from tkinter import * from tkinter.filedialog import askdirectory, askopenfilename, asksaveasfilename from tkinter.ttk import Combobox +import subprocess from pcbdevice.main import main @@ -9,18 +11,19 @@ frame = Frame(root) frame.pack() class textBox: - def __init__(self, master, parameter): + def __init__(self, master, parameter, text): self.master = master - self.createWidget(master, parameter) + self.createWidget(master, parameter, text) - def createWidget(self, master, parameter): + def createWidget(self, master, parameter, text): frame = Frame(master, width=500, height=30, ) frame.pack(side=TOP) frame.pack_propagate(0) Text = Label(frame, text=parameter) Text.pack(side=LEFT) - self.Box = Entry(frame, width = 20) + self.v = StringVar(frame, value=text) + self.Box = Entry(frame, width = 20, textvariable = self.v) self.Box.pack(side=RIGHT) class menuBox: @@ -35,7 +38,8 @@ class menuBox: Text = Label(frame, text=parameter) Text.pack(side=LEFT) - self.Box = Combobox(frame, values = selection, width = 17) + self.v = StringVar(frame, value = selection[0]) + self.Box = Combobox(frame, state = 'readonly', values = selection, width = 17, textvariable = self.v) self.Box.pack(side=RIGHT) class button: @@ -44,14 +48,43 @@ class button: self.createWidget(master) def execution(self): - main(PCB.path, Gcode.path, bool(ascii.Box.current()), int(Width.Box.get()), int(Height.Box.get()), - int(radius.Box.get()), unit.Box.get()) + if self.verifyEntry(): + main(PCB.path, Gcode.path, bool(ascii.Box.current()), int(Width.Box.get()), int(Height.Box.get()), + int(radius.Box.get()), unit.Box.get()) + os.startfile(Gcode.path.rsplit('/', 1)[0]) + else: + print('FAIL') + + def verifyEntry(self): + if not Width.Box.get().isdigit(): + self.State.config(text = 'ERROR: Width needs to be a positive integer', fg = 'red', font = 'Helvetica 10 bold') + return 0 + if not Height.Box.get().isdigit(): + self.State.config(text = 'ERROR: Height needs to be a positive integer', fg = 'red', font = 'Helvetica 10 bold') + return 0 + if not radius.Box.get().isdigit(): + self.State.config(text = 'ERROR: Tool radius needs to be a positive integer', fg = 'red', font = 'Helvetica 10 bold') + return 0 + if not (radius.Box.get() < Width.Box.get() or radius.Box.get() < Height.Box.get()): + self.State.config(text = 'ERROR: Tool radius needs to be smaller than Width and Height', fg = 'red', font = 'Helvetica 10 bold') + return 0 + if not os.path.isfile(PCB.path) or not PCB.path.endswith('.pbm'): + self.State.config(text = 'ERROR: Unable to find PCB file or file type is not .pbm', fg = 'red', font = 'Helvetica 10 bold') + return 0 + if not Gcode.path.endswith('.gcode'): + self.State.config(text = 'ERROR: File type is not .gcode', fg = 'red', font = 'Helvetica 10 bold') + return 0 + + self.State.config(text='SUCCESS: (ง ͠° ͟ل͜ ͡°)ง', fg='green', font='Helvetica 10 bold') + return 1 def createWidget(self, master): frame = Frame(master, width=500, height=30, ) frame.pack(side=BOTTOM) frame.pack_propagate(0) + self.State = Label(frame, text='') + self.State.pack(side=LEFT) Butt = Button(frame, text = 'execute program', command = lambda: self.execution()) Butt.pack(side = RIGHT) @@ -64,10 +97,12 @@ class pathFind: self.createWidget(master, parameter, openSave) def openDir(self): - self.path = str(askopenfilename(initialdir = "/",title = "Select file",filetypes = (("pbm files","*.pbm")))) + self.path = str(askopenfilename(initialdir = "/",title = "Select file",filetypes = (("pbm files","*.pbm"),("all files","*.*")))) + self.Box.insert(END, self.path) def saveDir(self): - self.path = str(asksaveasfilename(initialdir = "/",title = "Select file",filetypes = (("pbm files","*.gcode")))) + self.path = str(asksaveasfilename(initialdir = "/",title = "Select file",filetypes = (("pbm files","*.gcode"),("all files","*.*")))) + self.Box.insert(END, self.path) def createWidget(self, master, parameter, openSave): frame = Frame(master, width=500, height=30, ) @@ -77,10 +112,12 @@ class pathFind: Text = Label(frame, text=parameter) Text.pack(side=LEFT) if openSave: - Butt = Button(frame, text = 'find path', command = lambda: self.openDir() ) + Butt = Button(frame, text = 'search', command = lambda: self.openDir()) else: - Butt = Button(frame, text = 'find path', command = lambda: self.saveDir() ) + Butt = Button(frame, text = 'search', command = lambda: self.saveDir()) Butt.pack(side = RIGHT) + self.Box = Entry(frame, width=45) + self.Box.pack(side=RIGHT, padx = 3) def display(this): print(this) @@ -92,9 +129,9 @@ root.geometry("550x300") PCB = pathFind(root, 'PCB image path', TRUE) Gcode = pathFind(root, 'Gcode output path', FALSE) ascii = menuBox(root, 'If the image is in ascii or binary', ['binary','ascii']) -Width = textBox(root, 'Width of the PCB') -Height = textBox(root, 'Height of the PCB') -radius = textBox(root, 'Tool\'s radius in mm') +Width = textBox(root, 'Width of the PCB', 100) +Height = textBox(root, 'Height of the PCB', 100) +radius = textBox(root, 'Tool\'s radius in mm', 1) unit = menuBox(root, 'PCB dimension unit', ['mm', 'm', 'in']) button = button(root)