Commit 8cc13495 authored by Guillaume Seguin's avatar Guillaume Seguin

Run reindent.py on the whole repository

parent ec596c5a
#!/usr/bin/env python #!/usr/bin/env python
# This file is part of the Printrun suite. # This file is part of the Printrun suite.
# #
# Printrun is free software: you can redistribute it and/or modify # Printrun is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or # the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version. # (at your option) any later version.
# #
# Printrun is distributed in the hope that it will be useful, # Printrun is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with Printrun. If not, see <http://www.gnu.org/licenses/>. # along with Printrun. If not, see <http://www.gnu.org/licenses/>.
...@@ -336,25 +336,25 @@ class stlwin(wx.Frame): ...@@ -336,25 +336,25 @@ class stlwin(wx.Frame):
def center(self, event): def center(self, event):
i = self.l.GetSelection() i = self.l.GetSelection()
if i != -1: if i != -1:
m = self.models[self.l.GetString(i)] m = self.models[self.l.GetString(i)]
m.offsets = [100, 100, m.offsets[2]] m.offsets = [100, 100, m.offsets[2]]
self.Refresh() self.Refresh()
def snap(self, event): def snap(self, event):
i = self.l.GetSelection() i = self.l.GetSelection()
if i != -1: if i != -1:
m = self.models[self.l.GetString(i)] m = self.models[self.l.GetString(i)]
m.offsets[2] = -1.0 * min(m.facetsminz)[0] m.offsets[2] = -1.0 * min(m.facetsminz)[0]
#print m.offsets[2] #print m.offsets[2]
self.Refresh() self.Refresh()
def delete(self, event): def delete(self, event):
i = self.l.GetSelection() i = self.l.GetSelection()
if i != -1: if i != -1:
del self.models[self.l.GetString(i)] del self.models[self.l.GetString(i)]
self.l.Delete(i) self.l.Delete(i)
self.l.Select(self.l.GetCount() - 1) self.l.Select(self.l.GetCount() - 1)
self.Refresh() self.Refresh()
def done(self, event, cb): def done(self, event, cb):
try: try:
......
#!/usr/bin/env python #!/usr/bin/env python
# This file is part of the Printrun suite. # This file is part of the Printrun suite.
# #
# Printrun is free software: you can redistribute it and/or modify # Printrun is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or # the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version. # (at your option) any later version.
# #
# Printrun is distributed in the hope that it will be useful, # Printrun is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with Printrun. If not, see <http://www.gnu.org/licenses/>. # along with Printrun. If not, see <http://www.gnu.org/licenses/>.
...@@ -45,7 +45,7 @@ class printcore(): ...@@ -45,7 +45,7 @@ class printcore():
self.clear = 0 #clear to send, enabled after responses self.clear = 0 #clear to send, enabled after responses
self.online = False #The printer has responded to the initial command and is active self.online = False #The printer has responded to the initial command and is active
self.printing = False #is a print currently running, true if printing, false if paused self.printing = False #is a print currently running, true if printing, false if paused
self.mainqueue = [] self.mainqueue = []
self.priqueue = [] self.priqueue = []
self.queueindex = 0 self.queueindex = 0
self.lineno = 0 self.lineno = 0
...@@ -69,7 +69,7 @@ class printcore(): ...@@ -69,7 +69,7 @@ class printcore():
self.print_thread = None self.print_thread = None
if port is not None and baud is not None: if port is not None and baud is not None:
self.connect(port, baud) self.connect(port, baud)
def disconnect(self): def disconnect(self):
"""Disconnects from printer and pauses the print """Disconnects from printer and pauses the print
""" """
...@@ -82,7 +82,7 @@ class printcore(): ...@@ -82,7 +82,7 @@ class printcore():
self.printer = None self.printer = None
self.online = False self.online = False
self.printing = False self.printing = False
def connect(self,port=None,baud=None): def connect(self,port=None,baud=None):
"""Set port and baudrate if given, then connect to printer """Set port and baudrate if given, then connect to printer
""" """
...@@ -98,7 +98,7 @@ class printcore(): ...@@ -98,7 +98,7 @@ class printcore():
self.stop_read_thread = False self.stop_read_thread = False
self.read_thread = Thread(target=self._listen) self.read_thread = Thread(target=self._listen)
self.read_thread.start() self.read_thread.start()
def reset(self): def reset(self):
"""Reset the printer """Reset the printer
""" """
...@@ -106,7 +106,7 @@ class printcore(): ...@@ -106,7 +106,7 @@ class printcore():
self.printer.setDTR(1) self.printer.setDTR(1)
time.sleep(0.2) time.sleep(0.2)
self.printer.setDTR(0) self.printer.setDTR(0)
def _readline(self): def _readline(self):
try: try:
line = self.printer.readline() line = self.printer.readline()
...@@ -164,11 +164,11 @@ class printcore(): ...@@ -164,11 +164,11 @@ class printcore():
self.clear = True self.clear = True
if line.startswith('ok') and "T:" in line and self.tempcb: if line.startswith('ok') and "T:" in line and self.tempcb:
#callback for temp, status, whatever #callback for temp, status, whatever
try: self.tempcb(line) try: self.tempcb(line)
except: pass except: pass
elif line.startswith('Error'): elif line.startswith('Error'):
if self.errorcb: if self.errorcb:
#callback for errors #callback for errors
try: self.errorcb(line) try: self.errorcb(line)
except: pass except: pass
if line.lower().startswith("resend") or line.startswith("rs"): if line.lower().startswith("resend") or line.startswith("rs"):
...@@ -181,10 +181,10 @@ class printcore(): ...@@ -181,10 +181,10 @@ class printcore():
self.resendfrom = toresend self.resendfrom = toresend
self.clear = True self.clear = True
self.clear = True self.clear = True
def _checksum(self, command): def _checksum(self, command):
return reduce(lambda x,y:x^y, map(ord, command)) return reduce(lambda x,y:x^y, map(ord, command))
def startprint(self, data, startindex = 0): def startprint(self, data, startindex = 0):
"""Start a print, data is an array of gcode commands. """Start a print, data is an array of gcode commands.
returns True on success, False if already printing. returns True on success, False if already printing.
...@@ -205,7 +205,7 @@ class printcore(): ...@@ -205,7 +205,7 @@ class printcore():
self.print_thread = Thread(target = self._print) self.print_thread = Thread(target = self._print)
self.print_thread.start() self.print_thread.start()
return True return True
def pause(self): def pause(self):
"""Pauses the print, saving the current position. """Pauses the print, saving the current position.
""" """
...@@ -213,7 +213,7 @@ class printcore(): ...@@ -213,7 +213,7 @@ class printcore():
self.printing = False self.printing = False
self.print_thread.join() self.print_thread.join()
self.print_thread = None self.print_thread = None
def resume(self): def resume(self):
"""Resumes a paused print. """Resumes a paused print.
""" """
...@@ -221,11 +221,11 @@ class printcore(): ...@@ -221,11 +221,11 @@ class printcore():
self.printing = True self.printing = True
self.print_thread = Thread(target = self._print) self.print_thread = Thread(target = self._print)
self.print_thread.start() self.print_thread.start()
def send(self, command, wait = 0): def send(self, command, wait = 0):
"""Adds a command to the checksummed main command queue if printing, or sends the command immediately if not printing """Adds a command to the checksummed main command queue if printing, or sends the command immediately if not printing
""" """
if self.online: if self.online:
if self.printing: if self.printing:
self.mainqueue.append(command) self.mainqueue.append(command)
...@@ -243,7 +243,7 @@ class printcore(): ...@@ -243,7 +243,7 @@ class printcore():
wait -= 1 wait -= 1
else: else:
print "Not connected to printer." print "Not connected to printer."
def send_now(self, command, wait = 0): def send_now(self, command, wait = 0):
"""Sends a command to the printer ahead of the command queue, without a checksum """Sends a command to the printer ahead of the command queue, without a checksum
""" """
...@@ -263,7 +263,7 @@ class printcore(): ...@@ -263,7 +263,7 @@ class printcore():
wait -= 1 wait -= 1
else: else:
print "Not connected to printer." print "Not connected to printer."
def _print(self): def _print(self):
if self.startcb: if self.startcb:
#callback for printing started #callback for printing started
...@@ -278,7 +278,7 @@ class printcore(): ...@@ -278,7 +278,7 @@ class printcore():
#callback for printing done #callback for printing done
try: self.endcb() try: self.endcb()
except: pass except: pass
def _sendnext(self): def _sendnext(self):
if not self.printer: if not self.printer:
return return
...@@ -313,7 +313,7 @@ class printcore(): ...@@ -313,7 +313,7 @@ class printcore():
self.queueindex = 0 self.queueindex = 0
self.lineno = 0 self.lineno = 0
self._send("M110", -1, True) self._send("M110", -1, True)
def _send(self, command, lineno = 0, calcchecksum = False): def _send(self, command, lineno = 0, calcchecksum = False):
if calcchecksum: if calcchecksum:
prefix = "N" + str(lineno) + " " + command prefix = "N" + str(lineno) + " " + command
......
...@@ -16,13 +16,13 @@ class SkeinforgeQuickEditDialog(wx.Dialog): ...@@ -16,13 +16,13 @@ class SkeinforgeQuickEditDialog(wx.Dialog):
self.cancelButton = wx.Button(self, wx.ID_CANCEL, "") self.cancelButton = wx.Button(self, wx.ID_CANCEL, "")
self.Bind(wx.EVT_BUTTON, self.OnExit, self.cancelButton) self.Bind(wx.EVT_BUTTON, self.OnExit, self.cancelButton)
self.Bind(wx.EVT_BUTTON, self.OnSave, self.okButton) self.Bind(wx.EVT_BUTTON, self.OnSave, self.okButton)
""" """
The following list determines which settings are shown. The following list determines which settings are shown.
The dictionary key is the plugin name and the value is a list of setting names as found in the corresponding .csv file for that plugin. The dictionary key is the plugin name and the value is a list of setting names as found in the corresponding .csv file for that plugin.
NOTE: Skeinforge is tightly integrated with Tkinter and there appears to be a dependency which stops radio-button values from being saved. NOTE: Skeinforge is tightly integrated with Tkinter and there appears to be a dependency which stops radio-button values from being saved.
Perhaps this can be solved, but at the moment this dialog cannot modify radio button values. One will have to use the main Skeinforge application. Perhaps this can be solved, but at the moment this dialog cannot modify radio button values. One will have to use the main Skeinforge application.
""" """
self.moduleSettingsMap = { self.moduleSettingsMap = {
'dimension':['Filament Diameter (mm):','Retraction Distance (millimeters):', 'Retraction Distance (millimeters):','Extruder Retraction Speed (mm/s):'], 'dimension':['Filament Diameter (mm):','Retraction Distance (millimeters):', 'Retraction Distance (millimeters):','Extruder Retraction Speed (mm/s):'],
...@@ -34,28 +34,28 @@ class SkeinforgeQuickEditDialog(wx.Dialog): ...@@ -34,28 +34,28 @@ class SkeinforgeQuickEditDialog(wx.Dialog):
'raft':['First Layer Main Feedrate (mm/s):','First Layer Perimeter Feedrate (mm/s):','First Layer Flow Rate Infill(scaler):','First Layer Flow Rate Perimeter(scaler):',], 'raft':['First Layer Main Feedrate (mm/s):','First Layer Perimeter Feedrate (mm/s):','First Layer Flow Rate Infill(scaler):','First Layer Flow Rate Perimeter(scaler):',],
'speed':['Main Feed Rate (mm/s):','Main Flow Rate (scaler):','Perimeter Feed Rate (mm/s):','Perimeter Flow Rate (scaler):','Travel Feed Rate (mm/s):'] 'speed':['Main Feed Rate (mm/s):','Main Flow Rate (scaler):','Perimeter Feed Rate (mm/s):','Perimeter Flow Rate (scaler):','Travel Feed Rate (mm/s):']
} }
self.scrollbarPanel = wx.ScrolledWindow(self, -1, style=wx.TAB_TRAVERSAL) self.scrollbarPanel = wx.ScrolledWindow(self, -1, style=wx.TAB_TRAVERSAL)
self.settingsSizer = self.getProfileSettings() self.settingsSizer = self.getProfileSettings()
self.scrollbarPanel.SetSizer(self.settingsSizer) self.scrollbarPanel.SetSizer(self.settingsSizer)
self.__set_properties() self.__set_properties()
self.__do_layout() self.__do_layout()
self.Show() self.Show()
def __set_properties(self): def __set_properties(self):
self.profileName = skeinforge_profile.getProfileName(skeinforge_profile.getCraftTypeName()) self.profileName = skeinforge_profile.getProfileName(skeinforge_profile.getCraftTypeName())
self.SetTitle("Skeinforge Quick Edit Profile: " + self.profileName) self.SetTitle("Skeinforge Quick Edit Profile: " + self.profileName)
# For some reason the dialog size is not consistent between Windows and Linux - this is a hack to get it working # For some reason the dialog size is not consistent between Windows and Linux - this is a hack to get it working
if (os.name == 'nt'): if (os.name == 'nt'):
self.SetMinSize(wx.DLG_SZE(self, (465, 370))) self.SetMinSize(wx.DLG_SZE(self, (465, 370)))
else: else:
self.SetSize(wx.DLG_SZE(self, (465, 325))) self.SetSize(wx.DLG_SZE(self, (465, 325)))
self.SetPosition((0, 0)) self.SetPosition((0, 0))
self.scrollbarPanel.SetScrollRate(10, 10) self.scrollbarPanel.SetScrollRate(10, 10)
def __do_layout(self): def __do_layout(self):
mainSizer = wx.BoxSizer(wx.VERTICAL) mainSizer = wx.BoxSizer(wx.VERTICAL)
actionsSizer = wx.BoxSizer(wx.HORIZONTAL) actionsSizer = wx.BoxSizer(wx.HORIZONTAL)
...@@ -65,34 +65,34 @@ class SkeinforgeQuickEditDialog(wx.Dialog): ...@@ -65,34 +65,34 @@ class SkeinforgeQuickEditDialog(wx.Dialog):
mainSizer.Add(actionsSizer, 0, wx.ALIGN_RIGHT | wx.ALL, 5) mainSizer.Add(actionsSizer, 0, wx.ALIGN_RIGHT | wx.ALL, 5)
self.SetSizer(mainSizer) self.SetSizer(mainSizer)
self.Layout() self.Layout()
def getProfileSettings(self): def getProfileSettings(self):
settingsSizer = wx.GridBagSizer(hgap=2, vgap=1) settingsSizer = wx.GridBagSizer(hgap=2, vgap=1)
settingsRow = 0 settingsRow = 0
for craftName in sorted(self.moduleSettingsMap.keys()): for craftName in sorted(self.moduleSettingsMap.keys()):
craftStaticBox = wx.StaticBox(self.scrollbarPanel, -1, craftName.capitalize()) craftStaticBox = wx.StaticBox(self.scrollbarPanel, -1, craftName.capitalize())
craftStaticBoxSizer = wx.StaticBoxSizer(craftStaticBox, wx.VERTICAL) craftStaticBoxSizer = wx.StaticBoxSizer(craftStaticBox, wx.VERTICAL)
# For some reason the dialog size is not consistent between Windows and Linux - this is a hack to get it working # For some reason the dialog size is not consistent between Windows and Linux - this is a hack to get it working
if (os.name == 'nt'): if (os.name == 'nt'):
craftStaticBoxSizer.SetMinSize((320, -1)) craftStaticBoxSizer.SetMinSize((320, -1))
else: else:
craftStaticBoxSizer.SetMinSize((450, -1)) craftStaticBoxSizer.SetMinSize((450, -1))
pluginModule = archive.getModuleWithPath(os.path.join(skeinforge_craft.getPluginsDirectoryPath(), craftName)) pluginModule = archive.getModuleWithPath(os.path.join(skeinforge_craft.getPluginsDirectoryPath(), craftName))
repo = pluginModule.getNewRepository() repo = pluginModule.getNewRepository()
for setting in settings.getReadRepository(repo).preferences: for setting in settings.getReadRepository(repo).preferences:
if setting.name in self.moduleSettingsMap[craftName]: if setting.name in self.moduleSettingsMap[craftName]:
settingSizer = wx.GridBagSizer(hgap=2, vgap=2) settingSizer = wx.GridBagSizer(hgap=2, vgap=2)
settingSizer.AddGrowableCol(0) settingSizer.AddGrowableCol(0)
settingRow = 0 settingRow = 0
settingLabel = wx.StaticText(self.scrollbarPanel, -1, setting.name) settingLabel = wx.StaticText(self.scrollbarPanel, -1, setting.name)
settingLabel.Wrap(400) settingLabel.Wrap(400)
settingSizer.Add(settingLabel, pos=(settingRow, 0)) settingSizer.Add(settingLabel, pos=(settingRow, 0))
if (isinstance(setting.value, bool)): if (isinstance(setting.value, bool)):
checkbox = wx.CheckBox(self.scrollbarPanel) checkbox = wx.CheckBox(self.scrollbarPanel)
checkbox.SetName(craftName + '.' + setting.name) checkbox.SetName(craftName + '.' + setting.name)
...@@ -103,7 +103,7 @@ class SkeinforgeQuickEditDialog(wx.Dialog): ...@@ -103,7 +103,7 @@ class SkeinforgeQuickEditDialog(wx.Dialog):
textCtrl = wx.TextCtrl(self.scrollbarPanel, value=str(setting.value), size=(50, -1)) textCtrl = wx.TextCtrl(self.scrollbarPanel, value=str(setting.value), size=(50, -1))
textCtrl.SetName(craftName + '.' + setting.name) textCtrl.SetName(craftName + '.' + setting.name)
settingSizer.Add(textCtrl, pos=(settingRow, 1)) settingSizer.Add(textCtrl, pos=(settingRow, 1))
craftStaticBoxSizer.Add(settingSizer, 1, wx.EXPAND, 0) craftStaticBoxSizer.Add(settingSizer, 1, wx.EXPAND, 0)
settingRow += 1 settingRow += 1
col = settingsRow % 2 col = settingsRow % 2
...@@ -114,7 +114,7 @@ class SkeinforgeQuickEditDialog(wx.Dialog): ...@@ -114,7 +114,7 @@ class SkeinforgeQuickEditDialog(wx.Dialog):
def OnExit(self, e): def OnExit(self, e):
self.Destroy() self.Destroy()
def OnSave(self, e): def OnSave(self, e):
for x in self.scrollbarPanel.GetChildren(): for x in self.scrollbarPanel.GetChildren():
if (isinstance(x, (wx.CheckBox, wx.TextCtrl))): if (isinstance(x, (wx.CheckBox, wx.TextCtrl))):
......
...@@ -13,7 +13,7 @@ class MyFrame(wx.Frame): ...@@ -13,7 +13,7 @@ class MyFrame(wx.Frame):
def __init__(self, parent, mysize): def __init__(self, parent, mysize):
wx.Frame.__init__(self, parent, wx.ID_ANY, size=mysize) wx.Frame.__init__(self, parent, wx.ID_ANY, size=mysize)
self.SetBackgroundColour('black') self.SetBackgroundColour('black')
# milliseconds per frame # milliseconds per frame
self.delay = 60 self.delay = 60
# number of loops # number of loops
...@@ -41,7 +41,7 @@ class MyFrame(wx.Frame): ...@@ -41,7 +41,7 @@ class MyFrame(wx.Frame):
self.image_list = [] self.image_list = []
for image_file in file_list: for image_file in file_list:
self.image_list.append(wx.Bitmap(image_file)) self.image_list.append(wx.Bitmap(image_file))
# bind the panel to the paint event # bind the panel to the paint event
wx.EVT_PAINT(self, self.onPaint) wx.EVT_PAINT(self, self.onPaint)
...@@ -73,4 +73,4 @@ width = 800 ...@@ -73,4 +73,4 @@ width = 800
frameoffset = 35 frameoffset = 35
height = 600 + frameoffset height = 600 + frameoffset
MyFrame(None, (width, height)).Show() MyFrame(None, (width, height)).Show()
app.MainLoop() app.MainLoop()
\ No newline at end of file
...@@ -23,9 +23,9 @@ modify it under the terms of the GNU Lesser General Public License as ...@@ -23,9 +23,9 @@ modify it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version. License, or (at your option) any later version.
As a special exception, the copyright holders of this library As a special exception, the copyright holders of this library
hereby recind Section 3 of the GNU Lesser General Public License. This hereby recind Section 3 of the GNU Lesser General Public License. This
means that you MAY NOT apply the terms of the ordinary GNU General means that you MAY NOT apply the terms of the ordinary GNU General
Public License instead of this License to any given copy of the Public License instead of this License to any given copy of the
Library. This has been done to prevent users of the Library from being Library. This has been done to prevent users of the Library from being
denied access or the ability to use future improvements. denied access or the ability to use future improvements.
...@@ -94,7 +94,7 @@ class BufferedCanvas(wx.Panel): ...@@ -94,7 +94,7 @@ class BufferedCanvas(wx.Panel):
Causes the canvas to be updated. Causes the canvas to be updated.
""" """
self.Refresh() self.Refresh()
def getWidthHeight(self): def getWidthHeight(self):
width,height = self.GetClientSizeTuple() width,height = self.GetClientSizeTuple()
if width == 0: if width == 0:
......
...@@ -2,150 +2,150 @@ ...@@ -2,150 +2,150 @@
#Interactive RepRap e axis calibration program #Interactive RepRap e axis calibration program
#(C) Nathan Zadoks 2011 #(C) Nathan Zadoks 2011
#Licensed under CC-BY-SA or GPLv2 and higher - Pick your poison. #Licensed under CC-BY-SA or GPLv2 and higher - Pick your poison.
s=300 #Extrusion speed (mm/min) s=300 #Extrusion speed (mm/min)
n=100 #Default length to extrude n=100 #Default length to extrude
m= 0 #User-entered measured extrusion length m= 0 #User-entered measured extrusion length
k=300 #Default amount of steps per mm k=300 #Default amount of steps per mm
port='/dev/ttyUSB0' #Default serial port to connect to printer port='/dev/ttyUSB0' #Default serial port to connect to printer
temp=210 #Default extrusion temperature temp=210 #Default extrusion temperature
tempmax=250 #Maximum extrusion temperature tempmax=250 #Maximum extrusion temperature
t=int(n*60)/s #Time to wait for extrusion t=int(n*60)/s #Time to wait for extrusion
try: try:
from printdummy import printcore from printdummy import printcore
except ImportError: except ImportError:
from printcore import printcore from printcore import printcore
import time,getopt,sys,os import time,getopt,sys,os
def float_input(prompt=''): def float_input(prompt=''):
import sys import sys
f=None f=None
while f==None: while f==None:
s=raw_input(prompt) s=raw_input(prompt)
try: try:
f=float(s) f=float(s)
except ValueError: except ValueError:
sys.stderr.write("Not a valid floating-point number.\n") sys.stderr.write("Not a valid floating-point number.\n")
sys.stderr.flush() sys.stderr.flush()
return f return f
def wait(t,m=''): def wait(t,m=''):
import time,sys import time,sys
sys.stdout.write(m+'['+(' '*t)+']\r'+m+'[') sys.stdout.write(m+'['+(' '*t)+']\r'+m+'[')
sys.stdout.flush() sys.stdout.flush()
for i in range(t): for i in range(t):
for s in ['|\b','/\b','-\b','\\\b','|']: for s in ['|\b','/\b','-\b','\\\b','|']:
sys.stdout.write(s) sys.stdout.write(s)
sys.stdout.flush() sys.stdout.flush()
time.sleep(1.0/5) time.sleep(1.0/5)
print print
def w(s): def w(s):
sys.stdout.write(s) sys.stdout.write(s)
sys.stdout.flush() sys.stdout.flush()
def heatup(p,temp,s=0): def heatup(p,temp,s=0):
curtemp=gettemp(p) curtemp=gettemp(p)
p.send_now('M109 S%03d'%temp) p.send_now('M109 S%03d'%temp)
p.temp=0 p.temp=0
if not s: w("Heating extruder up..") if not s: w("Heating extruder up..")
f=False f=False
while curtemp<=(temp-1): while curtemp<=(temp-1):
p.send_now('M105') p.send_now('M105')
time.sleep(0.5) time.sleep(0.5)
if not f: if not f:
time.sleep(1.5) time.sleep(1.5)
f=True f=True
curtemp=gettemp(p) curtemp=gettemp(p)
if curtemp: w(u"\rHeating extruder up.. %3d \xb0C"%curtemp) if curtemp: w(u"\rHeating extruder up.. %3d \xb0C"%curtemp)
if s: print if s: print
else: print "\nReady." else: print "\nReady."
def gettemp(p): def gettemp(p):
try: p.logl try: p.logl
except: setattr(p,'logl',0) except: setattr(p,'logl',0)
try: p.temp try: p.temp
except: setattr(p,'temp',0) except: setattr(p,'temp',0)
for n in range(p.logl,len(p.log)): for n in range(p.logl,len(p.log)):
line=p.log[n] line=p.log[n]
if 'T:' in line: if 'T:' in line:
try: try:
setattr(p,'temp',int(line.split('T:')[1].split()[0])) setattr(p,'temp',int(line.split('T:')[1].split()[0]))
except: print line except: print line
p.logl=len(p.log) p.logl=len(p.log)
return p.temp return p.temp
if not os.path.exists(port): if not os.path.exists(port):
port=0 port=0
#Parse options #Parse options
help=u""" help=u"""
%s [ -l DISTANCE ] [ -s STEPS ] [ -t TEMP ] [ -p PORT ] %s [ -l DISTANCE ] [ -s STEPS ] [ -t TEMP ] [ -p PORT ]
-l --length Length of filament to extrude for each calibration step (default: %d mm) -l --length Length of filament to extrude for each calibration step (default: %d mm)
-s --steps Initial amount of steps to use (default: %d steps) -s --steps Initial amount of steps to use (default: %d steps)
-t --temp Extrusion temperature in degrees Celsius (default: %d \xb0C, max %d \xb0C) -t --temp Extrusion temperature in degrees Celsius (default: %d \xb0C, max %d \xb0C)
-p --port Serial port the printer is connected to (default: %s) -p --port Serial port the printer is connected to (default: %s)
-h --help This cruft. -h --help This cruft.
"""[1:-1].encode('utf-8')%(sys.argv[0],n,k,temp,tempmax,port if port else 'auto') """[1:-1].encode('utf-8')%(sys.argv[0],n,k,temp,tempmax,port if port else 'auto')
try: try:
opts,args=getopt.getopt(sys.argv[1:],"hl:s:t:p:",["help","length=","steps=","temp=","port="]) opts,args=getopt.getopt(sys.argv[1:],"hl:s:t:p:",["help","length=","steps=","temp=","port="])
except getopt.GetoptError,err: except getopt.GetoptError,err:
print str(err) print str(err)
print help print help
sys.exit(2) sys.exit(2)
for o,a in opts: for o,a in opts:
if o in ('-h','--help'): if o in ('-h','--help'):
print help print help
sys.exit() sys.exit()
elif o in ('-l','--length'): elif o in ('-l','--length'):
n=float(a) n=float(a)
elif o in ('-s','--steps'): elif o in ('-s','--steps'):
k=int(a) k=int(a)
elif o in ('-t','--temp'): elif o in ('-t','--temp'):
temp=int(a) temp=int(a)
if temp>=tempmax: if temp>=tempmax:
print (u'%d \xb0C? Are you insane?'.encode('utf-8')%temp)+(" That's over nine thousand!" if temp>9000 else '') print (u'%d \xb0C? Are you insane?'.encode('utf-8')%temp)+(" That's over nine thousand!" if temp>9000 else '')
sys.exit(255) sys.exit(255)
elif o in ('-p','--port'): elif o in ('-p','--port'):
port=a port=a
#Show initial parameters #Show initial parameters
print "Initial parameters" print "Initial parameters"
print "Steps per mm: %3d steps"%k print "Steps per mm: %3d steps"%k
print "Length extruded: %3d mm"%n print "Length extruded: %3d mm"%n
print print
print "Serial port: %s"%(port if port else 'auto') print "Serial port: %s"%(port if port else 'auto')
p=None p=None
try: try:
#Connect to printer #Connect to printer
w("Connecting to printer..") w("Connecting to printer..")
try: try:
p=printcore(port,115200) p=printcore(port,115200)
except: except:
print 'Error.' print 'Error.'
raise raise
while not p.online: while not p.online:
time.sleep(1) time.sleep(1)
w('.') w('.')
print " connected." print " connected."
heatup(p,temp) heatup(p,temp)
#Calibration loop #Calibration loop
while n!=m: while n!=m:
heatup(p,temp,True) heatup(p,temp,True)
p.send_now("G92 E0") #Reset e axis p.send_now("G92 E0") #Reset e axis
p.send_now("G1 E%d F%d"%(n,s)) #Extrude length of filament p.send_now("G1 E%d F%d"%(n,s)) #Extrude length of filament
wait(t,'Extruding.. ') wait(t,'Extruding.. ')
m=float_input("How many millimeters of filament were extruded? ") m=float_input("How many millimeters of filament were extruded? ")
if m==0: continue if m==0: continue
if n!=m: if n!=m:
k=(n/m)*k k=(n/m)*k
p.send_now("M92 E%d"%int(round(k))) #Set new step count p.send_now("M92 E%d"%int(round(k))) #Set new step count
print "Steps per mm: %3d steps"%k #Tell user print "Steps per mm: %3d steps"%k #Tell user
print 'Calibration completed.' #Yay! print 'Calibration completed.' #Yay!
except KeyboardInterrupt: except KeyboardInterrupt:
pass pass
finally: finally:
if p: p.disconnect() if p: p.disconnect()
...@@ -263,5 +263,3 @@ class Graph(BufferedCanvas): ...@@ -263,5 +263,3 @@ class Graph(BufferedCanvas):
self.drawextruder0temp(dc, gc) self.drawextruder0temp(dc, gc)
self.drawextruder1targettemp(dc, gc) self.drawextruder1targettemp(dc, gc)
self.drawextruder1temp(dc, gc) self.drawextruder1temp(dc, gc)
# This file is part of the Printrun suite. # This file is part of the Printrun suite.
# #
# Printrun is free software: you can redistribute it and/or modify # Printrun is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or # the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version. # (at your option) any later version.
# #
# Printrun is distributed in the hope that it will be useful, # Printrun is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with Printrun. If not, see <http://www.gnu.org/licenses/>. # along with Printrun. If not, see <http://www.gnu.org/licenses/>.
import wx,time import wx,time
...@@ -20,9 +20,9 @@ ID_ABOUT = 101 ...@@ -20,9 +20,9 @@ ID_ABOUT = 101
ID_EXIT = 110 ID_EXIT = 110
class window(wx.Frame): class window(wx.Frame):
def __init__(self,f,size=(600,600),build_dimensions=[200,200,100,0,0,0],grid=(10,50),extrusion_width=0.5): def __init__(self,f,size=(600,600),build_dimensions=[200,200,100,0,0,0],grid=(10,50),extrusion_width=0.5):
wx.Frame.__init__(self,None,title="Gcode view, shift to move view, mousewheel to set layer",size=(size[0],size[1])) wx.Frame.__init__(self,None,title="Gcode view, shift to move view, mousewheel to set layer",size=(size[0],size[1]))
self.p=gviz(self,size=size,build_dimensions=build_dimensions,grid=grid,extrusion_width=extrusion_width) self.p=gviz(self,size=size,build_dimensions=build_dimensions,grid=grid,extrusion_width=extrusion_width)
vbox = wx.BoxSizer(wx.VERTICAL) vbox = wx.BoxSizer(wx.VERTICAL)
toolbar = wx.ToolBar(self, -1, style=wx.TB_HORIZONTAL | wx.NO_BORDER) toolbar = wx.ToolBar(self, -1, style=wx.TB_HORIZONTAL | wx.NO_BORDER)
toolbar.AddSimpleTool(1, wx.Image(imagefile('zoom_in.png'), wx.BITMAP_TYPE_PNG).ConvertToBitmap(), 'Zoom In [+]', '') toolbar.AddSimpleTool(1, wx.Image(imagefile('zoom_in.png'), wx.BITMAP_TYPE_PNG).ConvertToBitmap(), 'Zoom In [+]', '')
...@@ -42,8 +42,8 @@ class window(wx.Frame): ...@@ -42,8 +42,8 @@ class window(wx.Frame):
self.Bind(wx.EVT_TOOL, lambda x:self.p.layerdown(), id=4) self.Bind(wx.EVT_TOOL, lambda x:self.p.layerdown(), id=4)
self.Bind(wx.EVT_TOOL, self.resetview, id=5) self.Bind(wx.EVT_TOOL, self.resetview, id=5)
#self.Bind(wx.EVT_TOOL, lambda x:self.p.inject(), id=5) #self.Bind(wx.EVT_TOOL, lambda x:self.p.inject(), id=5)
self.CreateStatusBar(1); self.CreateStatusBar(1);
self.SetStatusText("Layer number and Z position show here when you scroll"); self.SetStatusText("Layer number and Z position show here when you scroll");
#self.bu=wx.Button(self.p,-1,"U",pos=(0,100),size=(40,140)) #self.bu=wx.Button(self.p,-1,"U",pos=(0,100),size=(40,140))
...@@ -51,19 +51,19 @@ class window(wx.Frame): ...@@ -51,19 +51,19 @@ class window(wx.Frame):
#self.bi=wx.Button(self.p,-1,"+",pos=(40,100),size=(40,140)) #self.bi=wx.Button(self.p,-1,"+",pos=(40,100),size=(40,140))
#self.bo=wx.Button(self.p,-1,"-",pos=(40,140),size=(40,140)) #self.bo=wx.Button(self.p,-1,"-",pos=(40,140),size=(40,140))
#self.bs=wx.Button(self.p, -1, "Inject", pos=(85, 103), size=(50, 20)) #self.bs=wx.Button(self.p, -1, "Inject", pos=(85, 103), size=(50, 20))
#self.bu.SetToolTip(wx.ToolTip("Move up one layer")) #self.bu.SetToolTip(wx.ToolTip("Move up one layer"))
#self.bd.SetToolTip(wx.ToolTip("Move down one layer")) #self.bd.SetToolTip(wx.ToolTip("Move down one layer"))
#self.bi.SetToolTip(wx.ToolTip("Zoom view in")) #self.bi.SetToolTip(wx.ToolTip("Zoom view in"))
#self.bo.SetToolTip(wx.ToolTip("Zoom view out")) #self.bo.SetToolTip(wx.ToolTip("Zoom view out"))
#self.bs.SetToolTip(wx.ToolTip("Insert Code at start of this layer")) #self.bs.SetToolTip(wx.ToolTip("Insert Code at start of this layer"))
#self.bu.Bind(wx.EVT_BUTTON,lambda x:self.p.layerup()) #self.bu.Bind(wx.EVT_BUTTON,lambda x:self.p.layerup())
#self.bd.Bind(wx.EVT_BUTTON,lambda x:self.p.layerdown()) #self.bd.Bind(wx.EVT_BUTTON,lambda x:self.p.layerdown())
#self.bi.Bind(wx.EVT_BUTTON,lambda x:self.p.zoom(200,200,1.2)) #self.bi.Bind(wx.EVT_BUTTON,lambda x:self.p.zoom(200,200,1.2))
#self.bo.Bind(wx.EVT_BUTTON,lambda x:self.p.zoom(200,200,1/1.2)) #self.bo.Bind(wx.EVT_BUTTON,lambda x:self.p.zoom(200,200,1/1.2))
#self.bs.Bind(wx.EVT_BUTTON,lambda x:self.p.inject()) #self.bs.Bind(wx.EVT_BUTTON,lambda x:self.p.inject())
s=time.time() s=time.time()
#print time.time()-s #print time.time()-s
self.initpos=[0,0] self.initpos=[0,0]
...@@ -77,12 +77,12 @@ class window(wx.Frame): ...@@ -77,12 +77,12 @@ class window(wx.Frame):
self.Bind(wx.EVT_MOUSEWHEEL,self.zoom) self.Bind(wx.EVT_MOUSEWHEEL,self.zoom)
self.p.Bind(wx.EVT_MOUSE_EVENTS,self.mouse) self.p.Bind(wx.EVT_MOUSE_EVENTS,self.mouse)
self.Bind(wx.EVT_MOUSE_EVENTS,self.mouse) self.Bind(wx.EVT_MOUSE_EVENTS,self.mouse)
def resetview(self,event): def resetview(self,event):
self.p.translate=[0.0,0.0] self.p.translate=[0.0,0.0]
self.p.scale=self.p.basescale self.p.scale=self.p.basescale
self.p.zoom(0,0,1.0) self.p.zoom(0,0,1.0)
def mouse(self,event): def mouse(self,event):
if event.ButtonUp(wx.MOUSE_BTN_LEFT): if event.ButtonUp(wx.MOUSE_BTN_LEFT):
if(self.initpos is not None): if(self.initpos is not None):
...@@ -97,14 +97,14 @@ class window(wx.Frame): ...@@ -97,14 +97,14 @@ class window(wx.Frame):
self.basetrans[1]+(e[1]-self.initpos[1]) ] self.basetrans[1]+(e[1]-self.initpos[1]) ]
self.p.repaint() self.p.repaint()
self.p.Refresh() self.p.Refresh()
else: else:
event.Skip() event.Skip()
def key(self, event): def key(self, event):
# Keycode definitions # Keycode definitions
kup=[85, 315] # Up keys kup=[85, 315] # Up keys
kdo=[68, 317] # Down Keys kdo=[68, 317] # Down Keys
kzi=[388, 316, 61] # Zoom In Keys kzi=[388, 316, 61] # Zoom In Keys
kzo=[390, 314, 45] # Zoom Out Keys kzo=[390, 314, 45] # Zoom Out Keys
x=event.GetKeyCode() x=event.GetKeyCode()
...@@ -118,7 +118,7 @@ class window(wx.Frame): ...@@ -118,7 +118,7 @@ class window(wx.Frame):
#else: #else:
# if x==wx.WXK_UP: # if x==wx.WXK_UP:
# self.p.layerup() # self.p.layerup()
# if x==wx.WXK_DOWN: # if x==wx.WXK_DOWN:
# self.p.layerdown() # self.p.layerdown()
if x in kup: if x in kup:
self.p.layerup() self.p.layerup()
...@@ -128,7 +128,7 @@ class window(wx.Frame): ...@@ -128,7 +128,7 @@ class window(wx.Frame):
self.p.zoom(cx,cy,1.2) self.p.zoom(cx,cy,1.2)
if x in kzo: if x in kzo:
self.p.zoom(cx, cy, 1/1.2) self.p.zoom(cx, cy, 1/1.2)
#print p.lines.keys() #print p.lines.keys()
def zoom(self, event): def zoom(self, event):
z=event.GetWheelRotation() z=event.GetWheelRotation()
...@@ -138,7 +138,7 @@ class window(wx.Frame): ...@@ -138,7 +138,7 @@ class window(wx.Frame):
else: else:
if z > 0: self.p.zoom(event.GetX(),event.GetY(),1.2) if z > 0: self.p.zoom(event.GetX(),event.GetY(),1.2)
elif z < 0: self.p.zoom(event.GetX(),event.GetY(),1/1.2) elif z < 0: self.p.zoom(event.GetX(),event.GetY(),1/1.2)
class gviz(wx.Panel): class gviz(wx.Panel):
def __init__(self,parent,size=(200,200),build_dimensions=[200,200,100,0,0,0],grid=(10,50),extrusion_width=0.5): def __init__(self,parent,size=(200,200),build_dimensions=[200,200,100,0,0,0],grid=(10,50),extrusion_width=0.5):
wx.Panel.__init__(self,parent,-1,size=(size[0],size[1])) wx.Panel.__init__(self,parent,-1,size=(size[0],size[1]))
...@@ -172,12 +172,12 @@ class gviz(wx.Panel): ...@@ -172,12 +172,12 @@ class gviz(wx.Panel):
self.hilightarcs=[] self.hilightarcs=[]
self.dirty=1 self.dirty=1
self.blitmap=wx.EmptyBitmap(self.GetClientSize()[0],self.GetClientSize()[1],-1) self.blitmap=wx.EmptyBitmap(self.GetClientSize()[0],self.GetClientSize()[1],-1)
def inject(self): def inject(self):
#import pdb; pdb.set_trace() #import pdb; pdb.set_trace()
print"Inject code here..." print"Inject code here..."
print "Layer "+str(self.layerindex +1)+" - Z = "+str(self.layers[self.layerindex])+" mm" print "Layer "+str(self.layerindex +1)+" - Z = "+str(self.layers[self.layerindex])+" mm"
def clear(self): def clear(self):
self.lastpos=[0,0,0,0,0,0,0] self.lastpos=[0,0,0,0,0,0,0]
self.lines={} self.lines={}
...@@ -190,7 +190,7 @@ class gviz(wx.Panel): ...@@ -190,7 +190,7 @@ class gviz(wx.Panel):
self.layerindex=0 self.layerindex=0
self.showall=0 self.showall=0
self.dirty=1 self.dirty=1
#self.repaint() #self.repaint()
def layerup(self): def layerup(self):
if(self.layerindex+1<len(self.layers)): if(self.layerindex+1<len(self.layers)):
self.layerindex+=1 self.layerindex+=1
...@@ -198,15 +198,15 @@ class gviz(wx.Panel): ...@@ -198,15 +198,15 @@ class gviz(wx.Panel):
self.parent.SetStatusText("Layer "+str(self.layerindex +1)+" - Going Up - Z = "+str(self.layers[self.layerindex])+" mm",0) self.parent.SetStatusText("Layer "+str(self.layerindex +1)+" - Going Up - Z = "+str(self.layers[self.layerindex])+" mm",0)
self.repaint() self.repaint()
self.Refresh() self.Refresh()
def layerdown(self): def layerdown(self):
if(self.layerindex>0): if(self.layerindex>0):
self.layerindex-=1 self.layerindex-=1
# Display layer info on statusbar (Jezmy) # Display layer info on statusbar (Jezmy)
self.parent.SetStatusText("Layer "+str(self.layerindex + 1)+" - Going Down - Z = "+str(self.layers[self.layerindex])+ " mm",0) self.parent.SetStatusText("Layer "+str(self.layerindex + 1)+" - Going Down - Z = "+str(self.layers[self.layerindex])+ " mm",0)
self.repaint() self.repaint()
self.Refresh() self.Refresh()
def setlayer(self,layer): def setlayer(self,layer):
try: try:
self.layerindex=self.layers.index(layer) self.layerindex=self.layers.index(layer)
...@@ -215,17 +215,17 @@ class gviz(wx.Panel): ...@@ -215,17 +215,17 @@ class gviz(wx.Panel):
self.showall=0 self.showall=0
except: except:
pass pass
def resize(self,event): def resize(self,event):
size=self.GetClientSize() size=self.GetClientSize()
newsize=min(float(size[0])/self.size[0],float(size[1])/self.size[1]) newsize=min(float(size[0])/self.size[0],float(size[1])/self.size[1])
self.size=self.GetClientSize() self.size=self.GetClientSize()
wx.CallAfter(self.zoom,0,0,newsize) wx.CallAfter(self.zoom,0,0,newsize)
def zoom(self,x,y,factor): def zoom(self,x,y,factor):
self.scale = [s * factor for s in self.scale] self.scale = [s * factor for s in self.scale]
self.translate = [ x - (x-self.translate[0]) * factor, self.translate = [ x - (x-self.translate[0]) * factor,
y - (y-self.translate[1]) * factor] y - (y-self.translate[1]) * factor]
penwidth = max(1.0,self.filament_width*((self.scale[0]+self.scale[1])/2.0)) penwidth = max(1.0,self.filament_width*((self.scale[0]+self.scale[1])/2.0))
...@@ -234,8 +234,8 @@ class gviz(wx.Panel): ...@@ -234,8 +234,8 @@ class gviz(wx.Panel):
#self.dirty=1 #self.dirty=1
self.repaint() self.repaint()
self.Refresh() self.Refresh()
def repaint(self): def repaint(self):
self.blitmap=wx.EmptyBitmap(self.GetClientSize()[0],self.GetClientSize()[1],-1) self.blitmap=wx.EmptyBitmap(self.GetClientSize()[0],self.GetClientSize()[1],-1)
dc=wx.MemoryDC() dc=wx.MemoryDC()
...@@ -257,7 +257,7 @@ class gviz(wx.Panel): ...@@ -257,7 +257,7 @@ class gviz(wx.Panel):
dc.SetBrush(wx.Brush((0,255,0))) dc.SetBrush(wx.Brush((0,255,0)))
if len(self.layers): if len(self.layers):
dc.DrawRectangle(self.size[0]-14,(1.0-(1.0*(self.layerindex+1))/len(self.layers))*self.size[1],13,self.size[1]-1) dc.DrawRectangle(self.size[0]-14,(1.0-(1.0*(self.layerindex+1))/len(self.layers))*self.size[1],13,self.size[1]-1)
def _drawlines(lines,pens): def _drawlines(lines,pens):
def _scaler(x): def _scaler(x):
return (self.scale[0]*x[0]+self.translate[0], return (self.scale[0]*x[0]+self.translate[0],
...@@ -266,7 +266,7 @@ class gviz(wx.Panel): ...@@ -266,7 +266,7 @@ class gviz(wx.Panel):
self.scale[1]*x[3]+self.translate[1],) self.scale[1]*x[3]+self.translate[1],)
scaled_lines = map(_scaler,lines) scaled_lines = map(_scaler,lines)
dc.DrawLineList(scaled_lines, pens) dc.DrawLineList(scaled_lines, pens)
def _drawarcs(arcs,pens): def _drawarcs(arcs,pens):
def _scaler(x): def _scaler(x):
return (self.scale[0]*x[0]+self.translate[0], return (self.scale[0]*x[0]+self.translate[0],
...@@ -280,7 +280,7 @@ class gviz(wx.Panel): ...@@ -280,7 +280,7 @@ class gviz(wx.Panel):
dc.SetPen(pens[i] if type(pens).__name__ == 'list' else pens) dc.SetPen(pens[i] if type(pens).__name__ == 'list' else pens)
dc.SetBrush(wx.TRANSPARENT_BRUSH) dc.SetBrush(wx.TRANSPARENT_BRUSH)
dc.DrawArc(*scaled_arcs[i]) dc.DrawArc(*scaled_arcs[i])
if self.showall: if self.showall:
l=[] l=[]
for i in self.layers: for i in self.layers:
...@@ -295,12 +295,12 @@ class gviz(wx.Panel): ...@@ -295,12 +295,12 @@ class gviz(wx.Panel):
_drawarcs(self.arcs[self.layers[layer_i]], self.fades[self.layerindex-layer_i-1]) _drawarcs(self.arcs[self.layers[layer_i]], self.fades[self.layerindex-layer_i-1])
_drawlines(self.lines[self.layers[self.layerindex]], self.pens[self.layers[self.layerindex]]) _drawlines(self.lines[self.layers[self.layerindex]], self.pens[self.layers[self.layerindex]])
_drawarcs(self.arcs[self.layers[self.layerindex]], self.arcpens[self.layers[self.layerindex]]) _drawarcs(self.arcs[self.layers[self.layerindex]], self.arcpens[self.layers[self.layerindex]])
_drawlines(self.hilight, self.hlpen) _drawlines(self.hilight, self.hlpen)
_drawarcs(self.hilightarcs, self.hlpen) _drawarcs(self.hilightarcs, self.hlpen)
dc.SelectObject(wx.NullBitmap) dc.SelectObject(wx.NullBitmap)
def paint(self,event): def paint(self,event):
dc=wx.PaintDC(self) dc=wx.PaintDC(self)
if(self.dirty): if(self.dirty):
...@@ -309,12 +309,12 @@ class gviz(wx.Panel): ...@@ -309,12 +309,12 @@ class gviz(wx.Panel):
sz=self.GetClientSize() sz=self.GetClientSize()
dc.DrawBitmap(self.blitmap,0,0) dc.DrawBitmap(self.blitmap,0,0)
del dc del dc
def addfile(self,gcodes=[]): def addfile(self,gcodes=[]):
self.clear() self.clear()
for i in gcodes: for i in gcodes:
self.addgcode(i) self.addgcode(i)
def addgcode(self,gcode="M105",hilight=0): def addgcode(self,gcode="M105",hilight=0):
gcode=gcode.split("*")[0] gcode=gcode.split("*")[0]
gcode=gcode.split(";")[0] gcode=gcode.split(";")[0]
...@@ -323,7 +323,7 @@ class gviz(wx.Panel): ...@@ -323,7 +323,7 @@ class gviz(wx.Panel):
return return
if gcode[0][0] == 'n': if gcode[0][0] == 'n':
gcode.pop(0) gcode.pop(0)
def _readgcode(): def _readgcode():
target=self.lastpos[:] target=self.lastpos[:]
target[5]=0.0 target[5]=0.0
...@@ -353,14 +353,14 @@ class gviz(wx.Panel): ...@@ -353,14 +353,14 @@ class gviz(wx.Panel):
self.arcpens[target[2]]=[] self.arcpens[target[2]]=[]
self.layers+=[target[2]] self.layers+=[target[2]]
return target return target
def _y(y): def _y(y):
return self.build_dimensions[1]-(y-self.build_dimensions[4]) return self.build_dimensions[1]-(y-self.build_dimensions[4])
def _x(x): def _x(x):
return x-self.build_dimensions[3] return x-self.build_dimensions[3]
start_pos = self.hilightpos[:] if hilight else self.lastpos[:] start_pos = self.hilightpos[:] if hilight else self.lastpos[:]
if gcode[0] in [ "g0", "g1" ]: if gcode[0] in [ "g0", "g1" ]:
target = _readgcode() target = _readgcode()
line = [ _x(start_pos[0]), _y(start_pos[1]), _x(target[0]), _y(target[1]) ] line = [ _x(start_pos[0]), _y(start_pos[1]), _x(target[0]), _y(target[1]) ]
...@@ -372,7 +372,7 @@ class gviz(wx.Panel): ...@@ -372,7 +372,7 @@ class gviz(wx.Panel):
self.hilight += [line] self.hilight += [line]
self.hilightpos = target self.hilightpos = target
self.dirty = 1 self.dirty = 1
if gcode[0] in [ "g2", "g3" ]: if gcode[0] in [ "g2", "g3" ]:
target = _readgcode() target = _readgcode()
arc = [] arc = []
...@@ -381,7 +381,7 @@ class gviz(wx.Panel): ...@@ -381,7 +381,7 @@ class gviz(wx.Panel):
arc += [ _x(start_pos[0] + target[5]), _y(start_pos[1] + target[6]) ] # center arc += [ _x(start_pos[0] + target[5]), _y(start_pos[1] + target[6]) ] # center
if gcode[0] == "g2": # clockwise, reverse endpoints if gcode[0] == "g2": # clockwise, reverse endpoints
arc[0], arc[1], arc[2], arc[3] = arc[2], arc[3], arc[0], arc[1] arc[0], arc[1], arc[2], arc[3] = arc[2], arc[3], arc[0], arc[1]
if not hilight: if not hilight:
self.arcs[ target[2] ] += [arc] self.arcs[ target[2] ] += [arc]
self.arcpens[ target[2] ] += [self.arcpen] self.arcpens[ target[2] ] += [self.arcpen]
...@@ -390,11 +390,10 @@ class gviz(wx.Panel): ...@@ -390,11 +390,10 @@ class gviz(wx.Panel):
self.hilightarcs += [arc] self.hilightarcs += [arc]
self.hilightpos = target self.hilightpos = target
self.dirty = 1 self.dirty = 1
if __name__ == '__main__': if __name__ == '__main__':
app = wx.App(False) app = wx.App(False)
#main = window(open("/home/kliment/designs/spinner/arm_export.gcode")) #main = window(open("/home/kliment/designs/spinner/arm_export.gcode"))
main = window(open("jam.gcode")) main = window(open("jam.gcode"))
main.Show() main.Show()
app.MainLoop() app.MainLoop()
...@@ -8,14 +8,14 @@ def install_locale(domain): ...@@ -8,14 +8,14 @@ def install_locale(domain):
gettext.install(domain, '/usr/share/pronterface/locale', unicode=1) gettext.install(domain, '/usr/share/pronterface/locale', unicode=1)
elif os.path.exists('/usr/local/share/pronterface/locale'): elif os.path.exists('/usr/local/share/pronterface/locale'):
gettext.install(domain, '/usr/local/share/pronterface/locale', unicode=1) gettext.install(domain, '/usr/local/share/pronterface/locale', unicode=1)
else: else:
gettext.install(domain, './locale', unicode=1) gettext.install(domain, './locale', unicode=1)
def imagefile(filename): def imagefile(filename):
for prefix in ['/usr/local/share/pronterface/images', '/usr/share/pronterface/images']: for prefix in ['/usr/local/share/pronterface/images', '/usr/share/pronterface/images']:
candidate = os.path.join(prefix, filename) candidate = os.path.join(prefix, filename)
if os.path.exists(candidate): if os.path.exists(candidate):
return candidate return candidate
local_candidate = os.path.join(os.path.dirname(__file__), "images", filename) local_candidate = os.path.join(os.path.dirname(__file__), "images", filename)
if os.path.exists(local_candidate): if os.path.exists(local_candidate):
return local_candidate return local_candidate
...@@ -24,9 +24,9 @@ def imagefile(filename): ...@@ -24,9 +24,9 @@ def imagefile(filename):
def lookup_file(filename, prefixes): def lookup_file(filename, prefixes):
for prefix in prefixes: for prefix in prefixes:
candidate = os.path.join(prefix, filename) candidate = os.path.join(prefix, filename)
if os.path.exists(candidate): if os.path.exists(candidate):
return candidate return candidate
return filename return filename
def pixmapfile(filename): def pixmapfile(filename):
......
# This file is part of the Printrun suite. # This file is part of the Printrun suite.
# #
# Printrun is free software: you can redistribute it and/or modify # Printrun is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or # the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version. # (at your option) any later version.
# #
# Printrun is distributed in the hope that it will be useful, # Printrun is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with Printrun. If not, see <http://www.gnu.org/licenses/>. # along with Printrun. If not, see <http://www.gnu.org/licenses/>.
...@@ -21,7 +21,7 @@ import tempfile ...@@ -21,7 +21,7 @@ import tempfile
import shutil import shutil
import svg.document as wxpsvgdocument import svg.document as wxpsvgdocument
import imghdr import imghdr
class dispframe(wx.Frame): class dispframe(wx.Frame):
def __init__(self, parent, title, res=(800, 600), printer=None): def __init__(self, parent, title, res=(800, 600), printer=None):
wx.Frame.__init__(self, parent=parent, title=title) wx.Frame.__init__(self, parent=parent, title=title)
...@@ -58,7 +58,7 @@ class dispframe(wx.Frame): ...@@ -58,7 +58,7 @@ class dispframe(wx.Frame):
points = [wx.Point(*map(lambda x:int(round(float(x) * self.scale)), j.strip().split())) for j in i.strip().split("M")[1].split("L")] points = [wx.Point(*map(lambda x:int(round(float(x) * self.scale)), j.strip().split())) for j in i.strip().split("M")[1].split("L")]
dc.DrawPolygon(points, self.size[0] / 2, self.size[1] / 2) dc.DrawPolygon(points, self.size[0] / 2, self.size[1] / 2)
elif self.slicer == 'Slic3r': elif self.slicer == 'Slic3r':
gc = wx.GraphicsContext_Create(dc) gc = wx.GraphicsContext_Create(dc)
gc.Translate(*self.offset) gc.Translate(*self.offset)
gc.Scale(self.scale, self.scale) gc.Scale(self.scale, self.scale)
wxpsvgdocument.SVGDocument(image).render(gc) wxpsvgdocument.SVGDocument(image).render(gc)
...@@ -69,12 +69,12 @@ class dispframe(wx.Frame): ...@@ -69,12 +69,12 @@ class dispframe(wx.Frame):
self.pic.SetBitmap(self.bitmap) self.pic.SetBitmap(self.bitmap)
self.pic.Show() self.pic.Show()
self.Refresh() self.Refresh()
except: except:
raise raise
pass pass
def showimgdelay(self, image): def showimgdelay(self, image):
self.drawlayer(image) self.drawlayer(image)
self.pic.Show() self.pic.Show()
...@@ -82,10 +82,10 @@ class dispframe(wx.Frame): ...@@ -82,10 +82,10 @@ class dispframe(wx.Frame):
self.Refresh() self.Refresh()
if self.p != None and self.p.online: if self.p != None and self.p.online:
self.p.send_now("G91") self.p.send_now("G91")
self.p.send_now("G1 Z%f F300" % (self.thickness,)) self.p.send_now("G1 Z%f F300" % (self.thickness,))
self.p.send_now("G90") self.p.send_now("G90")
def nextimg(self, event): def nextimg(self, event):
if self.index < len(self.layers): if self.index < len(self.layers):
i = self.index i = self.index
...@@ -99,8 +99,8 @@ class dispframe(wx.Frame): ...@@ -99,8 +99,8 @@ class dispframe(wx.Frame):
wx.CallAfter(self.pic.Hide) wx.CallAfter(self.pic.Hide)
wx.CallAfter(self.Refresh) wx.CallAfter(self.Refresh)
wx.CallAfter(self.ShowFullScreen, 0) wx.CallAfter(self.ShowFullScreen, 0)
wx.CallAfter(self.timer.Stop) wx.CallAfter(self.timer.Stop)
def present(self, layers, interval=0.5, pause=0.2, thickness=0.4, scale=20, size=(800, 600), offset=(0, 0)): def present(self, layers, interval=0.5, pause=0.2, thickness=0.4, scale=20, size=(800, 600), offset=(0, 0)):
wx.CallAfter(self.pic.Hide) wx.CallAfter(self.pic.Hide)
wx.CallAfter(self.Refresh) wx.CallAfter(self.Refresh)
...@@ -117,7 +117,7 @@ class dispframe(wx.Frame): ...@@ -117,7 +117,7 @@ class dispframe(wx.Frame):
self.timer.Start(1000 * interval + 1000 * pause) self.timer.Start(1000 * interval + 1000 * pause)
class setframe(wx.Frame): class setframe(wx.Frame):
def __init__(self, parent, printer=None): def __init__(self, parent, printer=None):
wx.Frame.__init__(self, parent, title="Projector setup") wx.Frame.__init__(self, parent, title="Projector setup")
self.f = dispframe(None, "", printer=printer) self.f = dispframe(None, "", printer=printer)
...@@ -147,26 +147,26 @@ class setframe(wx.Frame): ...@@ -147,26 +147,26 @@ class setframe(wx.Frame):
wx.StaticText(self.panel, -1, "Y:", pos=(160, 60)) wx.StaticText(self.panel, -1, "Y:", pos=(160, 60))
self.Y = wx.TextCtrl(self.panel, -1, "768", pos=(210, 60)) self.Y = wx.TextCtrl(self.panel, -1, "768", pos=(210, 60))
wx.StaticText(self.panel, -1, "OffsetX:", pos=(160, 90)) wx.StaticText(self.panel, -1, "OffsetX:", pos=(160, 90))
self.offsetX = wx.TextCtrl(self.panel, -1, "50", pos=(210, 90)) self.offsetX = wx.TextCtrl(self.panel, -1, "50", pos=(210, 90))
wx.StaticText(self.panel, -1, "OffsetY:", pos=(160, 120)) wx.StaticText(self.panel, -1, "OffsetY:", pos=(160, 120))
self.offsetY = wx.TextCtrl(self.panel, -1, "50", pos=(210, 120)) self.offsetY = wx.TextCtrl(self.panel, -1, "50", pos=(210, 120))
self.bload = wx.Button(self.panel, -1, "Present", pos=(0, 150)) self.bload = wx.Button(self.panel, -1, "Present", pos=(0, 150))
self.bload.Bind(wx.EVT_BUTTON, self.startdisplay) self.bload.Bind(wx.EVT_BUTTON, self.startdisplay)
wx.StaticText(self.panel, -1, "Fullscreen:", pos=(160, 150)) wx.StaticText(self.panel, -1, "Fullscreen:", pos=(160, 150))
self.fullscreen = wx.CheckBox(self.panel, -1, pos=(220, 150)) self.fullscreen = wx.CheckBox(self.panel, -1, pos=(220, 150))
self.fullscreen.SetValue(True) self.fullscreen.SetValue(True)
self.Show() self.Show()
def __del__(self): def __del__(self):
if hasattr(self, 'image_dir') and self.image_dir != '': if hasattr(self, 'image_dir') and self.image_dir != '':
shutil.rmtree(self.image_dir) shutil.rmtree(self.image_dir)
def parsesvg(self, name): def parsesvg(self, name):
et = xml.etree.ElementTree.ElementTree(file=name) et = xml.etree.ElementTree.ElementTree(file=name)
#xml.etree.ElementTree.dump(et) #xml.etree.ElementTree.dump(et)
...@@ -177,18 +177,18 @@ class setframe(wx.Frame): ...@@ -177,18 +177,18 @@ class setframe(wx.Frame):
if (slicer == 'Slic3r'): if (slicer == 'Slic3r'):
height = et.getroot().get('height') height = et.getroot().get('height')
width = et.getroot().get('width') width = et.getroot().get('width')
for i in et.findall("{http://www.w3.org/2000/svg}g"): for i in et.findall("{http://www.w3.org/2000/svg}g"):
z = float(i.get('{http://slic3r.org/namespaces/slic3r}z')) z = float(i.get('{http://slic3r.org/namespaces/slic3r}z'))
zdiff = z - zlast zdiff = z - zlast
zlast = z zlast = z
svgSnippet = xml.etree.ElementTree.Element('{http://www.w3.org/2000/svg}svg') svgSnippet = xml.etree.ElementTree.Element('{http://www.w3.org/2000/svg}svg')
svgSnippet.set('height', height + 'mm') svgSnippet.set('height', height + 'mm')
svgSnippet.set('width', width + 'mm') svgSnippet.set('width', width + 'mm')
svgSnippet.set('viewBox', '0 0 ' + height + ' ' + width) svgSnippet.set('viewBox', '0 0 ' + height + ' ' + width)
svgSnippet.append(i) svgSnippet.append(i)
ol += [svgSnippet] ol += [svgSnippet]
else : else :
for i in et.findall("{http://www.w3.org/2000/svg}g")[0].findall("{http://www.w3.org/2000/svg}g"): for i in et.findall("{http://www.w3.org/2000/svg}g")[0].findall("{http://www.w3.org/2000/svg}g"):
...@@ -198,7 +198,7 @@ class setframe(wx.Frame): ...@@ -198,7 +198,7 @@ class setframe(wx.Frame):
path = i.find('{http://www.w3.org/2000/svg}path') path = i.find('{http://www.w3.org/2000/svg}path')
ol += [(path.get("d").split("z"))[:-1]] ol += [(path.get("d").split("z"))[:-1]]
return ol, zdiff, slicer return ol, zdiff, slicer
def parse3DLPzip(self, name): def parse3DLPzip(self, name):
if not zipfile.is_zipfile(name): if not zipfile.is_zipfile(name):
raise Exception(name + " is not a zip file!") raise Exception(name + " is not a zip file!")
...@@ -212,7 +212,7 @@ class setframe(wx.Frame): ...@@ -212,7 +212,7 @@ class setframe(wx.Frame):
if os.path.isfile(path) and imghdr.what(path) in acceptedImageTypes: if os.path.isfile(path) and imghdr.what(path) in acceptedImageTypes:
ol.append(wx.Bitmap(path)) ol.append(wx.Bitmap(path))
return ol, -1, "bitmap" return ol, -1, "bitmap"
def loadfile(self, event): def loadfile(self, event):
dlg = wx.FileDialog(self, ("Open file to print"), style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST) dlg = wx.FileDialog(self, ("Open file to print"), style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST)
dlg.SetWildcard(("Slic3r or Skeinforge svg files (;*.svg;*.SVG;);3DLP Zip (;*.3dlp.zip;)")) dlg.SetWildcard(("Slic3r or Skeinforge svg files (;*.svg;*.SVG;);3DLP Zip (;*.3dlp.zip;)"))
......
...@@ -17,7 +17,7 @@ import wx ...@@ -17,7 +17,7 @@ import wx
class macroed(wx.Dialog): class macroed(wx.Dialog):
"""Really simple editor to edit macro definitions""" """Really simple editor to edit macro definitions"""
def __init__(self,macro_name,definition,callback,gcode=False): def __init__(self,macro_name,definition,callback,gcode=False):
self.indent_chars = " " self.indent_chars = " "
title=" macro %s" title=" macro %s"
...@@ -54,7 +54,7 @@ class macroed(wx.Dialog): ...@@ -54,7 +54,7 @@ class macroed(wx.Dialog):
topsizer.Fit(self) topsizer.Fit(self)
self.Show() self.Show()
self.e.SetFocus() self.e.SetFocus()
def find(self,ev): def find(self,ev):
# Ask user what to look for, find it and point at it ... (Jezmy) # Ask user what to look for, find it and point at it ... (Jezmy)
S = self.e.GetStringSelection() S = self.e.GetStringSelection()
...@@ -63,27 +63,27 @@ class macroed(wx.Dialog): ...@@ -63,27 +63,27 @@ class macroed(wx.Dialog):
FindValue = wx.GetTextFromUser('Please enter a search string:', caption="Search", default_value=S, parent=None) FindValue = wx.GetTextFromUser('Please enter a search string:', caption="Search", default_value=S, parent=None)
somecode = self.e.GetValue() somecode = self.e.GetValue()
numLines = len(somecode) numLines = len(somecode)
position = somecode.find(FindValue, self.e.GetInsertionPoint()) position = somecode.find(FindValue, self.e.GetInsertionPoint())
if position == -1 : if position == -1 :
# ShowMessage(self,-1, "Not found!") # ShowMessage(self,-1, "Not found!")
titletext = wx.TextCtrl(self.panel,-1,"Not Found!") titletext = wx.TextCtrl(self.panel,-1,"Not Found!")
else: else:
# self.title.SetValue("Position : "+str(position)) # self.title.SetValue("Position : "+str(position))
titletext = wx.TextCtrl(self.panel,-1,str(position)) titletext = wx.TextCtrl(self.panel,-1,str(position))
# ananswer = wx.MessageBox(str(numLines)+" Lines detected in file\n"+str(position), "OK") # ananswer = wx.MessageBox(str(numLines)+" Lines detected in file\n"+str(position), "OK")
self.e.SetFocus() self.e.SetFocus()
self.e.SetInsertionPoint(position) self.e.SetInsertionPoint(position)
self.e.SetSelection(position, position + len(FindValue)) self.e.SetSelection(position, position + len(FindValue))
self.e.ShowPosition(position) self.e.ShowPosition(position)
def ShowMessage(self, ev , message): def ShowMessage(self, ev , message):
dlg = wxMessageDialog(self, message, dlg = wxMessageDialog(self, message,
"Info!", wxOK | wxICON_INFORMATION) "Info!", wxOK | wxICON_INFORMATION)
dlg.ShowModal() dlg.ShowModal()
dlg.Destroy() dlg.Destroy()
def save(self,ev): def save(self,ev):
self.Destroy() self.Destroy()
if not self.gcode: if not self.gcode:
......
# This file is part of the Printrun suite. # This file is part of the Printrun suite.
# #
# Printrun is free software: you can redistribute it and/or modify # Printrun is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or # the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version. # (at your option) any later version.
# #
# Printrun is distributed in the hope that it will be useful, # Printrun is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with Printrun. If not, see <http://www.gnu.org/licenses/>. # along with Printrun. If not, see <http://www.gnu.org/licenses/>.
...@@ -38,15 +38,15 @@ I=[ ...@@ -38,15 +38,15 @@ I=[
def transpose(matrix): def transpose(matrix):
return zip(*matrix) return zip(*matrix)
#return [[v[i] for v in matrix] for i in xrange(len(matrix[0]))] #return [[v[i] for v in matrix] for i in xrange(len(matrix[0]))]
def multmatrix(vector,matrix): def multmatrix(vector,matrix):
return map(sum, transpose(map(lambda x:[x[0]*p for p in x[1]], zip(vector, transpose(matrix))))) return map(sum, transpose(map(lambda x:[x[0]*p for p in x[1]], zip(vector, transpose(matrix)))))
def applymatrix(facet,matrix=I): def applymatrix(facet,matrix=I):
#return facet #return facet
#return [map(lambda x:-1.0*x,multmatrix(facet[0]+[1],matrix)[:3]),map(lambda x:multmatrix(x+[1],matrix)[:3],facet[1])] #return [map(lambda x:-1.0*x,multmatrix(facet[0]+[1],matrix)[:3]),map(lambda x:multmatrix(x+[1],matrix)[:3],facet[1])]
return genfacet(map(lambda x:multmatrix(x+[1],matrix)[:3],facet[1])) return genfacet(map(lambda x:multmatrix(x+[1],matrix)[:3],facet[1]))
f=[[0,0,0],[[-3.022642, 0.642482, -9.510565],[-3.022642, 0.642482, -9.510565],[-3.022642, 0.642482, -9.510565]]] f=[[0,0,0],[[-3.022642, 0.642482, -9.510565],[-3.022642, 0.642482, -9.510565],[-3.022642, 0.642482, -9.510565]]]
m=[ m=[
[1,0,0,0], [1,0,0,0],
...@@ -73,7 +73,7 @@ def emitstl(filename,facets=[],objname="stltool_export",binary=1): ...@@ -73,7 +73,7 @@ def emitstl(filename,facets=[],objname="stltool_export",binary=1):
f.write(buf) f.write(buf)
f.close() f.close()
return return
f=open(filename,"w") f=open(filename,"w")
f.write("solid "+objname+"\n") f.write("solid "+objname+"\n")
...@@ -85,8 +85,8 @@ def emitstl(filename,facets=[],objname="stltool_export",binary=1): ...@@ -85,8 +85,8 @@ def emitstl(filename,facets=[],objname="stltool_export",binary=1):
f.write(" endfacet"+"\n") f.write(" endfacet"+"\n")
f.write("endsolid "+objname+"\n") f.write("endsolid "+objname+"\n")
f.close() f.close()
class stl: class stl:
def __init__(self, filename=None): def __init__(self, filename=None):
...@@ -94,7 +94,7 @@ class stl: ...@@ -94,7 +94,7 @@ class stl:
self.facets=[] self.facets=[]
self.facetsminz=[] self.facetsminz=[]
self.facetsmaxz=[] self.facetsmaxz=[]
self.name="" self.name=""
self.insolid=0 self.insolid=0
self.infacet=0 self.infacet=0
...@@ -133,7 +133,7 @@ class stl: ...@@ -133,7 +133,7 @@ class stl:
for i in self.f: for i in self.f:
if not self.parseline(i): if not self.parseline(i):
return return
def translate(self,v=[0,0,0]): def translate(self,v=[0,0,0]):
matrix=[ matrix=[
[1,0,0,v[0]], [1,0,0,v[0]],
...@@ -142,7 +142,7 @@ class stl: ...@@ -142,7 +142,7 @@ class stl:
[0,0,0,1] [0,0,0,1]
] ]
return self.transform(matrix) return self.transform(matrix)
def rotate(self,v=[0,0,0]): def rotate(self,v=[0,0,0]):
import math import math
z=v[2] z=v[2]
...@@ -167,7 +167,7 @@ class stl: ...@@ -167,7 +167,7 @@ class stl:
[0,0,0,1] [0,0,0,1]
] ]
return self.transform(matrix1).transform(matrix2).transform(matrix3) return self.transform(matrix1).transform(matrix2).transform(matrix3)
def scale(self,v=[0,0,0]): def scale(self,v=[0,0,0]):
matrix=[ matrix=[
[v[0],0,0,0], [v[0],0,0,0],
...@@ -176,8 +176,8 @@ class stl: ...@@ -176,8 +176,8 @@ class stl:
[0,0,0,1] [0,0,0,1]
] ]
return self.transform(matrix) return self.transform(matrix)
def transform(self,m=I): def transform(self,m=I):
s=stl() s=stl()
s.facets=[applymatrix(i,m) for i in self.facets] s.facets=[applymatrix(i,m) for i in self.facets]
...@@ -190,7 +190,7 @@ class stl: ...@@ -190,7 +190,7 @@ class stl:
s.facetsminz+=[(min(map(lambda x:x[2], facet[1])),facet)] s.facetsminz+=[(min(map(lambda x:x[2], facet[1])),facet)]
s.facetsmaxz+=[(max(map(lambda x:x[2], facet[1])),facet)] s.facetsmaxz+=[(max(map(lambda x:x[2], facet[1])),facet)]
return s return s
def export(self,f=sys.stdout): def export(self,f=sys.stdout):
f.write("solid "+self.name+"\n") f.write("solid "+self.name+"\n")
for i in self.facets: for i in self.facets:
...@@ -202,14 +202,14 @@ class stl: ...@@ -202,14 +202,14 @@ class stl:
f.write(" endfacet"+"\n") f.write(" endfacet"+"\n")
f.write("endsolid "+self.name+"\n") f.write("endsolid "+self.name+"\n")
f.flush() f.flush()
def parseline(self,l): def parseline(self,l):
l=l.strip() l=l.strip()
if l.startswith("solid"): if l.startswith("solid"):
self.insolid=1 self.insolid=1
self.name=l[6:] self.name=l[6:]
#print self.name #print self.name
elif l.startswith("endsolid"): elif l.startswith("endsolid"):
self.insolid=0 self.insolid=0
return 0 return 0
...@@ -244,7 +244,7 @@ if __name__=="__main__": ...@@ -244,7 +244,7 @@ if __name__=="__main__":
working.remove(j[1]) working.remove(j[1])
else: else:
break break
print i,len(working) print i,len(working)
emitstl("../../Downloads/frame-vertex-neo-foot-x4-a.stl",s.facets,"emitted_object") emitstl("../../Downloads/frame-vertex-neo-foot-x4-a.stl",s.facets,"emitted_object")
#stl("../prusamendel/stl/mendelplate.stl") #stl("../prusamendel/stl/mendelplate.stl")
#!/usr/bin/python #!/usr/bin/python
# This file is part of the Printrun suite. # This file is part of the Printrun suite.
# #
# Printrun is free software: you can redistribute it and/or modify # Printrun is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or # the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version. # (at your option) any later version.
# #
# Printrun is distributed in the hope that it will be useful, # Printrun is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with Printrun. If not, see <http://www.gnu.org/licenses/>. # along with Printrun. If not, see <http://www.gnu.org/licenses/>.
...@@ -304,14 +304,14 @@ class gcview(object): ...@@ -304,14 +304,14 @@ class gcview(object):
('v3f/static', vertices), ('v3f/static', vertices),
('n3f/static', normals))) ('n3f/static', normals)))
if lasth is not None: if lasth is not None:
self.layers[lasth] = pyglet.graphics.Batch() self.layers[lasth] = pyglet.graphics.Batch()
indices = range(len(layertemp[lasth][0])) # [[3*i,3*i+1,3*i+2] for i in xrange(len(facets))] indices = range(len(layertemp[lasth][0])) # [[3*i,3*i+1,3*i+2] for i in xrange(len(facets))]
self.vlists.append(self.layers[lasth].add_indexed(len(layertemp[lasth][0]) // 3, self.vlists.append(self.layers[lasth].add_indexed(len(layertemp[lasth][0]) // 3,
GL_TRIANGLES, GL_TRIANGLES,
None, # group, None, # group,
indices, indices,
('v3f/static', layertemp[lasth][0]), ('v3f/static', layertemp[lasth][0]),
('n3f/static', layertemp[lasth][1]))) ('n3f/static', layertemp[lasth][1])))
def genline(self, i, h, w): def genline(self, i, h, w):
S = i[0][:3] S = i[0][:3]
...@@ -356,28 +356,28 @@ class gcview(object): ...@@ -356,28 +356,28 @@ class gcview(object):
return spoints, epoints, S, E return spoints, epoints, S, E
def transform(self, line): def transform(self, line):
line = line.split(";")[0] line = line.split(";")[0]
cur = self.prev[:] cur = self.prev[:]
if len(line) > 0: if len(line) > 0:
if "G1" in line or "G0" in line or "G92" in line: if "G1" in line or "G0" in line or "G92" in line:
if("X" in line): if("X" in line):
cur[0] = float(line.split("X")[1].split(" ")[0]) cur[0] = float(line.split("X")[1].split(" ")[0])
if("Y" in line): if("Y" in line):
cur[1] = float(line.split("Y")[1].split(" ")[0]) cur[1] = float(line.split("Y")[1].split(" ")[0])
if("Z" in line): if("Z" in line):
cur[2] = float(line.split("Z")[1].split(" ")[0]) cur[2] = float(line.split("Z")[1].split(" ")[0])
if("E" in line): if("E" in line):
cur[3] = float(line.split("E")[1].split(" ")[0]) cur[3] = float(line.split("E")[1].split(" ")[0])
if self.prev == cur: if self.prev == cur:
return None return None
if self.fline or "G92" in line: if self.fline or "G92" in line:
self.prev = cur self.prev = cur
self.fline = 0 self.fline = 0
return None return None
else: else:
r = [self.prev, cur] r = [self.prev, cur]
self.prev = cur self.prev = cur
return r return r
def delete(self): def delete(self):
for i in self.vlists: for i in self.vlists:
...@@ -570,27 +570,27 @@ class TestGlPanel(GLPanel): ...@@ -570,27 +570,27 @@ class TestGlPanel(GLPanel):
self.initpos = None self.initpos = None
elif event.Dragging() and event.RightIsDown() and event.ShiftDown(): elif event.Dragging() and event.RightIsDown() and event.ShiftDown():
if self.initpos is None: if self.initpos is None:
self.initpos = event.GetPositionTuple() self.initpos = event.GetPositionTuple()
else: else:
p1 = self.initpos p1 = self.initpos
p2 = event.GetPositionTuple() p2 = event.GetPositionTuple()
sz = self.GetClientSize() sz = self.GetClientSize()
p1 = list(p1) p1 = list(p1)
p2 = list(p2) p2 = list(p2)
p1[1] *= -1 p1[1] *= -1
p2[1] *= -1 p2[1] *= -1
self.transv = map(lambda x, y, z, c: c - self.dist * (x - y) / z, list(p1) + [0], list(p2) + [0], list(sz) + [1], self.transv) self.transv = map(lambda x, y, z, c: c - self.dist * (x - y) / z, list(p1) + [0], list(p2) + [0], list(sz) + [1], self.transv)
glLoadIdentity() glLoadIdentity()
glTranslatef(self.transv[0], self.transv[1], 0) glTranslatef(self.transv[0], self.transv[1], 0)
glTranslatef(0, 0, self.transv[2]) glTranslatef(0, 0, self.transv[2])
if(self.rot): if(self.rot):
glMultMatrixd(build_rotmatrix(self.basequat)) glMultMatrixd(build_rotmatrix(self.basequat))
glGetDoublev(GL_MODELVIEW_MATRIX, self.mvmat) glGetDoublev(GL_MODELVIEW_MATRIX, self.mvmat)
self.rot = 1 self.rot = 1
self.initpos = None self.initpos = None
else: else:
#mouse is moving without a button press #mouse is moving without a button press
p = event.GetPositionTuple() p = event.GetPositionTuple()
......
...@@ -5,9 +5,9 @@ ...@@ -5,9 +5,9 @@
import wx import wx
def AddEllipticalArc(self, x, y, w, h, startAngle, endAngle, clockwise=False): def AddEllipticalArc(self, x, y, w, h, startAngle, endAngle, clockwise=False):
""" Draws an arc of an ellipse within bounding rect (x,y,w,h) """ Draws an arc of an ellipse within bounding rect (x,y,w,h)
from startArc to endArc (in radians, relative to the horizontal line of the eclipse)""" from startArc to endArc (in radians, relative to the horizontal line of the eclipse)"""
if True: if True:
import warnings import warnings
warnings.warn("elliptical arcs are not supported") warnings.warn("elliptical arcs are not supported")
...@@ -15,7 +15,7 @@ def AddEllipticalArc(self, x, y, w, h, startAngle, endAngle, clockwise=False): ...@@ -15,7 +15,7 @@ def AddEllipticalArc(self, x, y, w, h, startAngle, endAngle, clockwise=False):
h = h/2.0 h = h/2.0
self.AddArc(x+w, y+h, ((w+h)/2), startAngle, endAngle, clockwise) self.AddArc(x+w, y+h, ((w+h)/2), startAngle, endAngle, clockwise)
return return
else: else:
#implement in terms of AddArc by applying a transformation matrix #implement in terms of AddArc by applying a transformation matrix
#Sigh this can't work, still need to patch wx to allow #Sigh this can't work, still need to patch wx to allow
#either a) AddPath that's not a closed path or #either a) AddPath that's not a closed path or
...@@ -25,19 +25,18 @@ def AddEllipticalArc(self, x, y, w, h, startAngle, endAngle, clockwise=False): ...@@ -25,19 +25,18 @@ def AddEllipticalArc(self, x, y, w, h, startAngle, endAngle, clockwise=False):
#possibly be simulated by combining the current transform with option a. #possibly be simulated by combining the current transform with option a.
mtx = wx.GraphicsRenderer_GetDefaultRenderer().CreateMatrix() mtx = wx.GraphicsRenderer_GetDefaultRenderer().CreateMatrix()
path = wx.GraphicsRenderer_GetDefaultRenderer().CreatePath() path = wx.GraphicsRenderer_GetDefaultRenderer().CreatePath()
mtx.Translate(x+(w/2.0), y+(h/2.0)) mtx.Translate(x+(w/2.0), y+(h/2.0))
mtx.Scale(w/2.0, y/2.0) mtx.Scale(w/2.0, y/2.0)
path.AddArc(0, 0, 1, startAngle, endAngle, clockwise) path.AddArc(0, 0, 1, startAngle, endAngle, clockwise)
path.Transform(mtx) path.Transform(mtx)
self.AddPath(path) self.AddPath(path)
self.MoveToPoint(path.GetCurrentPoint()) self.MoveToPoint(path.GetCurrentPoint())
self.CloseSubpath() self.CloseSubpath()
if not hasattr(wx.GraphicsPath, "AddEllipticalArc"): if not hasattr(wx.GraphicsPath, "AddEllipticalArc"):
wx.GraphicsPath.AddEllipticalArc = AddEllipticalArc wx.GraphicsPath.AddEllipticalArc = AddEllipticalArc
del AddEllipticalArc del AddEllipticalArc
\ No newline at end of file
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
Parsers for specific attributes Parsers for specific attributes
""" """
import urlparse import urlparse
from pyparsing import (Literal, from pyparsing import (Literal,
Optional, oneOf, Group, StringEnd, Combine, Word, alphas, hexnums, Optional, oneOf, Group, StringEnd, Combine, Word, alphas, hexnums,
CaselessLiteral, SkipTo CaselessLiteral, SkipTo
) )
...@@ -21,14 +21,14 @@ def parsePossibleURL(t): ...@@ -21,14 +21,14 @@ def parsePossibleURL(t):
colorDeclaration = none | currentColor | colourValue colorDeclaration = none | currentColor | colourValue
urlEnd = ( urlEnd = (
Literal(")").suppress() + Literal(")").suppress() +
Optional(Group(colorDeclaration), default=()) + Optional(Group(colorDeclaration), default=()) +
StringEnd() StringEnd()
) )
url = ( url = (
CaselessLiteral("URL") CaselessLiteral("URL")
+ +
Literal("(").suppress()+ Literal("(").suppress()+
Group(SkipTo(urlEnd, include=True).setParseAction(parsePossibleURL)) Group(SkipTo(urlEnd, include=True).setParseAction(parsePossibleURL))
) )
...@@ -37,7 +37,7 @@ url = ( ...@@ -37,7 +37,7 @@ url = (
#For none and currentColor, the details tuple will be the empty tuple #For none and currentColor, the details tuple will be the empty tuple
#for CSS color declarations, it will be (type, (R,G,B)) #for CSS color declarations, it will be (type, (R,G,B))
#for URLs, it will be ("URL", ((url tuple), fallback)) #for URLs, it will be ("URL", ((url tuple), fallback))
#The url tuple will be as returned by urlparse.urlsplit, and can be #The url tuple will be as returned by urlparse.urlsplit, and can be
#an empty tuple if the parser has an error #an empty tuple if the parser has an error
#The fallback will be another (type, details) tuple as a parsed #The fallback will be another (type, details) tuple as a parsed
#colorDeclaration, but may be the empty tuple if it is not present #colorDeclaration, but may be the empty tuple if it is not present
......
...@@ -3,4 +3,4 @@ ...@@ -3,4 +3,4 @@
from pyparsing import Literal, Combine from pyparsing import Literal, Combine
from .identifier import identifier from .identifier import identifier
atkeyword = Combine(Literal("@") + identifier) atkeyword = Combine(Literal("@") + identifier)
\ No newline at end of file
...@@ -5,4 +5,3 @@ ...@@ -5,4 +5,3 @@
from pyparsing import nestedExpr from pyparsing import nestedExpr
block = nestedExpr(opener="{", closer="}") block = nestedExpr(opener="{", closer="}")
...@@ -21,31 +21,31 @@ comma = Literal(",").suppress() ...@@ -21,31 +21,31 @@ comma = Literal(",").suppress()
def clampColourByte(val): def clampColourByte(val):
val = int(val) val = int(val)
return min(max(0,val), 255) return min(max(0,val), 255)
def clampColourPerc(val): def clampColourPerc(val):
val = float(val) val = float(val)
return min(max(0,val), 100) return min(max(0,val), 100)
def parseColorPerc(token): def parseColorPerc(token):
val = token[0] val = token[0]
val = clampColourPerc(val) val = clampColourPerc(val)
#normalize to bytes #normalize to bytes
return int(255 * (val / 100.0)) return int(255 * (val / 100.0))
colorByte = Optional(sign) + integerConstant.setParseAction(lambda t: clampColourByte(t[0])) colorByte = Optional(sign) + integerConstant.setParseAction(lambda t: clampColourByte(t[0]))
colorPerc = number.setParseAction(parseColorPerc) + Literal("%").suppress() colorPerc = number.setParseAction(parseColorPerc) + Literal("%").suppress()
rgb = ( rgb = (
Literal("rgb(").setParseAction(lambda t: "RGB") + Literal("rgb(").setParseAction(lambda t: "RGB") +
( (
#integer constants, ie 255,255,255 #integer constants, ie 255,255,255
Group(colorByte + comma + colorByte + comma + colorByte) ^ Group(colorByte + comma + colorByte + comma + colorByte) ^
#percentage values, ie 100%, 50% #percentage values, ie 100%, 50%
Group(colorPerc + comma + colorPerc + comma + colorPerc) Group(colorPerc + comma + colorPerc + comma + colorPerc)
) )
+ +
Literal(")").suppress() + StringEnd() Literal(")").suppress() + StringEnd()
) )
...@@ -54,10 +54,10 @@ def parseShortHex(t): ...@@ -54,10 +54,10 @@ def parseShortHex(t):
doubleHex = Word(hexnums, exact=2).setParseAction(lambda t: int(t[0], 16)) doubleHex = Word(hexnums, exact=2).setParseAction(lambda t: int(t[0], 16))
hexLiteral = (Literal("#").setParseAction(lambda t: "RGB") + hexLiteral = (Literal("#").setParseAction(lambda t: "RGB") +
( (
Group(doubleHex + doubleHex + doubleHex) | Group(doubleHex + doubleHex + doubleHex) |
Word(hexnums, exact=3).setParseAction(parseShortHex) Word(hexnums, exact=3).setParseAction(parseShortHex)
) + StringEnd() ) + StringEnd()
) )
...@@ -66,7 +66,7 @@ def parseNamedColour(t): ...@@ -66,7 +66,7 @@ def parseNamedColour(t):
return ["RGB", NamedColours[t[0].lower()]] return ["RGB", NamedColours[t[0].lower()]]
except KeyError: except KeyError:
return ["RGB", (0,0,0)] return ["RGB", (0,0,0)]
namedColour = Word(alphas).setParseAction(parseNamedColour) namedColour = Word(alphas).setParseAction(parseNamedColour)
...@@ -246,7 +246,7 @@ NamedColours = { ...@@ -246,7 +246,7 @@ NamedColours = {
def fillCSS2SystemColours(): def fillCSS2SystemColours():
#The system colours require a wxApp to be present to retrieve, #The system colours require a wxApp to be present to retrieve,
#so if you wnat support for them you'll need #so if you wnat support for them you'll need
#to call this function after your wxApp instance starts #to call this function after your wxApp instance starts
systemColors = { systemColors = {
"ActiveBorder": wx.SYS_COLOUR_ACTIVEBORDER, "ActiveBorder": wx.SYS_COLOUR_ACTIVEBORDER,
...@@ -280,4 +280,4 @@ def fillCSS2SystemColours(): ...@@ -280,4 +280,4 @@ def fillCSS2SystemColours():
NamedColours.update( NamedColours.update(
#strip the alpha from the system colors. Is this really what we want to do? #strip the alpha from the system colors. Is this really what we want to do?
(k.lower(), wx.SystemSettings.GetColour(v)[:3]) for (k,v) in systemColors.iteritems() (k.lower(), wx.SystemSettings.GetColour(v)[:3]) for (k,v) in systemColors.iteritems()
) )
\ No newline at end of file
...@@ -10,7 +10,7 @@ class White(White): ...@@ -10,7 +10,7 @@ class White(White):
super(White, self).__init__(ws, min, max, exact) super(White, self).__init__(ws, min, max, exact)
escaped = ( escaped = (
Literal("\\").suppress() + Literal("\\").suppress() +
#chr(20)-chr(126) + chr(128)-unichr(sys.maxunicode) #chr(20)-chr(126) + chr(128)-unichr(sys.maxunicode)
Regex(u"[\u0020-\u007e\u0080-\uffff]", re.IGNORECASE) Regex(u"[\u0020-\u007e\u0080-\uffff]", re.IGNORECASE)
) )
...@@ -18,7 +18,7 @@ escaped = ( ...@@ -18,7 +18,7 @@ escaped = (
def convertToUnicode(t): def convertToUnicode(t):
return unichr(int(t[0], 16)) return unichr(int(t[0], 16))
hex_unicode = ( hex_unicode = (
Literal("\\").suppress() + Literal("\\").suppress() +
Regex("[0-9a-f]{1,6}", re.IGNORECASE) + Regex("[0-9a-f]{1,6}", re.IGNORECASE) +
Optional(White(exact=1)).suppress() Optional(White(exact=1)).suppress()
).setParseAction(convertToUnicode) ).setParseAction(convertToUnicode)
...@@ -29,9 +29,9 @@ escape = hex_unicode | escaped ...@@ -29,9 +29,9 @@ escape = hex_unicode | escaped
#any unicode literal outside the 0-127 ascii range #any unicode literal outside the 0-127 ascii range
nonascii = Regex(u"[^\u0000-\u007f]") nonascii = Regex(u"[^\u0000-\u007f]")
#single character for starting an identifier. #single character for starting an identifier.
nmstart = Regex(u"[A-Z]", re.IGNORECASE) | nonascii | escape nmstart = Regex(u"[A-Z]", re.IGNORECASE) | nonascii | escape
nmchar = Regex(u"[0-9A-Z-]", re.IGNORECASE) | nonascii | escape nmchar = Regex(u"[0-9A-Z-]", re.IGNORECASE) | nonascii | escape
identifier = Combine(nmstart + ZeroOrMore(nmchar)) identifier = Combine(nmstart + ZeroOrMore(nmchar))
\ No newline at end of file
...@@ -5,4 +5,4 @@ def inlineStyle(styleString): ...@@ -5,4 +5,4 @@ def inlineStyle(styleString):
return {} return {}
styles = styleString.split(";") styles = styleString.split(";")
rv = dict(style.split(":") for style in styles if len(style) != 0) rv = dict(style.split(":") for style in styles if len(style) != 0)
return rv return rv
\ No newline at end of file
...@@ -48,4 +48,4 @@ transformList = delimitedList(Group(transform), delim=maybeComma) ...@@ -48,4 +48,4 @@ transformList = delimitedList(Group(transform), delim=maybeComma)
if __name__ == '__main__': if __name__ == '__main__':
from tests.test_css import * from tests.test_css import *
unittest.main() unittest.main()
\ No newline at end of file
...@@ -43,4 +43,4 @@ length = lengthValue + Optional(lengthUnit, default=None) + StringEnd() ...@@ -43,4 +43,4 @@ length = lengthValue + Optional(lengthUnit, default=None) + StringEnd()
length.leaveWhitespace() length.leaveWhitespace()
#set the parse action aftward so it doesn't "infect" the parsers that build on it #set the parse action aftward so it doesn't "infect" the parsers that build on it
number.setParseAction(asFloat) number.setParseAction(asFloat)
\ No newline at end of file
...@@ -15,7 +15,7 @@ from svg.css import values ...@@ -15,7 +15,7 @@ from svg.css import values
from attributes import paintValue from attributes import paintValue
document = """<?xml version="1.0" standalone="no"?> document = """<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="4cm" height="4cm" viewBox="0 0 400 400" <svg width="4cm" height="4cm" viewBox="0 0 400 400"
xmlns="http://www.w3.org/2000/svg" version="1.1"> xmlns="http://www.w3.org/2000/svg" version="1.1">
...@@ -38,7 +38,7 @@ def attrAsFloat(node, attr, defaultValue="0"): ...@@ -38,7 +38,7 @@ def attrAsFloat(node, attr, defaultValue="0"):
return float(val) return float(val)
except ValueError: except ValueError:
return valueToPixels(val) return valueToPixels(val)
def valueToPixels(val, defaultUnits="px"): def valueToPixels(val, defaultUnits="px"):
#TODO manage default units #TODO manage default units
from pyparsing import ParseException from pyparsing import ParseException
...@@ -67,7 +67,7 @@ def pathHandler(func): ...@@ -67,7 +67,7 @@ def pathHandler(func):
ops = self.generatePathOps(path) ops = self.generatePathOps(path)
return path, ops return path, ops
return inner return inner
class SVGDocument(object): class SVGDocument(object):
lastControl = None lastControl = None
...@@ -102,12 +102,12 @@ class SVGDocument(object): ...@@ -102,12 +102,12 @@ class SVGDocument(object):
def state(self): def state(self):
""" Retrieve the current state, without popping""" """ Retrieve the current state, without popping"""
return self.stateStack[-1] return self.stateStack[-1]
def processElement(self, element): def processElement(self, element):
""" Process one element of the XML tree. """ Process one element of the XML tree.
Returns the path representing the node, Returns the path representing the node,
and an operation list for drawing the node. and an operation list for drawing the node.
Parent nodes should return a path (for hittesting), but Parent nodes should return a path (for hittesting), but
no draw operations no draw operations
""" """
...@@ -126,7 +126,7 @@ class SVGDocument(object): ...@@ -126,7 +126,7 @@ class SVGDocument(object):
""" Returns an oplist for transformations. """ Returns an oplist for transformations.
This applies to a node, not the current state because This applies to a node, not the current state because
the transform stack is saved in the wxGraphicsContext. the transform stack is saved in the wxGraphicsContext.
This oplist does *not* include the push/pop state commands This oplist does *not* include the push/pop state commands
""" """
ops = [] ops = []
...@@ -188,8 +188,8 @@ class SVGDocument(object): ...@@ -188,8 +188,8 @@ class SVGDocument(object):
(wx.GraphicsContext.ConcatTransform, (matrix,)) (wx.GraphicsContext.ConcatTransform, (matrix,))
) )
return ops return ops
def addGroupToDocument(self, node): def addGroupToDocument(self, node):
""" For parent elements: push on a state, """ For parent elements: push on a state,
then process all child elements then process all child elements
...@@ -197,7 +197,7 @@ class SVGDocument(object): ...@@ -197,7 +197,7 @@ class SVGDocument(object):
ops = [ ops = [
(wx.GraphicsContext.PushState, ()) (wx.GraphicsContext.PushState, ())
] ]
path = makePath() path = makePath()
ops.extend(self.createTransformOpsFromNode(node)) ops.extend(self.createTransformOpsFromNode(node))
for child in node.getchildren(): for child in node.getchildren():
...@@ -210,7 +210,7 @@ class SVGDocument(object): ...@@ -210,7 +210,7 @@ class SVGDocument(object):
(wx.GraphicsContext.PopState, ()) (wx.GraphicsContext.PopState, ())
) )
return path, ops return path, ops
def getFontFromState(self): def getFontFromState(self):
font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT) font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
family = self.state.get("font-family") family = self.state.get("font-family")
...@@ -227,10 +227,10 @@ class SVGDocument(object): ...@@ -227,10 +227,10 @@ class SVGDocument(object):
else: else:
font.SetPointSize(int(val)) font.SetPointSize(int(val))
return font return font
def addTextToDocument(self, node): def addTextToDocument(self, node):
x, y = [attrAsFloat(node, attr) for attr in ('x', 'y')] x, y = [attrAsFloat(node, attr) for attr in ('x', 'y')]
def DoDrawText(context, text, x, y, brush=wx.NullGraphicsBrush): def DoDrawText(context, text, x, y, brush=wx.NullGraphicsBrush):
#SVG spec appears to originate text from the bottom #SVG spec appears to originate text from the bottom
#rather than the top as with our API. This function #rather than the top as with our API. This function
...@@ -252,7 +252,7 @@ class SVGDocument(object): ...@@ -252,7 +252,7 @@ class SVGDocument(object):
(DoDrawText, (text, x, y)) (DoDrawText, (text, x, y))
] ]
return None, ops return None, ops
@pathHandler @pathHandler
def addRectToDocument(self, node, path): def addRectToDocument(self, node, path):
x, y, w, h = (attrAsFloat(node, attr) for attr in ['x', 'y', 'width', 'height']) x, y, w, h = (attrAsFloat(node, attr) for attr in ['x', 'y', 'width', 'height'])
...@@ -271,7 +271,7 @@ class SVGDocument(object): ...@@ -271,7 +271,7 @@ class SVGDocument(object):
#value clamping as per spec section 9.2 #value clamping as per spec section 9.2
rx = min(rx, w/2) rx = min(rx, w/2)
ry = min(ry, h/2) ry = min(ry, h/2)
#origin #origin
path.MoveToPoint(x+rx, y) path.MoveToPoint(x+rx, y)
path.AddLineToPoint(x+w-rx, y) path.AddLineToPoint(x+w-rx, y)
...@@ -315,12 +315,12 @@ class SVGDocument(object): ...@@ -315,12 +315,12 @@ class SVGDocument(object):
path.AddRectangle( path.AddRectangle(
x, y, w, h x, y, w, h
) )
@pathHandler @pathHandler
def addCircleToDocument(self, node, path): def addCircleToDocument(self, node, path):
cx, cy, r = [attrAsFloat(node, attr) for attr in ('cx', 'cy', 'r')] cx, cy, r = [attrAsFloat(node, attr) for attr in ('cx', 'cy', 'r')]
path.AddCircle(cx, cy, r) path.AddCircle(cx, cy, r)
@pathHandler @pathHandler
def addEllipseToDocument(self, node, path): def addEllipseToDocument(self, node, path):
cx, cy, rx, ry = [float(node.get(attr, 0)) for attr in ('cx', 'cy', 'rx', 'ry')] cx, cy, rx, ry = [float(node.get(attr, 0)) for attr in ('cx', 'cy', 'rx', 'ry')]
...@@ -332,29 +332,29 @@ class SVGDocument(object): ...@@ -332,29 +332,29 @@ class SVGDocument(object):
x = cx - rx x = cx - rx
y = cy - ry y = cy - ry
path.AddEllipse(x, y, rx*2, ry*2) path.AddEllipse(x, y, rx*2, ry*2)
@pathHandler @pathHandler
def addLineToDocument(self, node, path): def addLineToDocument(self, node, path):
x1, y1, x2, y2 = [attrAsFloat(node, attr) for attr in ('x1', 'y1', 'x2', 'y2')] x1, y1, x2, y2 = [attrAsFloat(node, attr) for attr in ('x1', 'y1', 'x2', 'y2')]
path.MoveToPoint(x1, y1) path.MoveToPoint(x1, y1)
path.AddLineToPoint(x2, y2) path.AddLineToPoint(x2, y2)
@pathHandler @pathHandler
def addPolyLineToDocument(self, node, path): def addPolyLineToDocument(self, node, path):
#translate to pathdata and render that #translate to pathdata and render that
data = "M " + node.get("points") data = "M " + node.get("points")
self.addPathDataToPath(data, path) self.addPathDataToPath(data, path)
@pathHandler @pathHandler
def addPolygonToDocument(self, node, path): def addPolygonToDocument(self, node, path):
#translate to pathdata and render that #translate to pathdata and render that
data = "M " + node.get("points") + " Z" data = "M " + node.get("points") + " Z"
self.addPathDataToPath(data, path) self.addPathDataToPath(data, path)
@pathHandler @pathHandler
def addPathDataToDocument(self, node, path): def addPathDataToDocument(self, node, path):
self.addPathDataToPath(node.get('d', ''), path) self.addPathDataToPath(node.get('d', ''), path)
def addPathDataToPath(self, data, path): def addPathDataToPath(self, data, path):
self.lastControl = None self.lastControl = None
self.lastControlQ = None self.lastControlQ = None
...@@ -364,7 +364,7 @@ class SVGDocument(object): ...@@ -364,7 +364,7 @@ class SVGDocument(object):
form of (command, [list of arguments]). form of (command, [list of arguments]).
We translate that to [(command, args[0]), (command, args[1])] We translate that to [(command, args[0]), (command, args[1])]
via a generator. via a generator.
M is special cased because its subsequent arguments M is special cased because its subsequent arguments
become linetos. become linetos.
""" """
...@@ -388,10 +388,10 @@ class SVGDocument(object): ...@@ -388,10 +388,10 @@ class SVGDocument(object):
#print "parsed in", time.time()-t #print "parsed in", time.time()-t
for stroke in normalizeStrokes(parsed): for stroke in normalizeStrokes(parsed):
self.addStrokeToPath(path, stroke) self.addStrokeToPath(path, stroke)
def generatePathOps(self, path): def generatePathOps(self, path):
""" Look at the current state and generate the """ Look at the current state and generate the
draw operations (fill, stroke, neither) for the path""" draw operations (fill, stroke, neither) for the path"""
ops = [] ops = []
brush = self.getBrushFromState(path) brush = self.getBrushFromState(path)
...@@ -414,7 +414,7 @@ class SVGDocument(object): ...@@ -414,7 +414,7 @@ class SVGDocument(object):
(wx.GraphicsContext.StrokePath, (path,)) (wx.GraphicsContext.StrokePath, (path,))
) )
return ops return ops
def getPenFromState(self): def getPenFromState(self):
pencolour = self.state.get('stroke', 'none') pencolour = self.state.get('stroke', 'none')
if pencolour == 'currentColor': if pencolour == 'currentColor':
...@@ -494,7 +494,7 @@ class SVGDocument(object): ...@@ -494,7 +494,7 @@ class SVGDocument(object):
opacity = float(opacity) opacity = float(opacity)
opacity = min(max(opacity, 0.0), 1.0) opacity = min(max(opacity, 0.0), 1.0)
a = 255 * opacity a = 255 * opacity
#using try/except block instead of #using try/except block instead of
#just setdefault because the wxBrush and wxColour would #just setdefault because the wxBrush and wxColour would
#be created every time anyway in order to pass them, #be created every time anyway in order to pass them,
#defeating the purpose of the cache #defeating the purpose of the cache
...@@ -502,14 +502,14 @@ class SVGDocument(object): ...@@ -502,14 +502,14 @@ class SVGDocument(object):
return SVGDocument.brushCache[(r,g,b,a)] return SVGDocument.brushCache[(r,g,b,a)]
except KeyError: except KeyError:
return SVGDocument.brushCache.setdefault((r,g,b,a), wx.Brush(wx.Colour(r,g,b,a))) return SVGDocument.brushCache.setdefault((r,g,b,a), wx.Brush(wx.Colour(r,g,b,a)))
def resolveURL(self, urlData): def resolveURL(self, urlData):
""" """
Resolve a URL and return an elementTree Element from it. Resolve a URL and return an elementTree Element from it.
Return None if unresolvable Return None if unresolvable
""" """
scheme, netloc, path, query, fragment = urlData scheme, netloc, path, query, fragment = urlData
if scheme == netloc == path == '': if scheme == netloc == path == '':
...@@ -524,15 +524,15 @@ class SVGDocument(object): ...@@ -524,15 +524,15 @@ class SVGDocument(object):
return None return None
else: else:
return self.resolveRemoteURL(urlData) return self.resolveRemoteURL(urlData)
def resolveRemoteURL(self, url): def resolveRemoteURL(self, url):
return None return None
def addStrokeToPath(self, path, stroke): def addStrokeToPath(self, path, stroke):
""" Given a stroke from a path command """ Given a stroke from a path command
(in the form (command, arguments)) create the path (in the form (command, arguments)) create the path
commands that represent it. commands that represent it.
TODO: break out into (yet another) class/module, TODO: break out into (yet another) class/module,
especially so we can get O(1) dispatch on type? especially so we can get O(1) dispatch on type?
""" """
...@@ -564,8 +564,8 @@ class SVGDocument(object): ...@@ -564,8 +564,8 @@ class SVGDocument(object):
) )
self.lastControl = control2 self.lastControl = control2
path.AddCurveToPoint( path.AddCurveToPoint(
control1, control1,
control2, control2,
endpoint endpoint
) )
#~ cp = path.GetCurrentPoint() #~ cp = path.GetCurrentPoint()
...@@ -574,7 +574,7 @@ class SVGDocument(object): ...@@ -574,7 +574,7 @@ class SVGDocument(object):
#~ path.AddCircle(x,y, 7) #~ path.AddCircle(x,y, 7)
#~ path.MoveToPoint(cp) #~ path.MoveToPoint(cp)
#~ print "C", control1, control2, endpoint #~ print "C", control1, control2, endpoint
elif type == 'S': elif type == 'S':
#control2, endpoint = arg #control2, endpoint = arg
control2, endpoint = map( control2, endpoint = map(
...@@ -584,11 +584,11 @@ class SVGDocument(object): ...@@ -584,11 +584,11 @@ class SVGDocument(object):
control1 = reflectPoint(self.lastControl, path.GetCurrentPoint()) control1 = reflectPoint(self.lastControl, path.GetCurrentPoint())
else: else:
control1 = path.GetCurrentPoint() control1 = path.GetCurrentPoint()
#~ print "S", self.lastControl,":",control1, control2, endpoint #~ print "S", self.lastControl,":",control1, control2, endpoint
self.lastControl = control2 self.lastControl = control2
path.AddCurveToPoint( path.AddCurveToPoint(
control1, control1,
control2, control2,
endpoint endpoint
) )
elif type == "Q": elif type == "Q":
...@@ -603,50 +603,50 @@ class SVGDocument(object): ...@@ -603,50 +603,50 @@ class SVGDocument(object):
cx, cy = path.GetCurrentPoint() cx, cy = path.GetCurrentPoint()
self.lastControlQ = (cx, cy) self.lastControlQ = (cx, cy)
path.AddQuadCurveToPoint(cx, cy, x, y) path.AddQuadCurveToPoint(cx, cy, x, y)
elif type == "V": elif type == "V":
_, y = normalizePoint((0, arg)) _, y = normalizePoint((0, arg))
x, _ = path.GetCurrentPoint() x, _ = path.GetCurrentPoint()
path.AddLineToPoint(x,y) path.AddLineToPoint(x,y)
elif type == "H": elif type == "H":
x, _ = normalizePoint((arg, 0)) x, _ = normalizePoint((arg, 0))
_, y = path.GetCurrentPoint() _, y = path.GetCurrentPoint()
path.AddLineToPoint(x,y) path.AddLineToPoint(x,y)
elif type == "A": elif type == "A":
#wxGC currently only supports circular arcs, #wxGC currently only supports circular arcs,
#not eliptical ones #not eliptical ones
( (
(rx, ry), #radii of ellipse (rx, ry), #radii of ellipse
angle, #angle of rotation on the ellipse in degrees angle, #angle of rotation on the ellipse in degrees
(fa, fs), #arc and stroke angle flags (fa, fs), #arc and stroke angle flags
(x, y) #endpoint on the arc (x, y) #endpoint on the arc
) = arg ) = arg
x, y = normalizePoint((x,y)) x, y = normalizePoint((x,y))
cx, cy = path.GetCurrentPoint() cx, cy = path.GetCurrentPoint()
if (cx, cy) == (x, y): if (cx, cy) == (x, y):
return #noop return #noop
if (rx == 0 or ry == 0): if (rx == 0 or ry == 0):
#no radius is effectively a line #no radius is effectively a line
path.AddLineToPoint(x,y) path.AddLineToPoint(x,y)
return return
#find the center point for the ellipse #find the center point for the ellipse
#translation via the angle #translation via the angle
angle = angle % 360 angle = angle % 360
angle = math.radians(angle) angle = math.radians(angle)
#translated endpoint #translated endpoint
xPrime = math.cos(angle) * ((cx-x)/2) xPrime = math.cos(angle) * ((cx-x)/2)
xPrime += math.sin(angle) * ((cx-x)/2) xPrime += math.sin(angle) * ((cx-x)/2)
yPrime = -(math.sin(angle)) * ((cy-y)/2) yPrime = -(math.sin(angle)) * ((cy-y)/2)
yPrime += (math.cos(angle)) * ((cy-y)/2) yPrime += (math.cos(angle)) * ((cy-y)/2)
temp = ((rx**2) * (ry**2)) - ((rx**2) * (yPrime**2)) - ((ry**2) * (xPrime**2)) temp = ((rx**2) * (ry**2)) - ((rx**2) * (yPrime**2)) - ((ry**2) * (xPrime**2))
temp /= ((rx**2) * (yPrime**2)) + ((ry**2)*(xPrime**2)) temp /= ((rx**2) * (yPrime**2)) + ((ry**2)*(xPrime**2))
temp = abs(temp) temp = abs(temp)
...@@ -659,7 +659,7 @@ class SVGDocument(object): ...@@ -659,7 +659,7 @@ class SVGDocument(object):
cyPrime = temp * -((ry * xPrime) / rx) cyPrime = temp * -((ry * xPrime) / rx)
if fa == fs: if fa == fs:
cxPrime, cyPrime = -cxPrime, -cyPrime cxPrime, cyPrime = -cxPrime, -cyPrime
#reflect backwards now for the origin #reflect backwards now for the origin
cnx = math.cos(angle) * cxPrime cnx = math.cos(angle) * cxPrime
cnx += math.sin(angle) * cxPrime cnx += math.sin(angle) * cxPrime
...@@ -667,18 +667,18 @@ class SVGDocument(object): ...@@ -667,18 +667,18 @@ class SVGDocument(object):
cny += (math.cos(angle)) * cyPrime cny += (math.cos(angle)) * cyPrime
cnx += ((cx+x)/2.0) cnx += ((cx+x)/2.0)
cny += ((cy+y)/2.0) cny += ((cy+y)/2.0)
#calculate the angle between the two endpoints #calculate the angle between the two endpoints
lastArc = wx.Point2D(x-cnx, y-cny).GetVectorAngle() lastArc = wx.Point2D(x-cnx, y-cny).GetVectorAngle()
firstArc = wx.Point2D(cx-cnx, cy-cny).GetVectorAngle() firstArc = wx.Point2D(cx-cnx, cy-cny).GetVectorAngle()
lastArc = math.radians(lastArc) lastArc = math.radians(lastArc)
firstArc = math.radians(firstArc) firstArc = math.radians(firstArc)
#aargh buggines. #aargh buggines.
#AddArc draws a straight line between #AddArc draws a straight line between
#the endpoints of the arc. #the endpoints of the arc.
#putting it in a subpath makes the strokes come out #putting it in a subpath makes the strokes come out
#correctly, but it still only fills the slice #correctly, but it still only fills the slice
#taking out the MoveToPoint fills correctly. #taking out the MoveToPoint fills correctly.
path.AddEllipse(cnx-rx, cny-ry, rx*2, ry*2) path.AddEllipse(cnx-rx, cny-ry, rx*2, ry*2)
...@@ -687,7 +687,7 @@ class SVGDocument(object): ...@@ -687,7 +687,7 @@ class SVGDocument(object):
#~ npath.AddEllipticalArc(cnx-rx, cny-ry, rx*2, ry*2, firstArc, lastArc, False) #~ npath.AddEllipticalArc(cnx-rx, cny-ry, rx*2, ry*2, firstArc, lastArc, False)
#~ npath.MoveToPoint(x,y) #~ npath.MoveToPoint(x,y)
#~ path.AddPath(npath) #~ path.AddPath(npath)
elif type == 'Z': elif type == 'Z':
#~ Bugginess: #~ Bugginess:
#~ CloseSubpath() doesn't change the #~ CloseSubpath() doesn't change the
...@@ -699,17 +699,17 @@ class SVGDocument(object): ...@@ -699,17 +699,17 @@ class SVGDocument(object):
#~ results #~ results
#~ Manually closing the path *and* calling CloseSubpath() appears #~ Manually closing the path *and* calling CloseSubpath() appears
#~ to give correct results on win32 #~ to give correct results on win32
pt = self.firstPoints.pop() pt = self.firstPoints.pop()
path.AddLineToPoint(pt) path.AddLineToPoint(pt)
path.CloseSubpath() path.CloseSubpath()
def render(self, context): def render(self, context):
if not hasattr(self, "ops"): if not hasattr(self, "ops"):
return return
for op, args in self.ops: for op, args in self.ops:
op(context, *args) op(context, *args)
if __name__ == '__main__': if __name__ == '__main__':
from tests.test_document import * from tests.test_document import *
unittest.main() unittest.main()
""" """
SVG path data parser SVG path data parser
Usage: Usage:
steps = svg.parseString(pathdata) steps = svg.parseString(pathdata)
for command, arguments in steps: for command, arguments in steps:
pass pass
""" """
from pyparsing import (ParserElement, Literal, Word, CaselessLiteral, from pyparsing import (ParserElement, Literal, Word, CaselessLiteral,
Optional, Combine, Forward, ZeroOrMore, nums, oneOf, Group, ParseException, OneOrMore) Optional, Combine, Forward, ZeroOrMore, nums, oneOf, Group, ParseException, OneOrMore)
#ParserElement.enablePackrat() #ParserElement.enablePackrat()
def Command(char): def Command(char):
""" Case insensitive but case preserving""" """ Case insensitive but case preserving"""
return CaselessPreservingLiteral(char) return CaselessPreservingLiteral(char)
def Arguments(token): def Arguments(token):
return Group(token) return Group(token)
class CaselessPreservingLiteral(CaselessLiteral): class CaselessPreservingLiteral(CaselessLiteral):
""" Like CaselessLiteral, but returns the match as found """ Like CaselessLiteral, but returns the match as found
instead of as defined. instead of as defined.
...@@ -40,8 +40,8 @@ class CaselessPreservingLiteral(CaselessLiteral): ...@@ -40,8 +40,8 @@ class CaselessPreservingLiteral(CaselessLiteral):
exc = self.myException exc = self.myException
exc.loc = loc exc.loc = loc
exc.pstr = instring exc.pstr = instring
raise exc raise exc
def Sequence(token): def Sequence(token):
""" A sequence of the token""" """ A sequence of the token"""
return OneOrMore(token+maybeComma) return OneOrMore(token+maybeComma)
...@@ -58,13 +58,13 @@ def convertToFloat(s, loc, toks): ...@@ -58,13 +58,13 @@ def convertToFloat(s, loc, toks):
exponent = CaselessLiteral("e")+Optional(sign)+Word(nums) exponent = CaselessLiteral("e")+Optional(sign)+Word(nums)
#note that almost all these fields are optional, #note that almost all these fields are optional,
#and this can match almost anything. We rely on Pythons built-in #and this can match almost anything. We rely on Pythons built-in
#float() function to clear out invalid values - loosely matching like this #float() function to clear out invalid values - loosely matching like this
#speeds up parsing quite a lot #speeds up parsing quite a lot
floatingPointConstant = Combine( floatingPointConstant = Combine(
Optional(sign) + Optional(sign) +
Optional(Word(nums)) + Optional(Word(nums)) +
Optional(Literal(".") + Optional(Word(nums)))+ Optional(Literal(".") + Optional(Word(nums)))+
Optional(exponent) Optional(exponent)
) )
...@@ -75,7 +75,7 @@ number = floatingPointConstant ...@@ -75,7 +75,7 @@ number = floatingPointConstant
#same as FP constant but don't allow a - sign #same as FP constant but don't allow a - sign
nonnegativeNumber = Combine( nonnegativeNumber = Combine(
Optional(Word(nums)) + Optional(Word(nums)) +
Optional(Literal(".") + Optional(Word(nums)))+ Optional(Literal(".") + Optional(Word(nums)))+
Optional(exponent) Optional(exponent)
) )
...@@ -120,7 +120,7 @@ ellipticalArcArgument = Group( ...@@ -120,7 +120,7 @@ ellipticalArcArgument = Group(
coordinatePair #(x,y) coordinatePair #(x,y)
) )
ellipticalArc = Group(Command("A") + Arguments(Sequence(ellipticalArcArgument))) ellipticalArc = Group(Command("A") + Arguments(Sequence(ellipticalArcArgument)))
smoothQuadraticBezierCurveto = Group(Command("T") + Arguments(coordinatePairSequence)) smoothQuadraticBezierCurveto = Group(Command("T") + Arguments(coordinatePairSequence))
...@@ -155,39 +155,37 @@ def profile(): ...@@ -155,39 +155,37 @@ def profile():
p.disable() p.disable()
p.print_stats() p.print_stats()
bpath = """M204.33 139.83 C196.33 133.33 206.68 132.82 206.58 132.58 C192.33 97.08 169.35 bpath = """M204.33 139.83 C196.33 133.33 206.68 132.82 206.58 132.58 C192.33 97.08 169.35
81.41 167.58 80.58 C162.12 78.02 159.48 78.26 160.45 76.97 C161.41 75.68 167.72 79.72 168.58 81.41 167.58 80.58 C162.12 78.02 159.48 78.26 160.45 76.97 C161.41 75.68 167.72 79.72 168.58
80.33 C193.83 98.33 207.58 132.33 207.58 132.33 C207.58 132.33 209.33 133.33 209.58 132.58 80.33 C193.83 98.33 207.58 132.33 207.58 132.33 C207.58 132.33 209.33 133.33 209.58 132.58
C219.58 103.08 239.58 87.58 246.33 81.33 C253.08 75.08 256.63 74.47 247.33 81.58 C218.58 103.58 C219.58 103.08 239.58 87.58 246.33 81.33 C253.08 75.08 256.63 74.47 247.33 81.58 C218.58 103.58
210.34 132.23 210.83 132.33 C222.33 134.83 211.33 140.33 211.83 139.83 C214.85 136.81 214.83 145.83 214.83 210.34 132.23 210.83 132.33 C222.33 134.83 211.33 140.33 211.83 139.83 C214.85 136.81 214.83 145.83 214.83
145.83 C214.83 145.83 231.83 110.83 298.33 66.33 C302.43 63.59 445.83 -14.67 395.83 80.83 C393.24 85.79 375.83 145.83 C214.83 145.83 231.83 110.83 298.33 66.33 C302.43 63.59 445.83 -14.67 395.83 80.83 C393.24 85.79 375.83
105.83 375.83 105.83 C375.83 105.83 377.33 114.33 371.33 121.33 C370.3 122.53 367.83 134.33 361.83 140.83 C360.14 142.67 105.83 375.83 105.83 C375.83 105.83 377.33 114.33 371.33 121.33 C370.3 122.53 367.83 134.33 361.83 140.83 C360.14 142.67
361.81 139.25 361.83 140.83 C362.33 170.83 337.76 170.17 339.33 170.33 C348.83 171.33 350.19 183.66 350.33 183.83 C355.83 361.81 139.25 361.83 140.83 C362.33 170.83 337.76 170.17 339.33 170.33 C348.83 171.33 350.19 183.66 350.33 183.83 C355.83
190.33 353.83 191.83 355.83 194.83 C366.63 211.02 355.24 210.05 356.83 212.83 C360.83 219.83 355.99 222.72 357.33 224.83 190.33 353.83 191.83 355.83 194.83 C366.63 211.02 355.24 210.05 356.83 212.83 C360.83 219.83 355.99 222.72 357.33 224.83
C360.83 230.33 354.75 233.84 354.83 235.33 C355.33 243.83 349.67 240.73 349.83 244.33 C350.33 255.33 346.33 250.83 343.83 254.83 C360.83 230.33 354.75 233.84 354.83 235.33 C355.33 243.83 349.67 240.73 349.83 244.33 C350.33 255.33 346.33 250.83 343.83 254.83
C336.33 266.83 333.46 262.38 332.83 263.83 C329.83 270.83 325.81 269.15 324.33 270.83 C320.83 274.83 317.33 274.83 315.83 276.33 C336.33 266.83 333.46 262.38 332.83 263.83 C329.83 270.83 325.81 269.15 324.33 270.83 C320.83 274.83 317.33 274.83 315.83 276.33
C308.83 283.33 304.86 278.39 303.83 278.83 C287.83 285.83 280.33 280.17 277.83 280.33 C270.33 280.83 271.48 279.67 269.33 277.83 C308.83 283.33 304.86 278.39 303.83 278.83 C287.83 285.83 280.33 280.17 277.83 280.33 C270.33 280.83 271.48 279.67 269.33 277.83
C237.83 250.83 219.33 211.83 215.83 206.83 C214.4 204.79 211.35 193.12 212.33 195.83 C214.33 201.33 213.33 250.33 207.83 250.33 C237.83 250.83 219.33 211.83 215.83 206.83 C214.4 204.79 211.35 193.12 212.33 195.83 C214.33 201.33 213.33 250.33 207.83 250.33
C202.33 250.33 201.83 204.33 205.33 195.83 C206.43 193.16 204.4 203.72 201.79 206.83 C196.33 213.33 179.5 250.83 147.59 277.83 C202.33 250.33 201.83 204.33 205.33 195.83 C206.43 193.16 204.4 203.72 201.79 206.83 C196.33 213.33 179.5 250.83 147.59 277.83
C145.42 279.67 146.58 280.83 138.98 280.33 C136.46 280.17 128.85 285.83 112.65 278.83 C111.61 278.39 107.58 283.33 100.49 276.33 C145.42 279.67 146.58 280.83 138.98 280.33 C136.46 280.17 128.85 285.83 112.65 278.83 C111.61 278.39 107.58 283.33 100.49 276.33
C98.97 274.83 95.43 274.83 91.88 270.83 C90.39 269.15 86.31 270.83 83.27 263.83 C82.64 262.38 79.73 266.83 72.13 254.83 C69.6 250.83 C98.97 274.83 95.43 274.83 91.88 270.83 C90.39 269.15 86.31 270.83 83.27 263.83 C82.64 262.38 79.73 266.83 72.13 254.83 C69.6 250.83
65.54 255.33 66.05 244.33 C66.22 240.73 60.48 243.83 60.99 235.33 C61.08 233.84 54.91 230.33 58.45 224.83 C59.81 222.72 54.91 219.83 65.54 255.33 66.05 244.33 C66.22 240.73 60.48 243.83 60.99 235.33 C61.08 233.84 54.91 230.33 58.45 224.83 C59.81 222.72 54.91 219.83
58.96 212.83 C60.57 210.05 49.04 211.02 59.97 194.83 C62 191.83 59.97 190.33 65.54 183.83 C65.69 183.66 67.06 171.33 76.69 170.33 58.96 212.83 C60.57 210.05 49.04 211.02 59.97 194.83 C62 191.83 59.97 190.33 65.54 183.83 C65.69 183.66 67.06 171.33 76.69 170.33
C78.28 170.17 53.39 170.83 53.9 140.83 C53.92 139.25 55.61 142.67 53.9 140.83 C47.82 134.33 45.32 122.53 44.27 121.33 C38.19 114.33 C78.28 170.17 53.39 170.83 53.9 140.83 C53.92 139.25 55.61 142.67 53.9 140.83 C47.82 134.33 45.32 122.53 44.27 121.33 C38.19 114.33
39.71 105.83 39.71 105.83 C39.71 105.83 22.08 85.79 19.46 80.83 C-31.19 -14.67 114.07 63.59 118.22 66.33 C185.58 110.83 202 145.83 39.71 105.83 39.71 105.83 C39.71 105.83 22.08 85.79 19.46 80.83 C-31.19 -14.67 114.07 63.59 118.22 66.33 C185.58 110.83 202 145.83
202 145.83 C202 145.83 202.36 143.28 203 141.83 C203.64 140.39 204.56 140.02 204.33 139.83 z""" 202 145.83 C202 145.83 202.36 143.28 203 141.83 C203.64 140.39 204.56 140.02 204.33 139.83 z"""
def ptest(): def ptest():
svg.parseString(bpath) svg.parseString(bpath)
if __name__ == '__main__': if __name__ == '__main__':
#~ from tests.test_pathdata import * #~ from tests.test_pathdata import *
#~ unittest.main() #~ unittest.main()
profile() profile()
...@@ -12,7 +12,7 @@ def PrintHeader(): ...@@ -12,7 +12,7 @@ def PrintHeader():
def PrintMenu(): def PrintMenu():
return '<div id="mainmenu"><ul><li><a href="/">home</a></li><li><a href="/settings">settings</a></li><li><a href="/console">console</a></li><li><a href="/status">status (XML)</a></li></ul></div>' return '<div id="mainmenu"><ul><li><a href="/">home</a></li><li><a href="/settings">settings</a></li><li><a href="/console">console</a></li><li><a href="/status">status (XML)</a></li></ul></div>'
def PrintFooter(): def PrintFooter():
return "</body></html>" return "</body></html>"
...@@ -24,7 +24,7 @@ def TReloadPage(action): ...@@ -24,7 +24,7 @@ def TReloadPage(action):
def clear_text(mypass): def clear_text(mypass):
return mypass return mypass
gPronterPtr = 0 gPronterPtr = 0
gWeblog = "" gWeblog = ""
gLogRefresh =5 gLogRefresh =5
...@@ -80,7 +80,7 @@ class ConnectButton(object): ...@@ -80,7 +80,7 @@ class ConnectButton(object):
'tools.basic_auth.realm': 'My Print Server', 'tools.basic_auth.realm': 'My Print Server',
'tools.basic_auth.users': users, 'tools.basic_auth.users': users,
'tools.basic_auth.encrypt': clear_text} 'tools.basic_auth.encrypt': clear_text}
class DisconnectButton(object): class DisconnectButton(object):
def index(self): def index(self):
#handle connect push, then reload page #handle connect push, then reload page
...@@ -149,7 +149,7 @@ class MoveButton(object): ...@@ -149,7 +149,7 @@ class MoveButton(object):
'tools.basic_auth.realm': 'My Print Server', 'tools.basic_auth.realm': 'My Print Server',
'tools.basic_auth.users': users, 'tools.basic_auth.users': users,
'tools.basic_auth.encrypt': clear_text} 'tools.basic_auth.encrypt': clear_text}
class CustomButton(object): class CustomButton(object):
def button(self, *args): def button(self, *args):
if not args: if not args:
...@@ -164,7 +164,7 @@ class CustomButton(object): ...@@ -164,7 +164,7 @@ class CustomButton(object):
'tools.basic_auth.realm': 'My Print Server', 'tools.basic_auth.realm': 'My Print Server',
'tools.basic_auth.users': users, 'tools.basic_auth.users': users,
'tools.basic_auth.encrypt': clear_text} 'tools.basic_auth.encrypt': clear_text}
class HomeButton(object): class HomeButton(object):
def axis(self, *args): def axis(self, *args):
if not args: if not args:
...@@ -183,13 +183,13 @@ class HomeButton(object): ...@@ -183,13 +183,13 @@ class HomeButton(object):
if(taxis == "all"): if(taxis == "all"):
gPronterPtr.onecmd('home') gPronterPtr.onecmd('home')
return ReloadPage("Home All") return ReloadPage("Home All")
axis.exposed = True axis.exposed = True
axis._cp_config = {'tools.basic_auth.on': True, axis._cp_config = {'tools.basic_auth.on': True,
'tools.basic_auth.realm': 'My Print Server', 'tools.basic_auth.realm': 'My Print Server',
'tools.basic_auth.users': users, 'tools.basic_auth.users': users,
'tools.basic_auth.encrypt': clear_text} 'tools.basic_auth.encrypt': clear_text}
class XMLstatus(object): class XMLstatus(object):
def index(self): def index(self):
#handle connect push, then reload page #handle connect push, then reload page
...@@ -203,7 +203,7 @@ class XMLstatus(object): ...@@ -203,7 +203,7 @@ class XMLstatus(object):
state="Printing" state="Printing"
if gPronterPtr.paused: if gPronterPtr.paused:
state="Paused" state="Paused"
txt=txt+'<state>'+state+'</state>\n' txt=txt+'<state>'+state+'</state>\n'
txt=txt+'<file>'+str(gPronterPtr.filename)+'</file>\n' txt=txt+'<file>'+str(gPronterPtr.filename)+'</file>\n'
txt=txt+'<status>'+str(gPronterPtr.status.GetStatusText())+'</status>\n' txt=txt+'<status>'+str(gPronterPtr.status.GetStatusText())+'</status>\n'
...@@ -234,13 +234,13 @@ class XMLstatus(object): ...@@ -234,13 +234,13 @@ class XMLstatus(object):
index.exposed = True index.exposed = True
class WebInterface(object): class WebInterface(object):
def __init__(self, pface): def __init__(self, pface):
if (sys.version_info[1] > 6): if (sys.version_info[1] > 6):
# 'allow_no_value' wasn't added until 2.7 # 'allow_no_value' wasn't added until 2.7
config = ConfigParser.SafeConfigParser(allow_no_value=True) config = ConfigParser.SafeConfigParser(allow_no_value=True)
else: else:
config = ConfigParser.SafeConfigParser() config = ConfigParser.SafeConfigParser()
config.read(configfile(pface.web_auth_config or 'auth.config')) config.read(configfile(pface.web_auth_config or 'auth.config'))
users[config.get("user", "user")] = config.get("user", "pass") users[config.get("user", "user")] = config.get("user", "pass")
self.pface = pface self.pface = pface
...@@ -248,12 +248,12 @@ class WebInterface(object): ...@@ -248,12 +248,12 @@ class WebInterface(object):
global gWeblog global gWeblog
self.name="<div id='title'>Pronterface Web-Interface</div>" self.name="<div id='title'>Pronterface Web-Interface</div>"
gWeblog = "" gWeblog = ""
gPronterPtr = self.pface gPronterPtr = self.pface
settings = SettingsPage() settings = SettingsPage()
logpage = LogPage() logpage = LogPage()
console = ConsolePage() console = ConsolePage()
#actions #actions
connect = ConnectButton() connect = ConnectButton()
disconnect = DisconnectButton() disconnect = DisconnectButton()
...@@ -264,7 +264,7 @@ class WebInterface(object): ...@@ -264,7 +264,7 @@ class WebInterface(object):
home = HomeButton() home = HomeButton()
move = MoveButton() move = MoveButton()
custom =CustomButton() custom =CustomButton()
def index(self): def index(self):
pageText=PrintHeader()+self.name+PrintMenu() pageText=PrintHeader()+self.name+PrintMenu()
pageText+="<div id='content'>\n" pageText+="<div id='content'>\n"
...@@ -274,20 +274,20 @@ class WebInterface(object): ...@@ -274,20 +274,20 @@ class WebInterface(object):
pageText+="<li><a href='/reset'>Reset</a></li>\n" pageText+="<li><a href='/reset'>Reset</a></li>\n"
pageText+="<li><a href='/printbutton'>Print</a></li>\n" pageText+="<li><a href='/printbutton'>Print</a></li>\n"
pageText+="<li><a href='/pausebutton'>Pause</a></li>\n" pageText+="<li><a href='/pausebutton'>Pause</a></li>\n"
for i in gPronterPtr.cpbuttons: for i in gPronterPtr.cpbuttons:
pageText+="<li><a href='/custom/button/"+i[1]+"'>"+i[0]+"</a></li>\n" pageText+="<li><a href='/custom/button/"+i[1]+"'>"+i[0]+"</a></li>\n"
#for i in gPronterPtr.custombuttons: #for i in gPronterPtr.custombuttons:
# print(str(i)); # print(str(i));
pageText+="</ul>\n" pageText+="</ul>\n"
pageText+="</div>\n" pageText+="</div>\n"
pageText+="<div id='gui'>\n" pageText+="<div id='gui'>\n"
pageText+="<div id='control_xy'>" pageText+="<div id='control_xy'>"
pageText+="<img src='/images/control_xy.png' usemap='#xymap'/>" pageText+="<img src='/images/control_xy.png' usemap='#xymap'/>"
pageText+='<map name="xymap">' pageText+='<map name="xymap">'
pageText+='<area shape="rect" coords="8,5,51,48" href="/home/axis/x" alt="X Home" title="X Home" />' pageText+='<area shape="rect" coords="8,5,51,48" href="/home/axis/x" alt="X Home" title="X Home" />'
pageText+='<area shape="rect" coords="195,6,236,46" href="/home/axis/y" alt="Y Home" title="Y Home" />' pageText+='<area shape="rect" coords="195,6,236,46" href="/home/axis/y" alt="Y Home" title="Y Home" />'
pageText+='<area shape="rect" coords="7,192,48,232" href="/home/axis/all" alt="All Home" title="All Home" />' pageText+='<area shape="rect" coords="7,192,48,232" href="/home/axis/all" alt="All Home" title="All Home" />'
...@@ -336,7 +336,7 @@ class WebInterface(object): ...@@ -336,7 +336,7 @@ class WebInterface(object):
# pageText+="<ul><li><b>Bed Temp:</b></li><li><a href='/off'>OFF</a></li><li><a href='/185'>185 (PLA)</a></li><li><a href='/240'>240 (ABS)</a></li></ul>" # pageText+="<ul><li><b>Bed Temp:</b></li><li><a href='/off'>OFF</a></li><li><a href='/185'>185 (PLA)</a></li><li><a href='/240'>240 (ABS)</a></li></ul>"
# pageText+="</div>" # pageText+="</div>"
# pageText+="</div>" # pageText+="</div>"
pageText=pageText+"<div id='file'>File Loaded: <i>"+str(gPronterPtr.filename)+"</i></div>" pageText=pageText+"<div id='file'>File Loaded: <i>"+str(gPronterPtr.filename)+"</i></div>"
pageText+="<div id='logframe'><iframe src='/logpage' width='100%' height='100%'>iFraming Not Supported?? No log for you.</iframe></div>" pageText+="<div id='logframe'><iframe src='/logpage' width='100%' height='100%'>iFraming Not Supported?? No log for you.</iframe></div>"
pageText+=PrintFooter() pageText+=PrintFooter()
...@@ -357,7 +357,7 @@ class WebInterfaceStub(object): ...@@ -357,7 +357,7 @@ class WebInterfaceStub(object):
def KillWebInterfaceThread(): def KillWebInterfaceThread():
cherrypy.engine.exit() cherrypy.engine.exit()
def StartWebInterfaceThread(webInterface): def StartWebInterfaceThread(webInterface):
current_dir = os.path.dirname(os.path.abspath(__file__)) current_dir = os.path.dirname(os.path.abspath(__file__))
cherrypy.config.update({'engine.autoreload_on':False}) cherrypy.config.update({'engine.autoreload_on':False})
......
# This file is part of the Printrun suite. # This file is part of the Printrun suite.
# #
# Printrun is free software: you can redistribute it and/or modify # Printrun is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or # the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version. # (at your option) any later version.
# #
# Printrun is distributed in the hope that it will be useful, # Printrun is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with Printrun. If not, see <http://www.gnu.org/licenses/>. # along with Printrun. If not, see <http://www.gnu.org/licenses/>.
import wx, os, math import wx, os, math
from bufferedcanvas import * from bufferedcanvas import *
from printrun_utils import * from printrun_utils import *
def sign(n): def sign(n):
if n < 0: return -1 if n < 0: return -1
...@@ -56,10 +56,10 @@ class XYButtons(BufferedCanvas): ...@@ -56,10 +56,10 @@ class XYButtons(BufferedCanvas):
self.lastMove = None self.lastMove = None
self.lastCorner = None self.lastCorner = None
self.bgcolor = wx.Colour() self.bgcolor = wx.Colour()
self.bgcolor.SetFromName(bgcolor) self.bgcolor.SetFromName(bgcolor)
self.bgcolormask = wx.Colour(self.bgcolor.Red(), self.bgcolor.Green(), self.bgcolor.Blue(), 128) self.bgcolormask = wx.Colour(self.bgcolor.Red(), self.bgcolor.Green(), self.bgcolor.Blue(), 128)
BufferedCanvas.__init__(self, parent, ID) BufferedCanvas.__init__(self, parent, ID)
self.SetSize(self.bg_bmp.GetSize()) self.SetSize(self.bg_bmp.GetSize())
...@@ -70,11 +70,11 @@ class XYButtons(BufferedCanvas): ...@@ -70,11 +70,11 @@ class XYButtons(BufferedCanvas):
self.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeaveWindow) self.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeaveWindow)
self.Bind(wx.EVT_KEY_UP, self.OnKey) self.Bind(wx.EVT_KEY_UP, self.OnKey)
wx.GetTopLevelParent(self).Bind(wx.EVT_CHAR_HOOK, self.OnTopLevelKey) wx.GetTopLevelParent(self).Bind(wx.EVT_CHAR_HOOK, self.OnTopLevelKey)
def disable(self): def disable(self):
self.enabled = False self.enabled = False
self.update() self.update()
def enable(self): def enable(self):
self.enabled = True self.enabled = True
self.update() self.update()
...@@ -84,7 +84,7 @@ class XYButtons(BufferedCanvas): ...@@ -84,7 +84,7 @@ class XYButtons(BufferedCanvas):
self.moveCallback(*self.lastMove) self.moveCallback(*self.lastMove)
if self.lastCorner: if self.lastCorner:
self.cornerCallback(self.lastCorner) self.cornerCallback(self.lastCorner)
def clearRepeat(self): def clearRepeat(self):
self.lastMove = None self.lastMove = None
self.lastCorner = None self.lastCorner = None
...@@ -95,7 +95,7 @@ class XYButtons(BufferedCanvas): ...@@ -95,7 +95,7 @@ class XYButtons(BufferedCanvas):
pxlen = x1 - pos.x pxlen = x1 - pos.x
pylen = y1 - pos.y pylen = y1 - pos.y
return abs(xlen*pylen-ylen*pxlen)/math.sqrt(xlen**2+ylen**2) return abs(xlen*pylen-ylen*pxlen)/math.sqrt(xlen**2+ylen**2)
def distanceToPoint(self, x1, y1, x2, y2): def distanceToPoint(self, x1, y1, x2, y2):
return math.sqrt((x1-x2)**2 + (y1-y2)**2) return math.sqrt((x1-x2)**2 + (y1-y2)**2)
...@@ -103,17 +103,17 @@ class XYButtons(BufferedCanvas): ...@@ -103,17 +103,17 @@ class XYButtons(BufferedCanvas):
idx = self.keypad_idx + 1 idx = self.keypad_idx + 1
if idx > 2: idx = 0 if idx > 2: idx = 0
return idx return idx
def setKeypadIndex(self, idx): def setKeypadIndex(self, idx):
self.keypad_idx = idx self.keypad_idx = idx
self.update() self.update()
def getMovement(self): def getMovement(self):
xdir = [1, 0, -1, 0][self.quadrant] xdir = [1, 0, -1, 0][self.quadrant]
ydir = [0, 1, 0, -1][self.quadrant] ydir = [0, 1, 0, -1][self.quadrant]
magnitude = math.pow(10, self.concentric-1) magnitude = math.pow(10, self.concentric-1)
return (magnitude * xdir, magnitude * ydir) return (magnitude * xdir, magnitude * ydir)
def lookupConcentric(self, radius): def lookupConcentric(self, radius):
idx = 0 idx = 0
for r in XYButtons.concentric_circle_radii[1:]: for r in XYButtons.concentric_circle_radii[1:]:
...@@ -134,27 +134,27 @@ class XYButtons(BufferedCanvas): ...@@ -134,27 +134,27 @@ class XYButtons(BufferedCanvas):
quadrant = 1 # Up quadrant = 1 # Up
else: else:
quadrant = 2 # Left quadrant = 2 # Left
idx = self.lookupConcentric(radius) idx = self.lookupConcentric(radius)
return (quadrant, idx) return (quadrant, idx)
def mouseOverKeypad(self, mpos): def mouseOverKeypad(self, mpos):
for idx, kpos in XYButtons.keypad_positions.items(): for idx, kpos in XYButtons.keypad_positions.items():
radius = self.distanceToPoint(mpos[0], mpos[1], kpos[0], kpos[1]) radius = self.distanceToPoint(mpos[0], mpos[1], kpos[0], kpos[1])
if radius < 9: if radius < 9:
return idx return idx
return None return None
def drawPartialPie(self, gc, center, r1, r2, angle1, angle2): def drawPartialPie(self, gc, center, r1, r2, angle1, angle2):
p1 = wx.Point(center.x + r1*math.cos(angle1), center.y + r1*math.sin(angle1)) p1 = wx.Point(center.x + r1*math.cos(angle1), center.y + r1*math.sin(angle1))
path = gc.CreatePath() path = gc.CreatePath()
path.MoveToPoint(p1.x, p1.y) path.MoveToPoint(p1.x, p1.y)
path.AddArc(center.x, center.y, r1, angle1, angle2, True) path.AddArc(center.x, center.y, r1, angle1, angle2, True)
path.AddArc(center.x, center.y, r2, angle2, angle1, False) path.AddArc(center.x, center.y, r2, angle2, angle1, False)
path.AddLineToPoint(p1.x, p1.y) path.AddLineToPoint(p1.x, p1.y)
gc.DrawPath(path) gc.DrawPath(path)
def highlightQuadrant(self, gc, quadrant, concentric): def highlightQuadrant(self, gc, quadrant, concentric):
assert(quadrant >= 0 and quadrant <= 3) assert(quadrant >= 0 and quadrant <= 3)
assert(concentric >= 0 and concentric <= 3) assert(concentric >= 0 and concentric <= 3)
...@@ -175,12 +175,12 @@ class XYButtons(BufferedCanvas): ...@@ -175,12 +175,12 @@ class XYButtons(BufferedCanvas):
elif quadrant == 3: elif quadrant == 3:
a1, a2 = (math.pi*0.25, math.pi*0.75) a1, a2 = (math.pi*0.25, math.pi*0.75)
center.y += inner_ring_radius center.y += inner_ring_radius
r1 = XYButtons.concentric_circle_radii[concentric] r1 = XYButtons.concentric_circle_radii[concentric]
r2 = XYButtons.concentric_circle_radii[concentric+1] r2 = XYButtons.concentric_circle_radii[concentric+1]
self.drawPartialPie(gc, center, r1-inner_ring_radius, r2-inner_ring_radius, a1+fudge, a2-fudge) self.drawPartialPie(gc, center, r1-inner_ring_radius, r2-inner_ring_radius, a1+fudge, a2-fudge)
def drawCorner(self, gc, x, y, angle=0.0): def drawCorner(self, gc, x, y, angle=0.0):
w, h = XYButtons.corner_size w, h = XYButtons.corner_size
...@@ -201,7 +201,7 @@ class XYButtons(BufferedCanvas): ...@@ -201,7 +201,7 @@ class XYButtons(BufferedCanvas):
w, h = XYButtons.corner_size w, h = XYButtons.corner_size
cx, cy = XYButtons.center cx, cy = XYButtons.center
ww, wh = self.GetSizeTuple() ww, wh = self.GetSizeTuple()
inset = 10 inset = 10
if corner == 0: if corner == 0:
x, y = (cx - ww/2 + inset, cy - wh/2 + inset) x, y = (cx - ww/2 + inset, cy - wh/2 + inset)
...@@ -215,10 +215,10 @@ class XYButtons(BufferedCanvas): ...@@ -215,10 +215,10 @@ class XYButtons(BufferedCanvas):
elif corner == 3: elif corner == 3:
x, y = (cx - ww/2 + inset, cy + wh/2 - inset) x, y = (cx - ww/2 + inset, cy + wh/2 - inset)
self.drawCorner(gc, x+w/2, y-h/2, math.pi*3/2) self.drawCorner(gc, x+w/2, y-h/2, math.pi*3/2)
def draw(self, dc, w, h): def draw(self, dc, w, h):
dc.SetBackground(wx.Brush(self.bgcolor)) dc.SetBackground(wx.Brush(self.bgcolor))
dc.Clear() dc.Clear()
gc = wx.GraphicsContext.Create(dc) gc = wx.GraphicsContext.Create(dc)
...@@ -226,7 +226,7 @@ class XYButtons(BufferedCanvas): ...@@ -226,7 +226,7 @@ class XYButtons(BufferedCanvas):
if self.bg_bmp: if self.bg_bmp:
w, h = (self.bg_bmp.GetWidth(), self.bg_bmp.GetHeight()) w, h = (self.bg_bmp.GetWidth(), self.bg_bmp.GetHeight())
gc.DrawBitmap(self.bg_bmp, 0, 0, w, h) gc.DrawBitmap(self.bg_bmp, 0, 0, w, h)
if self.enabled: if self.enabled:
# Brush and pen for grey overlay when mouse hovers over # Brush and pen for grey overlay when mouse hovers over
gc.SetPen(wx.Pen(wx.Colour(100,100,100,172), 4)) gc.SetPen(wx.Pen(wx.Colour(100,100,100,172), 4))
...@@ -238,13 +238,13 @@ class XYButtons(BufferedCanvas): ...@@ -238,13 +238,13 @@ class XYButtons(BufferedCanvas):
self.highlightQuadrant(gc, self.quadrant, self.concentric) self.highlightQuadrant(gc, self.quadrant, self.concentric)
elif self.corner != None: elif self.corner != None:
self.highlightCorner(gc, self.corner) self.highlightCorner(gc, self.corner)
if self.keypad_idx >= 0: if self.keypad_idx >= 0:
padw, padh = (self.keypad_bmp.GetWidth(), self.keypad_bmp.GetHeight()) padw, padh = (self.keypad_bmp.GetWidth(), self.keypad_bmp.GetHeight())
pos = XYButtons.keypad_positions[self.keypad_idx] pos = XYButtons.keypad_positions[self.keypad_idx]
pos = (pos[0] - padw/2 - 3, pos[1] - padh/2 - 3) pos = (pos[0] - padw/2 - 3, pos[1] - padh/2 - 3)
gc.DrawBitmap(self.keypad_bmp, pos[0], pos[1], padw, padh) gc.DrawBitmap(self.keypad_bmp, pos[0], pos[1], padw, padh)
# Draw label overlays # Draw label overlays
gc.SetPen(wx.Pen(wx.Colour(255,255,255,128), 1)) gc.SetPen(wx.Pen(wx.Colour(255,255,255,128), 1))
gc.SetBrush(wx.Brush(wx.Colour(255,255,255,128+64))) gc.SetBrush(wx.Brush(wx.Colour(255,255,255,128+64)))
...@@ -256,7 +256,7 @@ class XYButtons(BufferedCanvas): ...@@ -256,7 +256,7 @@ class XYButtons(BufferedCanvas):
gc.SetPen(wx.Pen(self.bgcolor, 0)) gc.SetPen(wx.Pen(self.bgcolor, 0))
gc.SetBrush(wx.Brush(self.bgcolormask)) gc.SetBrush(wx.Brush(self.bgcolormask))
gc.DrawRectangle(0, 0, w, h) gc.DrawRectangle(0, 0, w, h)
# Used to check exact position of keypad dots, should we ever resize the bg image # Used to check exact position of keypad dots, should we ever resize the bg image
# for idx, kpos in XYButtons.label_overlay_positions.items(): # for idx, kpos in XYButtons.label_overlay_positions.items():
...@@ -289,7 +289,7 @@ class XYButtons(BufferedCanvas): ...@@ -289,7 +289,7 @@ class XYButtons(BufferedCanvas):
else: else:
evt.Skip() evt.Skip()
return return
if self.moveCallback: if self.moveCallback:
self.concentric = self.keypad_idx self.concentric = self.keypad_idx
x, y = self.getMovement() x, y = self.getMovement()
...@@ -301,7 +301,7 @@ class XYButtons(BufferedCanvas): ...@@ -301,7 +301,7 @@ class XYButtons(BufferedCanvas):
def OnMotion(self, event): def OnMotion(self, event):
if not self.enabled: if not self.enabled:
return return
oldcorner = self.corner oldcorner = self.corner
oldq, oldc = self.quadrant, self.concentric oldq, oldc = self.quadrant, self.concentric
...@@ -318,7 +318,7 @@ class XYButtons(BufferedCanvas): ...@@ -318,7 +318,7 @@ class XYButtons(BufferedCanvas):
# If mouse hovers in space between quadrants, don't commit to a quadrant # If mouse hovers in space between quadrants, don't commit to a quadrant
if riseDist <= XYButtons.spacer or fallDist <= XYButtons.spacer: if riseDist <= XYButtons.spacer or fallDist <= XYButtons.spacer:
self.quadrant = None self.quadrant = None
cx, cy = XYButtons.center cx, cy = XYButtons.center
if mpos.x < cx and mpos.y < cy: if mpos.x < cx and mpos.y < cy:
self.corner = 0 self.corner = 0
...@@ -335,7 +335,7 @@ class XYButtons(BufferedCanvas): ...@@ -335,7 +335,7 @@ class XYButtons(BufferedCanvas):
def OnLeftDown(self, event): def OnLeftDown(self, event):
if not self.enabled: if not self.enabled:
return return
# Take focus when clicked so that arrow keys can control movement # Take focus when clicked so that arrow keys can control movement
self.SetFocus() self.SetFocus()
...@@ -362,7 +362,7 @@ class XYButtons(BufferedCanvas): ...@@ -362,7 +362,7 @@ class XYButtons(BufferedCanvas):
self.setKeypadIndex(-1) self.setKeypadIndex(-1)
else: else:
self.setKeypadIndex(idx) self.setKeypadIndex(idx)
def OnLeaveWindow(self, evt): def OnLeaveWindow(self, evt):
self.quadrant = None self.quadrant = None
self.concentric = None self.concentric = None
......
# This file is part of the Printrun suite. # This file is part of the Printrun suite.
# #
# Printrun is free software: you can redistribute it and/or modify # Printrun is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or # the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version. # (at your option) any later version.
# #
# Printrun is distributed in the hope that it will be useful, # Printrun is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with Printrun. If not, see <http://www.gnu.org/licenses/>. # along with Printrun. If not, see <http://www.gnu.org/licenses/>.
import wx, os, math import wx, os, math
from bufferedcanvas import * from bufferedcanvas import *
from printrun_utils import * from printrun_utils import *
def sign(n): def sign(n):
if n < 0: return -1 if n < 0: return -1
...@@ -42,9 +42,9 @@ class ZButtons(BufferedCanvas): ...@@ -42,9 +42,9 @@ class ZButtons(BufferedCanvas):
# Remember the last clicked value, so we can repeat when spacebar pressed # Remember the last clicked value, so we can repeat when spacebar pressed
self.lastValue = None self.lastValue = None
self.bgcolor = wx.Colour() self.bgcolor = wx.Colour()
self.bgcolor.SetFromName(bgcolor) self.bgcolor.SetFromName(bgcolor)
self.bgcolormask = wx.Colour(self.bgcolor.Red(), self.bgcolor.Green(), self.bgcolor.Blue(), 128) self.bgcolormask = wx.Colour(self.bgcolor.Red(), self.bgcolor.Green(), self.bgcolor.Blue(), 128)
BufferedCanvas.__init__(self, parent, ID) BufferedCanvas.__init__(self, parent, ID)
...@@ -59,7 +59,7 @@ class ZButtons(BufferedCanvas): ...@@ -59,7 +59,7 @@ class ZButtons(BufferedCanvas):
def disable(self): def disable(self):
self.enabled = False self.enabled = False
self.update() self.update()
def enable(self): def enable(self):
self.enabled = True self.enabled = True
self.update() self.update()
...@@ -78,7 +78,7 @@ class ZButtons(BufferedCanvas): ...@@ -78,7 +78,7 @@ class ZButtons(BufferedCanvas):
return idx return idx
idx += 1 idx += 1
return None return None
def highlight(self, gc, rng, dir): def highlight(self, gc, rng, dir):
assert(rng >= -1 and rng <= 3) assert(rng >= -1 and rng <= 3)
assert(dir >= -1 and dir <= 1) assert(dir >= -1 and dir <= 1)
...@@ -93,13 +93,13 @@ class ZButtons(BufferedCanvas): ...@@ -93,13 +93,13 @@ class ZButtons(BufferedCanvas):
gc.DrawRoundedRectangle(x, y, w, h, 4) gc.DrawRoundedRectangle(x, y, w, h, 4)
# gc.DrawRectangle(x, y, w, h) # gc.DrawRectangle(x, y, w, h)
# self.drawPartialPie(dc, center, r1-inner_ring_radius, r2-inner_ring_radius, a1+fudge, a2-fudge) # self.drawPartialPie(dc, center, r1-inner_ring_radius, r2-inner_ring_radius, a1+fudge, a2-fudge)
def getRangeDir(self, pos): def getRangeDir(self, pos):
ydelta = ZButtons.center[1] - pos[1] ydelta = ZButtons.center[1] - pos[1]
return (self.lookupRange(abs(ydelta)), sign(ydelta)) return (self.lookupRange(abs(ydelta)), sign(ydelta))
def draw(self, dc, w, h): def draw(self, dc, w, h):
dc.SetBackground(wx.Brush(self.bgcolor)) dc.SetBackground(wx.Brush(self.bgcolor))
dc.Clear() dc.Clear()
gc = wx.GraphicsContext.Create(dc) gc = wx.GraphicsContext.Create(dc)
if self.bg_bmp: if self.bg_bmp:
...@@ -114,7 +114,7 @@ class ZButtons(BufferedCanvas): ...@@ -114,7 +114,7 @@ class ZButtons(BufferedCanvas):
if kpos and idx != self.range: if kpos and idx != self.range:
r = kpos[2] r = kpos[2]
gc.DrawEllipse(ZButtons.center[0]-kpos[0]-r, ZButtons.center[1]-kpos[1]-r, r*2, r*2) gc.DrawEllipse(ZButtons.center[0]-kpos[0]-r, ZButtons.center[1]-kpos[1]-r, r*2, r*2)
# Top 'layer' is the mouse-over highlights # Top 'layer' is the mouse-over highlights
gc.SetPen(wx.Pen(wx.Colour(100,100,100,172), 4)) gc.SetPen(wx.Pen(wx.Colour(100,100,100,172), 4))
gc.SetBrush(wx.Brush(wx.Colour(0,0,0,128))) gc.SetBrush(wx.Brush(wx.Colour(0,0,0,128)))
...@@ -132,7 +132,7 @@ class ZButtons(BufferedCanvas): ...@@ -132,7 +132,7 @@ class ZButtons(BufferedCanvas):
def OnMotion(self, event): def OnMotion(self, event):
if not self.enabled: if not self.enabled:
return return
oldr, oldd = self.range, self.direction oldr, oldd = self.range, self.direction
mpos = event.GetPosition() mpos = event.GetPosition()
......
# This file is part of the Printrun suite. # This file is part of the Printrun suite.
# #
# Printrun is free software: you can redistribute it and/or modify # Printrun is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or # the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version. # (at your option) any later version.
# #
# Printrun is distributed in the hope that it will be useful, # Printrun is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with Printrun. If not, see <http://www.gnu.org/licenses/>. # along with Printrun. If not, see <http://www.gnu.org/licenses/>.
...@@ -70,7 +70,7 @@ class scapewin(wx.Frame): ...@@ -70,7 +70,7 @@ class scapewin(wx.Frame):
self.SetIcon(wx.Icon("plater.ico",wx.BITMAP_TYPE_ICO)) self.SetIcon(wx.Icon("plater.ico",wx.BITMAP_TYPE_ICO))
self.SetClientSize(size) self.SetClientSize(size)
self.panel=wx.Panel(self,size=size) self.panel=wx.Panel(self,size=size)
""" """
if __name__ == '__main__': if __name__ == '__main__':
...@@ -82,4 +82,3 @@ if __name__ == '__main__': ...@@ -82,4 +82,3 @@ if __name__ == '__main__':
""" """
zimage("catposthtmap2.jpg","testobj.stl") zimage("catposthtmap2.jpg","testobj.stl")
del a del a
#!/usr/bin/env python #!/usr/bin/env python
# This file is part of the Printrun suite. # This file is part of the Printrun suite.
# #
# Printrun is free software: you can redistribute it and/or modify # Printrun is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or # the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version. # (at your option) any later version.
# #
# Printrun is distributed in the hope that it will be useful, # Printrun is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with Printrun. If not, see <http://www.gnu.org/licenses/>. # along with Printrun. If not, see <http://www.gnu.org/licenses/>.
import cmd, sys import cmd, sys
import glob, os, time, datetime import glob, os, time, datetime
import sys, subprocess import sys, subprocess
import math, codecs import math, codecs
from math import sqrt from math import sqrt
...@@ -42,7 +42,7 @@ except: ...@@ -42,7 +42,7 @@ except:
def dosify(name): def dosify(name):
return os.path.split(name)[1].split(".")[0][:8]+".g" return os.path.split(name)[1].split(".")[0][:8]+".g"
def measurements(g): def measurements(g):
Xcur=0.0 Xcur=0.0
Ycur=0.0 Ycur=0.0
...@@ -56,8 +56,8 @@ def measurements(g): ...@@ -56,8 +56,8 @@ def measurements(g):
Xtot=0 Xtot=0
Ytot=0 Ytot=0
Ztot=0 Ztot=0
for i in g: for i in g:
if "X" in i and ("G1" in i or "G0" in i): if "X" in i and ("G1" in i or "G0" in i):
try: try:
...@@ -73,7 +73,7 @@ def measurements(g): ...@@ -73,7 +73,7 @@ def measurements(g):
if Ycur>Ymax: Ymax=Ycur if Ycur>Ymax: Ymax=Ycur
except: except:
pass pass
if "Z" in i and ("G1" in i or "G0" in i): if "Z" in i and ("G1" in i or "G0" in i):
try: try:
Zcur = float(i.split("Z")[1].split(" ")[0]) Zcur = float(i.split("Z")[1].split(" ")[0])
...@@ -81,12 +81,12 @@ def measurements(g): ...@@ -81,12 +81,12 @@ def measurements(g):
if Zcur>Zmax: Zmax=Zcur if Zcur>Zmax: Zmax=Zcur
except: except:
pass pass
Xtot = Xmax - Xmin Xtot = Xmax - Xmin
Ytot = Ymax - Ymin Ytot = Ymax - Ymin
Ztot = Zmax - Zmin Ztot = Zmax - Zmin
return (Xtot,Ytot,Ztot,Xmin,Xmax,Ymin,Ymax,Zmin,Zmax) return (Xtot,Ytot,Ztot,Xmin,Xmax,Ymin,Ymax,Zmin,Zmax)
def totalelength(g): def totalelength(g):
...@@ -108,11 +108,11 @@ def get_coordinate_value(axis, parts): ...@@ -108,11 +108,11 @@ def get_coordinate_value(axis, parts):
return float(i[1:]) return float(i[1:])
return None return None
def hypot3d(X1, Y1, Z1, X2=0.0, Y2=0.0, Z2=0.0): def hypot3d(X1, Y1, Z1, X2=0.0, Y2=0.0, Z2=0.0):
return math.hypot(X2-X1, math.hypot(Y2-Y1, Z2-Z1)) return math.hypot(X2-X1, math.hypot(Y2-Y1, Z2-Z1))
def estimate_duration(g): def estimate_duration(g):
lastx = lasty = lastz = laste = lastf = 0.0 lastx = lasty = lastz = laste = lastf = 0.0
x = y = z = e = f = 0.0 x = y = z = e = f = 0.0
currenttravel = 0.0 currenttravel = 0.0
...@@ -150,7 +150,7 @@ def estimate_duration(g): ...@@ -150,7 +150,7 @@ def estimate_duration(g):
f = get_coordinate_value("F", parts[1:]) f = get_coordinate_value("F", parts[1:])
if f is None: f=lastf if f is None: f=lastf
else: f /= 60.0 # mm/s vs mm/m else: f /= 60.0 # mm/s vs mm/m
# given last feedrate and current feedrate calculate the distance needed to achieve current feedrate. # given last feedrate and current feedrate calculate the distance needed to achieve current feedrate.
# if travel is longer than req'd distance, then subtract distance to achieve full speed, and add the time it took to get there. # if travel is longer than req'd distance, then subtract distance to achieve full speed, and add the time it took to get there.
# then calculate the time taken to complete the remaining distance # then calculate the time taken to complete the remaining distance
...@@ -279,7 +279,7 @@ class pronsole(cmd.Cmd): ...@@ -279,7 +279,7 @@ class pronsole(cmd.Cmd):
self.webrequested=False self.webrequested=False
self.web_config=None self.web_config=None
self.web_auth_config=None self.web_auth_config=None
def set_temp_preset(self,key,value): def set_temp_preset(self,key,value):
if not key.startswith("bed"): if not key.startswith("bed"):
self.temps["pla"] = str(self.settings.temperature_pla) self.temps["pla"] = str(self.settings.temperature_pla)
...@@ -289,7 +289,7 @@ class pronsole(cmd.Cmd): ...@@ -289,7 +289,7 @@ class pronsole(cmd.Cmd):
self.bedtemps["pla"] = str(self.settings.bedtemp_pla) self.bedtemps["pla"] = str(self.settings.bedtemp_pla)
self.bedtemps["abs"] = str(self.settings.bedtemp_abs) self.bedtemps["abs"] = str(self.settings.bedtemp_abs)
print "Bed temperature presets updated, pla:%s, abs:%s" % (self.bedtemps["pla"],self.bedtemps["abs"]) print "Bed temperature presets updated, pla:%s, abs:%s" % (self.bedtemps["pla"],self.bedtemps["abs"])
def scanserial(self): def scanserial(self):
"""scan for available ports. return a list of device names.""" """scan for available ports. return a list of device names."""
baselist=[] baselist=[]
...@@ -309,16 +309,16 @@ class pronsole(cmd.Cmd): ...@@ -309,16 +309,16 @@ class pronsole(cmd.Cmd):
print "Printer is now online" print "Printer is now online"
sys.stdout.write(self.prompt) sys.stdout.write(self.prompt)
sys.stdout.flush() sys.stdout.flush()
def help_help(self,l): def help_help(self,l):
self.do_help("") self.do_help("")
def do_gcodes(self,l): def do_gcodes(self,l):
self.help_gcodes() self.help_gcodes()
def help_gcodes(self): def help_gcodes(self):
print "Gcodes are passed through to the printer as they are" print "Gcodes are passed through to the printer as they are"
def complete_macro(self,text,line,begidx,endidx): def complete_macro(self,text,line,begidx,endidx):
if (len(line.split())==2 and line[-1] != " ") or (len(line.split())==1 and line[-1]==" "): if (len(line.split())==2 and line[-1] != " ") or (len(line.split())==1 and line[-1]==" "):
return [i for i in self.macros.keys() if i.startswith(text)] return [i for i in self.macros.keys() if i.startswith(text)]
...@@ -326,7 +326,7 @@ class pronsole(cmd.Cmd): ...@@ -326,7 +326,7 @@ class pronsole(cmd.Cmd):
return [i for i in ["/D", "/S"] + self.completenames(text) if i.startswith(text)] return [i for i in ["/D", "/S"] + self.completenames(text) if i.startswith(text)]
else: else:
return [] return []
def hook_macro(self,l): def hook_macro(self,l):
l = l.rstrip() l = l.rstrip()
ls = l.lstrip() ls = l.lstrip()
...@@ -336,8 +336,8 @@ class pronsole(cmd.Cmd): ...@@ -336,8 +336,8 @@ class pronsole(cmd.Cmd):
# pass the unprocessed line to regular command processor to not require empty line in .pronsolerc # pass the unprocessed line to regular command processor to not require empty line in .pronsolerc
return self.onecmd(l) return self.onecmd(l)
self.cur_macro_def += l + "\n" self.cur_macro_def += l + "\n"
def end_macro(self): def end_macro(self):
if self.__dict__.has_key("onecmd"): del self.onecmd # remove override if self.__dict__.has_key("onecmd"): del self.onecmd # remove override
self.prompt="PC>" self.prompt="PC>"
if self.cur_macro_def!="": if self.cur_macro_def!="":
...@@ -360,7 +360,7 @@ class pronsole(cmd.Cmd): ...@@ -360,7 +360,7 @@ class pronsole(cmd.Cmd):
else: else:
print "Empty macro - cancelled" print "Empty macro - cancelled"
del self.cur_macro_name,self.cur_macro_def del self.cur_macro_name,self.cur_macro_def
def compile_macro_line(self,line): def compile_macro_line(self,line):
line = line.rstrip() line = line.rstrip()
ls = line.lstrip() ls = line.lstrip()
...@@ -370,7 +370,7 @@ class pronsole(cmd.Cmd): ...@@ -370,7 +370,7 @@ class pronsole(cmd.Cmd):
return ws + ls[1:] + "\n" # python mode return ws + ls[1:] + "\n" # python mode
else: else:
return ws + 'self.onecmd("'+ls+'".format(*arg))\n' # parametric command mode return ws + 'self.onecmd("'+ls+'".format(*arg))\n' # parametric command mode
def compile_macro(self,macro_name,macro_def): def compile_macro(self,macro_name,macro_def):
if macro_def.strip() == "": if macro_def.strip() == "":
print "Empty macro - cancelled" print "Empty macro - cancelled"
...@@ -384,7 +384,7 @@ class pronsole(cmd.Cmd): ...@@ -384,7 +384,7 @@ class pronsole(cmd.Cmd):
pycode += self.compile_macro_line(l) pycode += self.compile_macro_line(l)
exec pycode exec pycode
return macro return macro
def start_macro(self,macro_name,prev_definition="",suppress_instructions=False): def start_macro(self,macro_name,prev_definition="",suppress_instructions=False):
if not self.processing_rc and not suppress_instructions: if not self.processing_rc and not suppress_instructions:
print "Enter macro using indented lines, end with empty line" print "Enter macro using indented lines, end with empty line"
...@@ -392,7 +392,7 @@ class pronsole(cmd.Cmd): ...@@ -392,7 +392,7 @@ class pronsole(cmd.Cmd):
self.cur_macro_def = "" self.cur_macro_def = ""
self.onecmd = self.hook_macro # override onecmd temporarily self.onecmd = self.hook_macro # override onecmd temporarily
self.prompt="..>" self.prompt="..>"
def delete_macro(self,macro_name): def delete_macro(self,macro_name):
if macro_name in self.macros.keys(): if macro_name in self.macros.keys():
delattr(self.__class__,"do_"+macro_name) delattr(self.__class__,"do_"+macro_name)
...@@ -427,7 +427,7 @@ class pronsole(cmd.Cmd): ...@@ -427,7 +427,7 @@ class pronsole(cmd.Cmd):
self.start_macro(macro_name,self.macros[macro_name]) self.start_macro(macro_name,self.macros[macro_name])
else: else:
self.start_macro(macro_name) self.start_macro(macro_name)
def help_macro(self): def help_macro(self):
print "Define single-line macro: macro <name> <definition>" print "Define single-line macro: macro <name> <definition>"
print "Define multi-line macro: macro <name>" print "Define multi-line macro: macro <name>"
...@@ -436,7 +436,7 @@ class pronsole(cmd.Cmd): ...@@ -436,7 +436,7 @@ class pronsole(cmd.Cmd):
print "Delete macro: macro <name> /d" print "Delete macro: macro <name> /d"
print "Show macro definition: macro <name> /s" print "Show macro definition: macro <name> /s"
print "'macro' without arguments displays list of defined macros" print "'macro' without arguments displays list of defined macros"
def subhelp_macro(self,macro_name): def subhelp_macro(self,macro_name):
if macro_name in self.macros.keys(): if macro_name in self.macros.keys():
macro_def = self.macros[macro_name] macro_def = self.macros[macro_name]
...@@ -458,7 +458,7 @@ class pronsole(cmd.Cmd): ...@@ -458,7 +458,7 @@ class pronsole(cmd.Cmd):
print "Unknown variable '%s'" % var print "Unknown variable '%s'" % var
except ValueError, ve: except ValueError, ve:
print "Bad value for variable '%s', expecting %s (%s)" % (var,repr(t)[1:-1],ve.args[0]) print "Bad value for variable '%s', expecting %s (%s)" % (var,repr(t)[1:-1],ve.args[0])
def do_set(self,argl): def do_set(self,argl):
args = argl.split(None,1) args = argl.split(None,1)
if len(args) < 1: if len(args) < 1:
...@@ -473,7 +473,7 @@ class pronsole(cmd.Cmd): ...@@ -473,7 +473,7 @@ class pronsole(cmd.Cmd):
print "Unknown variable '%s'" % args[0] print "Unknown variable '%s'" % args[0]
return return
self.set(args[0],args[1]) self.set(args[0],args[1])
def help_set(self): def help_set(self):
print "Set variable: set <variable> <value>" print "Set variable: set <variable> <value>"
print "Show variable: set <variable>" print "Show variable: set <variable>"
...@@ -486,11 +486,11 @@ class pronsole(cmd.Cmd): ...@@ -486,11 +486,11 @@ class pronsole(cmd.Cmd):
return [i for i in self.settings._tabcomplete(line.split()[1]) if i.startswith(text)] return [i for i in self.settings._tabcomplete(line.split()[1]) if i.startswith(text)]
else: else:
return [] return []
def postloop(self): def postloop(self):
self.p.disconnect() self.p.disconnect()
cmd.Cmd.postloop(self) cmd.Cmd.postloop(self)
def load_rc(self,rc_filename): def load_rc(self,rc_filename):
self.processing_rc=True self.processing_rc=True
try: try:
...@@ -505,7 +505,7 @@ class pronsole(cmd.Cmd): ...@@ -505,7 +505,7 @@ class pronsole(cmd.Cmd):
self.rc_loaded = True self.rc_loaded = True
finally: finally:
self.processing_rc=False self.processing_rc=False
def load_default_rc(self,rc_filename=".pronsolerc"): def load_default_rc(self,rc_filename=".pronsolerc"):
try: try:
try: try:
...@@ -515,10 +515,10 @@ class pronsole(cmd.Cmd): ...@@ -515,10 +515,10 @@ class pronsole(cmd.Cmd):
except IOError: except IOError:
# make sure the filename is initialized # make sure the filename is initialized
self.rc_filename = os.path.abspath(os.path.join(os.path.expanduser("~"),rc_filename)) self.rc_filename = os.path.abspath(os.path.join(os.path.expanduser("~"),rc_filename))
def save_in_rc(self,key,definition): def save_in_rc(self,key,definition):
""" """
Saves or updates macro or other definitions in .pronsolerc Saves or updates macro or other definitions in .pronsolerc
key is prefix that determines what is being defined/updated (e.g. 'macro foo') key is prefix that determines what is being defined/updated (e.g. 'macro foo')
definition is the full definition (that is written to file). (e.g. 'macro foo move x 10') definition is the full definition (that is written to file). (e.g. 'macro foo move x 10')
Set key as empty string to just add (and not overwrite) Set key as empty string to just add (and not overwrite)
...@@ -566,17 +566,17 @@ class pronsole(cmd.Cmd): ...@@ -566,17 +566,17 @@ class pronsole(cmd.Cmd):
print "Saving failed for",key+":",str(e) print "Saving failed for",key+":",str(e)
finally: finally:
del rci,rco del rci,rco
def preloop(self): def preloop(self):
print "Welcome to the printer console! Type \"help\" for a list of available commands." print "Welcome to the printer console! Type \"help\" for a list of available commands."
cmd.Cmd.preloop(self) cmd.Cmd.preloop(self)
def do_connect(self,l): def do_connect(self,l):
a=l.split() a=l.split()
p=self.scanserial() p=self.scanserial()
port=self.settings.port port=self.settings.port
if (port == "" or port not in p) and len(p)>0: if (port == "" or port not in p) and len(p)>0:
port=p[0] port=p[0]
baud=self.settings.baudrate or 115200 baud=self.settings.baudrate or 115200
if(len(a)>0): if(len(a)>0):
port=a[0] port=a[0]
...@@ -597,7 +597,7 @@ class pronsole(cmd.Cmd): ...@@ -597,7 +597,7 @@ class pronsole(cmd.Cmd):
self.settings.baudrate = baud self.settings.baudrate = baud
self.save_in_rc("set baudrate","set baudrate %d" % baud) self.save_in_rc("set baudrate","set baudrate %d" % baud)
self.p.connect(port, baud) self.p.connect(port, baud)
def help_connect(self): def help_connect(self):
print "Connect to printer" print "Connect to printer"
print "connect <port> <baudrate>" print "connect <port> <baudrate>"
...@@ -607,7 +607,7 @@ class pronsole(cmd.Cmd): ...@@ -607,7 +607,7 @@ class pronsole(cmd.Cmd):
print "Available ports: ", " ".join(ports) print "Available ports: ", " ".join(ports)
else: else:
print "No serial ports were automatically found." print "No serial ports were automatically found."
def complete_connect(self, text, line, begidx, endidx): def complete_connect(self, text, line, begidx, endidx):
if (len(line.split())==2 and line[-1] != " ") or (len(line.split())==1 and line[-1]==" "): if (len(line.split())==2 and line[-1] != " ") or (len(line.split())==1 and line[-1]==" "):
return [i for i in self.scanserial() if i.startswith(text)] return [i for i in self.scanserial() if i.startswith(text)]
...@@ -615,13 +615,13 @@ class pronsole(cmd.Cmd): ...@@ -615,13 +615,13 @@ class pronsole(cmd.Cmd):
return [i for i in ["2400", "9600", "19200", "38400", "57600", "115200"] if i.startswith(text)] return [i for i in ["2400", "9600", "19200", "38400", "57600", "115200"] if i.startswith(text)]
else: else:
return [] return []
def do_disconnect(self,l): def do_disconnect(self,l):
self.p.disconnect() self.p.disconnect()
def help_disconnect(self): def help_disconnect(self):
print "Disconnects from the printer" print "Disconnects from the printer"
def do_load(self,l): def do_load(self,l):
if len(l)==0: if len(l)==0:
print "No file name given." print "No file name given."
...@@ -633,7 +633,7 @@ class pronsole(cmd.Cmd): ...@@ -633,7 +633,7 @@ class pronsole(cmd.Cmd):
self.f=[i.replace("\n","").replace("\r","") for i in open(l)] self.f=[i.replace("\n","").replace("\r","") for i in open(l)]
self.filename=l self.filename=l
print "Loaded ",l,", ",len(self.f)," lines." print "Loaded ",l,", ",len(self.f)," lines."
def complete_load(self, text, line, begidx, endidx): def complete_load(self, text, line, begidx, endidx):
s=line.split() s=line.split()
if len(s)>2: if len(s)>2:
...@@ -643,11 +643,11 @@ class pronsole(cmd.Cmd): ...@@ -643,11 +643,11 @@ class pronsole(cmd.Cmd):
return [i[len(s[1])-len(text):] for i in glob.glob(s[1]+"*/")+glob.glob(s[1]+"*.g*")] return [i[len(s[1])-len(text):] for i in glob.glob(s[1]+"*/")+glob.glob(s[1]+"*.g*")]
else: else:
return glob.glob("*/")+glob.glob("*.g*") return glob.glob("*/")+glob.glob("*.g*")
def help_load(self): def help_load(self):
print "Loads a gcode file (with tab-completion)" print "Loads a gcode file (with tab-completion)"
def do_upload(self,l): def do_upload(self,l):
if len(l)==0: if len(l)==0:
print "No file name given." print "No file name given."
...@@ -699,8 +699,8 @@ class pronsole(cmd.Cmd): ...@@ -699,8 +699,8 @@ class pronsole(cmd.Cmd):
self.p.clear=1 self.p.clear=1
self.p.startprint([]) self.p.startprint([])
print "A partial file named ",tname," may have been written to the sd card." print "A partial file named ",tname," may have been written to the sd card."
def complete_upload(self, text, line, begidx, endidx): def complete_upload(self, text, line, begidx, endidx):
s=line.split() s=line.split()
if len(s)>2: if len(s)>2:
...@@ -710,17 +710,17 @@ class pronsole(cmd.Cmd): ...@@ -710,17 +710,17 @@ class pronsole(cmd.Cmd):
return [i[len(s[1])-len(text):] for i in glob.glob(s[1]+"*/")+glob.glob(s[1]+"*.g*")] return [i[len(s[1])-len(text):] for i in glob.glob(s[1]+"*/")+glob.glob(s[1]+"*.g*")]
else: else:
return glob.glob("*/")+glob.glob("*.g*") return glob.glob("*/")+glob.glob("*.g*")
def help_upload(self): def help_upload(self):
print "Uploads a gcode file to the sd card" print "Uploads a gcode file to the sd card"
def help_print(self): def help_print(self):
if self.f is None: if self.f is None:
print "Send a loaded gcode file to the printer. Load a file with the load command first." print "Send a loaded gcode file to the printer. Load a file with the load command first."
else: else:
print "Send a loaded gcode file to the printer. You have "+self.filename+" loaded right now." print "Send a loaded gcode file to the printer. You have "+self.filename+" loaded right now."
def do_print(self, l): def do_print(self, l):
if self.f is None: if self.f is None:
print "No file loaded. Please use load first." print "No file loaded. Please use load first."
...@@ -734,7 +734,7 @@ class pronsole(cmd.Cmd): ...@@ -734,7 +734,7 @@ class pronsole(cmd.Cmd):
#self.p.pause() #self.p.pause()
#self.paused=True #self.paused=True
#self.do_resume(None) #self.do_resume(None)
def do_pause(self,l): def do_pause(self,l):
if self.sdprinting: if self.sdprinting:
self.p.send_now("M25") self.p.send_now("M25")
...@@ -743,14 +743,14 @@ class pronsole(cmd.Cmd): ...@@ -743,14 +743,14 @@ class pronsole(cmd.Cmd):
print "Not printing, cannot pause." print "Not printing, cannot pause."
return return
self.p.pause() self.p.pause()
#self.p.connect()# This seems to work, but is not a good solution. #self.p.connect()# This seems to work, but is not a good solution.
self.paused=True self.paused=True
#self.do_resume(None) #self.do_resume(None)
def help_pause(self): def help_pause(self):
print "Pauses a running print" print "Pauses a running print"
def do_resume(self,l): def do_resume(self,l):
if not self.paused: if not self.paused:
print "Not paused, unable to resume. Start a print first." print "Not paused, unable to resume. Start a print first."
...@@ -761,16 +761,16 @@ class pronsole(cmd.Cmd): ...@@ -761,16 +761,16 @@ class pronsole(cmd.Cmd):
return return
else: else:
self.p.resume() self.p.resume()
def help_resume(self): def help_resume(self):
print "Resumes a paused print." print "Resumes a paused print."
def emptyline(self): def emptyline(self):
pass pass
def do_shell(self,l): def do_shell(self,l):
exec(l) exec(l)
def listfiles(self,line): def listfiles(self,line):
if "Begin file list" in line: if "Begin file list" in line:
self.listing=1 self.listing=1
...@@ -779,7 +779,7 @@ class pronsole(cmd.Cmd): ...@@ -779,7 +779,7 @@ class pronsole(cmd.Cmd):
self.recvlisteners.remove(self.listfiles) self.recvlisteners.remove(self.listfiles)
elif self.listing: elif self.listing:
self.sdfiles+=[line.replace("\n","").replace("\r","").lower()] self.sdfiles+=[line.replace("\n","").replace("\r","").lower()]
def do_ls(self,l): def do_ls(self,l):
if not self.p.online: if not self.p.online:
print "Printer is not online. Try connect to it first." print "Printer is not online. Try connect to it first."
...@@ -790,10 +790,10 @@ class pronsole(cmd.Cmd): ...@@ -790,10 +790,10 @@ class pronsole(cmd.Cmd):
self.p.send_now("M20") self.p.send_now("M20")
time.sleep(0.5) time.sleep(0.5)
print " ".join(self.sdfiles) print " ".join(self.sdfiles)
def help_ls(self): def help_ls(self):
print "lists files on the SD card" print "lists files on the SD card"
def waitforsdresponse(self,l): def waitforsdresponse(self,l):
if "file.open failed" in l: if "file.open failed" in l:
print "Opening file failed." print "Opening file failed."
...@@ -820,13 +820,13 @@ class pronsole(cmd.Cmd): ...@@ -820,13 +820,13 @@ class pronsole(cmd.Cmd):
self.percentdone=100.0*int(vals[0])/int(vals[1]) self.percentdone=100.0*int(vals[0])/int(vals[1])
except: except:
pass pass
def do_reset(self,l): def do_reset(self,l):
self.p.reset() self.p.reset()
def help_reset(self): def help_reset(self):
print "Resets the printer." print "Resets the printer."
def do_sdprint(self,l): def do_sdprint(self,l):
if not self.p.online: if not self.p.online:
print "Printer is not online. Try connect to it first." print "Printer is not online. Try connect to it first."
...@@ -844,11 +844,11 @@ class pronsole(cmd.Cmd): ...@@ -844,11 +844,11 @@ class pronsole(cmd.Cmd):
print "Printing file: "+l.lower()+" from SD card." print "Printing file: "+l.lower()+" from SD card."
print "Requesting SD print..." print "Requesting SD print..."
time.sleep(1) time.sleep(1)
def help_sdprint(self): def help_sdprint(self):
print "Print a file from the SD card. Tabcompletes with available file names." print "Print a file from the SD card. Tabcompletes with available file names."
print "sdprint filename.g" print "sdprint filename.g"
def complete_sdprint(self, text, line, begidx, endidx): def complete_sdprint(self, text, line, begidx, endidx):
if self.sdfiles==[] and self.p.online: if self.sdfiles==[] and self.p.online:
self.listing=2 self.listing=2
...@@ -857,7 +857,7 @@ class pronsole(cmd.Cmd): ...@@ -857,7 +857,7 @@ class pronsole(cmd.Cmd):
time.sleep(0.5) time.sleep(0.5)
if (len(line.split())==2 and line[-1] != " ") or (len(line.split())==1 and line[-1]==" "): if (len(line.split())==2 and line[-1] != " ") or (len(line.split())==1 and line[-1]==" "):
return [i for i in self.sdfiles if i.startswith(text)] return [i for i in self.sdfiles if i.startswith(text)]
def recvcb(self,l): def recvcb(self,l):
if "T:" in l: if "T:" in l:
self.tempreadings=l self.tempreadings=l
...@@ -868,11 +868,11 @@ class pronsole(cmd.Cmd): ...@@ -868,11 +868,11 @@ class pronsole(cmd.Cmd):
sys.stdout.flush() sys.stdout.flush()
for i in self.recvlisteners: for i in self.recvlisteners:
i(l) i(l)
def help_shell(self): def help_shell(self):
print "Executes a python command. Example:" print "Executes a python command. Example:"
print "! os.listdir('.')" print "! os.listdir('.')"
def default(self,l): def default(self,l):
if(l[0] in self.commandprefixes.upper()): if(l[0] in self.commandprefixes.upper()):
if(self.p and self.p.online): if(self.p and self.p.online):
...@@ -890,24 +890,24 @@ class pronsole(cmd.Cmd): ...@@ -890,24 +890,24 @@ class pronsole(cmd.Cmd):
return return
else: else:
cmd.Cmd.default(self,l) cmd.Cmd.default(self,l)
def help_help(self): def help_help(self):
self.do_help("") self.do_help("")
def tempcb(self,l): def tempcb(self,l):
if "T:" in l: if "T:" in l:
print l.replace("\r","").replace("T","Hotend").replace("B","Bed").replace("\n","").replace("ok ","") print l.replace("\r","").replace("T","Hotend").replace("B","Bed").replace("\n","").replace("ok ","")
def do_gettemp(self,l): def do_gettemp(self,l):
if self.p.online: if self.p.online:
self.recvlisteners+=[self.tempcb] self.recvlisteners+=[self.tempcb]
self.p.send_now("M105") self.p.send_now("M105")
time.sleep(0.75) time.sleep(0.75)
self.recvlisteners.remove(self.tempcb) self.recvlisteners.remove(self.tempcb)
def help_gettemp(self): def help_gettemp(self):
print "Read the extruder and bed temperature." print "Read the extruder and bed temperature."
def do_settemp(self,l): def do_settemp(self,l):
try: try:
l=l.lower().replace(",",".") l=l.lower().replace(",",".")
...@@ -924,16 +924,16 @@ class pronsole(cmd.Cmd): ...@@ -924,16 +924,16 @@ class pronsole(cmd.Cmd):
print "You cannot set negative temperatures. To turn the hotend off entirely, set its temperature to 0." print "You cannot set negative temperatures. To turn the hotend off entirely, set its temperature to 0."
except: except:
print "You must enter a temperature." print "You must enter a temperature."
def help_settemp(self): def help_settemp(self):
print "Sets the hotend temperature to the value entered." print "Sets the hotend temperature to the value entered."
print "Enter either a temperature in celsius or one of the following keywords" print "Enter either a temperature in celsius or one of the following keywords"
print ", ".join([i+"("+self.temps[i]+")" for i in self.temps.keys()]) print ", ".join([i+"("+self.temps[i]+")" for i in self.temps.keys()])
def complete_settemp(self, text, line, begidx, endidx): def complete_settemp(self, text, line, begidx, endidx):
if (len(line.split())==2 and line[-1] != " ") or (len(line.split())==1 and line[-1]==" "): if (len(line.split())==2 and line[-1] != " ") or (len(line.split())==1 and line[-1]==" "):
return [i for i in self.temps.keys() if i.startswith(text)] return [i for i in self.temps.keys() if i.startswith(text)]
def do_bedtemp(self,l): def do_bedtemp(self,l):
try: try:
l=l.lower().replace(",",".") l=l.lower().replace(",",".")
...@@ -950,16 +950,16 @@ class pronsole(cmd.Cmd): ...@@ -950,16 +950,16 @@ class pronsole(cmd.Cmd):
print "You cannot set negative temperatures. To turn the bed off entirely, set its temperature to 0." print "You cannot set negative temperatures. To turn the bed off entirely, set its temperature to 0."
except: except:
print "You must enter a temperature." print "You must enter a temperature."
def help_bedtemp(self): def help_bedtemp(self):
print "Sets the bed temperature to the value entered." print "Sets the bed temperature to the value entered."
print "Enter either a temperature in celsius or one of the following keywords" print "Enter either a temperature in celsius or one of the following keywords"
print ", ".join([i+"("+self.bedtemps[i]+")" for i in self.bedtemps.keys()]) print ", ".join([i+"("+self.bedtemps[i]+")" for i in self.bedtemps.keys()])
def complete_bedtemp(self, text, line, begidx, endidx): def complete_bedtemp(self, text, line, begidx, endidx):
if (len(line.split())==2 and line[-1] != " ") or (len(line.split())==1 and line[-1]==" "): if (len(line.split())==2 and line[-1] != " ") or (len(line.split())==1 and line[-1]==" "):
return [i for i in self.bedtemps.keys() if i.startswith(text)] return [i for i in self.bedtemps.keys() if i.startswith(text)]
def do_move(self,l): def do_move(self,l):
if(len(l.split())<2): if(len(l.split())<2):
print "No move specified." print "No move specified."
...@@ -999,14 +999,14 @@ class pronsole(cmd.Cmd): ...@@ -999,14 +999,14 @@ class pronsole(cmd.Cmd):
self.p.send_now("G91") self.p.send_now("G91")
self.p.send_now("G1 "+axis+str(l[1])+" F"+str(feed)) self.p.send_now("G1 "+axis+str(l[1])+" F"+str(feed))
self.p.send_now("G90") self.p.send_now("G90")
def help_move(self): def help_move(self):
print "Move an axis. Specify the name of the axis and the amount. " print "Move an axis. Specify the name of the axis and the amount. "
print "move X 10 will move the X axis forward by 10mm at ",self.settings.xy_feedrate,"mm/min (default XY speed)" print "move X 10 will move the X axis forward by 10mm at ",self.settings.xy_feedrate,"mm/min (default XY speed)"
print "move Y 10 5000 will move the Y axis forward by 10mm at 5000mm/min" print "move Y 10 5000 will move the Y axis forward by 10mm at 5000mm/min"
print "move Z -1 will move the Z axis down by 1mm at ",self.settings.z_feedrate,"mm/min (default Z speed)" print "move Z -1 will move the Z axis down by 1mm at ",self.settings.z_feedrate,"mm/min (default Z speed)"
print "Common amounts are in the tabcomplete list." print "Common amounts are in the tabcomplete list."
def complete_move(self, text, line, begidx, endidx): def complete_move(self, text, line, begidx, endidx):
if (len(line.split())==2 and line[-1] != " ") or (len(line.split())==1 and line[-1]==" "): if (len(line.split())==2 and line[-1] != " ") or (len(line.split())==1 and line[-1]==" "):
return [i for i in ["X ","Y ","Z ","E "] if i.lower().startswith(text)] return [i for i in ["X ","Y ","Z ","E "] if i.lower().startswith(text)]
...@@ -1020,7 +1020,7 @@ class pronsole(cmd.Cmd): ...@@ -1020,7 +1020,7 @@ class pronsole(cmd.Cmd):
return [i[rlen:] for i in ["-100","-10","-1","-0.1","100","10","1","0.1","-50","-5","-0.5","50","5","0.5","-200","-20","-2","-0.2","200","20","2","0.2"] if i.startswith(base)] return [i[rlen:] for i in ["-100","-10","-1","-0.1","100","10","1","0.1","-50","-5","-0.5","50","5","0.5","-200","-20","-2","-0.2","200","20","2","0.2"] if i.startswith(base)]
else: else:
return [] return []
def do_extrude(self,l,override=None,overridefeed=300): def do_extrude(self,l,override=None,overridefeed=300):
length=5#default extrusion length length=5#default extrusion length
feed=self.settings.e_feedrate#default speed feed=self.settings.e_feedrate#default speed
...@@ -1053,14 +1053,14 @@ class pronsole(cmd.Cmd): ...@@ -1053,14 +1053,14 @@ class pronsole(cmd.Cmd):
self.p.send_now("G91") self.p.send_now("G91")
self.p.send_now("G1 E"+str(length)+" F"+str(feed)) self.p.send_now("G1 E"+str(length)+" F"+str(feed))
self.p.send_now("G90") self.p.send_now("G90")
def help_extrude(self): def help_extrude(self):
print "Extrudes a length of filament, 5mm by default, or the number of mm given as a parameter" print "Extrudes a length of filament, 5mm by default, or the number of mm given as a parameter"
print "extrude - extrudes 5mm of filament at 300mm/min (5mm/s)" print "extrude - extrudes 5mm of filament at 300mm/min (5mm/s)"
print "extrude 20 - extrudes 20mm of filament at 300mm/min (5mm/s)" print "extrude 20 - extrudes 20mm of filament at 300mm/min (5mm/s)"
print "extrude -5 - REVERSES 5mm of filament at 300mm/min (5mm/s)" print "extrude -5 - REVERSES 5mm of filament at 300mm/min (5mm/s)"
print "extrude 10 210 - extrudes 10mm of filament at 210mm/min (3.5mm/s)" print "extrude 10 210 - extrudes 10mm of filament at 210mm/min (3.5mm/s)"
def do_reverse(self, l): def do_reverse(self, l):
length=5#default extrusion length length=5#default extrusion length
feed=self.settings.e_feedrate#default speed feed=self.settings.e_feedrate#default speed
...@@ -1082,23 +1082,23 @@ class pronsole(cmd.Cmd): ...@@ -1082,23 +1082,23 @@ class pronsole(cmd.Cmd):
except: except:
print "Invalid speed given." print "Invalid speed given."
self.do_extrude("",length*-1.0,feed) self.do_extrude("",length*-1.0,feed)
def help_reverse(self): def help_reverse(self):
print "Reverses the extruder, 5mm by default, or the number of mm given as a parameter" print "Reverses the extruder, 5mm by default, or the number of mm given as a parameter"
print "reverse - reverses 5mm of filament at 300mm/min (5mm/s)" print "reverse - reverses 5mm of filament at 300mm/min (5mm/s)"
print "reverse 20 - reverses 20mm of filament at 300mm/min (5mm/s)" print "reverse 20 - reverses 20mm of filament at 300mm/min (5mm/s)"
print "reverse 10 210 - extrudes 10mm of filament at 210mm/min (3.5mm/s)" print "reverse 10 210 - extrudes 10mm of filament at 210mm/min (3.5mm/s)"
print "reverse -5 - EXTRUDES 5mm of filament at 300mm/min (5mm/s)" print "reverse -5 - EXTRUDES 5mm of filament at 300mm/min (5mm/s)"
def do_exit(self,l): def do_exit(self,l):
print "Disconnecting from printer..." print "Disconnecting from printer..."
self.p.disconnect() self.p.disconnect()
print "Exiting program. Goodbye!" print "Exiting program. Goodbye!"
return True return True
def help_exit(self): def help_exit(self):
print "Disconnects from the printer and exits the program." print "Disconnects from the printer and exits the program."
def do_monitor(self,l): def do_monitor(self,l):
interval=5 interval=5
if not self.p.online: if not self.p.online:
...@@ -1121,23 +1121,23 @@ class pronsole(cmd.Cmd): ...@@ -1121,23 +1121,23 @@ class pronsole(cmd.Cmd):
#print (self.tempreadings.replace("\r","").replace("T","Hotend").replace("B","Bed").replace("\n","").replace("ok ","")) #print (self.tempreadings.replace("\r","").replace("T","Hotend").replace("B","Bed").replace("\n","").replace("ok ",""))
if(self.p.printing): if(self.p.printing):
print "Print progress: ", 100*float(self.p.queueindex)/len(self.p.mainqueue), "%" print "Print progress: ", 100*float(self.p.queueindex)/len(self.p.mainqueue), "%"
if(self.sdprinting): if(self.sdprinting):
print "SD print progress: ", self.percentdone,"%" print "SD print progress: ", self.percentdone,"%"
except: except:
print "Done monitoring." print "Done monitoring."
pass pass
self.monitoring=0 self.monitoring=0
def help_monitor(self): def help_monitor(self):
print "Monitor a machine's temperatures and an SD print's status." print "Monitor a machine's temperatures and an SD print's status."
print "monitor - Reports temperature and SD print status (if SD printing) every 5 seconds" print "monitor - Reports temperature and SD print status (if SD printing) every 5 seconds"
print "monitor 2 - Reports temperature and SD print status (if SD printing) every 2 seconds" print "monitor 2 - Reports temperature and SD print status (if SD printing) every 2 seconds"
def expandcommand(self,c): def expandcommand(self,c):
return c.replace("$python",sys.executable) return c.replace("$python",sys.executable)
def do_skein(self,l): def do_skein(self,l):
l=l.split() l=l.split()
if len(l)==0: if len(l)==0:
...@@ -1166,7 +1166,7 @@ class pronsole(cmd.Cmd): ...@@ -1166,7 +1166,7 @@ class pronsole(cmd.Cmd):
self.do_load(l[0].replace(".stl","_export.gcode")) self.do_load(l[0].replace(".stl","_export.gcode"))
except Exception,e: except Exception,e:
print "Skeinforge execution failed: ",e print "Skeinforge execution failed: ",e
def complete_skein(self, text, line, begidx, endidx): def complete_skein(self, text, line, begidx, endidx):
s=line.split() s=line.split()
if len(s)>2: if len(s)>2:
...@@ -1176,14 +1176,14 @@ class pronsole(cmd.Cmd): ...@@ -1176,14 +1176,14 @@ class pronsole(cmd.Cmd):
return [i[len(s[1])-len(text):] for i in glob.glob(s[1]+"*/")+glob.glob(s[1]+"*.stl")] return [i[len(s[1])-len(text):] for i in glob.glob(s[1]+"*/")+glob.glob(s[1]+"*.stl")]
else: else:
return glob.glob("*/")+glob.glob("*.stl") return glob.glob("*/")+glob.glob("*.stl")
def help_skein(self): def help_skein(self):
print "Creates a gcode file from an stl model using the slicer (with tab-completion)" print "Creates a gcode file from an stl model using the slicer (with tab-completion)"
print "skein filename.stl - create gcode file" print "skein filename.stl - create gcode file"
print "skein filename.stl view - create gcode file and view using skeiniso" print "skein filename.stl view - create gcode file and view using skeiniso"
print "skein set - adjust slicer settings" print "skein set - adjust slicer settings"
def do_home(self,l): def do_home(self,l):
if not self.p.online: if not self.p.online:
print "Printer is not online. Unable to move." print "Printer is not online. Unable to move."
...@@ -1202,7 +1202,7 @@ class pronsole(cmd.Cmd): ...@@ -1202,7 +1202,7 @@ class pronsole(cmd.Cmd):
if not len(l): if not len(l):
self.p.send_now("G28") self.p.send_now("G28")
self.p.send_now("G92 E0") self.p.send_now("G92 E0")
def help_home(self): def help_home(self):
print "Homes the printer" print "Homes the printer"
print "home - homes all axes and zeroes the extruder(Using G28 and G92)" print "home - homes all axes and zeroes the extruder(Using G28 and G92)"
...@@ -1210,7 +1210,7 @@ class pronsole(cmd.Cmd): ...@@ -1210,7 +1210,7 @@ class pronsole(cmd.Cmd):
print "home z - homes z axis only (Using G28)" print "home z - homes z axis only (Using G28)"
print "home e - set extruder position to zero (Using G92)" print "home e - set extruder position to zero (Using G92)"
print "home xyze - homes all axes and zeroes the extruder (Using G28 and G92)" print "home xyze - homes all axes and zeroes the extruder (Using G28 and G92)"
def parse_cmdline(self,args): def parse_cmdline(self,args):
import getopt import getopt
opts,args = getopt.getopt(args, "c:e:hw", ["conf=","config=","help","web","web-config=", "web-auth-config="]) opts,args = getopt.getopt(args, "c:e:hw", ["conf=","config=","help","web","web-config=", "web-auth-config="])
...@@ -1240,7 +1240,7 @@ class pronsole(cmd.Cmd): ...@@ -1240,7 +1240,7 @@ class pronsole(cmd.Cmd):
self.processing_args = False self.processing_args = False
if __name__=="__main__": if __name__=="__main__":
interp=pronsole() interp=pronsole()
interp.parse_cmdline(sys.argv[1:]) interp.parse_cmdline(sys.argv[1:])
try: try:
...@@ -1248,4 +1248,3 @@ if __name__=="__main__": ...@@ -1248,4 +1248,3 @@ if __name__=="__main__":
except: except:
interp.p.disconnect() interp.p.disconnect()
#raise #raise
...@@ -49,7 +49,7 @@ from printrun.zbuttons import ZButtons ...@@ -49,7 +49,7 @@ from printrun.zbuttons import ZButtons
from printrun.graph import Graph from printrun.graph import Graph
from printrun.printrun_utils import pixmapfile, configfile from printrun.printrun_utils import pixmapfile, configfile
import pronsole import pronsole
def dosify(name): def dosify(name):
return os.path.split(name)[1].split(".")[0][:8]+".g" return os.path.split(name)[1].split(".")[0][:8]+".g"
...@@ -316,7 +316,7 @@ class PronterWindow(wx.Frame,pronsole.pronsole): ...@@ -316,7 +316,7 @@ class PronterWindow(wx.Frame,pronsole.pronsole):
wx.CallAfter(self.settbtn.SetForegroundColour, "") wx.CallAfter(self.settbtn.SetForegroundColour, "")
wx.CallAfter(self.htemp.SetBackgroundColour, "white") wx.CallAfter(self.htemp.SetBackgroundColour, "white")
wx.CallAfter(self.htemp.Refresh) wx.CallAfter(self.htemp.Refresh)
def do_settemp(self, l = ""): def do_settemp(self, l = ""):
try: try:
if not l.__class__ in (str, unicode) or not len(l): if not l.__class__ in (str, unicode) or not len(l):
...@@ -579,7 +579,7 @@ class PronterWindow(wx.Frame,pronsole.pronsole): ...@@ -579,7 +579,7 @@ class PronterWindow(wx.Frame,pronsole.pronsole):
#self.minibtn.Bind(wx.EVT_BUTTON,self.toggleview) #self.minibtn.Bind(wx.EVT_BUTTON,self.toggleview)
#uts.Add((25,-1)) #uts.Add((25,-1))
#uts.Add((15,-1),flag=wx.EXPAND) #uts.Add((15,-1),flag=wx.EXPAND)
#uts.Add(self.minibtn,0,wx.ALIGN_CENTER) #uts.Add(self.minibtn,0,wx.ALIGN_CENTER)
...@@ -642,7 +642,7 @@ class PronterWindow(wx.Frame,pronsole.pronsole): ...@@ -642,7 +642,7 @@ class PronterWindow(wx.Frame,pronsole.pronsole):
#lls.Add((200,375)) #lls.Add((200,375))
szbuttons=wx.GridBagSizer() szbuttons=wx.GridBagSizer()
self.xyb = XYButtons(self.panel, self.moveXY, self.homeButtonClicked, self.spacebarAction, self.settings.bgcolor) self.xyb = XYButtons(self.panel, self.moveXY, self.homeButtonClicked, self.spacebarAction, self.settings.bgcolor)
szbuttons.Add(self.xyb,pos=(0,1),flag=wx.ALIGN_CENTER) szbuttons.Add(self.xyb,pos=(0,1),flag=wx.ALIGN_CENTER)
self.zb = ZButtons(self.panel, self.moveZ, self.settings.bgcolor) self.zb = ZButtons(self.panel, self.moveZ, self.settings.bgcolor)
...@@ -738,7 +738,7 @@ class PronterWindow(wx.Frame,pronsole.pronsole): ...@@ -738,7 +738,7 @@ class PronterWindow(wx.Frame,pronsole.pronsole):
self.btemp.SetValue(i) self.btemp.SetValue(i)
for i in htemp_choices: for i in htemp_choices:
if i.split()[0] == str(self.settings.last_temperature).split('.')[0] or i.split()[0] == str(self.settings.last_temperature) : if i.split()[0] == str(self.settings.last_temperature).split('.')[0] or i.split()[0] == str(self.settings.last_temperature) :
self.htemp.SetValue(i) self.htemp.SetValue(i)
if( '(' not in self.btemp.Value): if( '(' not in self.btemp.Value):
self.btemp.SetValue(self.btemp.Value + ' (user)') self.btemp.SetValue(self.btemp.Value + ' (user)')
...@@ -748,7 +748,7 @@ class PronterWindow(wx.Frame,pronsole.pronsole): ...@@ -748,7 +748,7 @@ class PronterWindow(wx.Frame,pronsole.pronsole):
#lls.Add(self.btemp,pos=(4,1),span=(1,3)) #lls.Add(self.btemp,pos=(4,1),span=(1,3))
#lls.Add(self.setbbtn,pos=(4,4),span=(1,2)) #lls.Add(self.setbbtn,pos=(4,4),span=(1,2))
self.tempdisp=wx.StaticText(self.panel,-1,"") self.tempdisp=wx.StaticText(self.panel,-1,"")
self.edist=wx.SpinCtrl(self.panel,-1,"5",min=0,max=1000,size=(60,-1)) self.edist=wx.SpinCtrl(self.panel,-1,"5",min=0,max=1000,size=(60,-1))
self.edist.SetBackgroundColour((225,200,200)) self.edist.SetBackgroundColour((225,200,200))
self.edist.SetForegroundColour("black") self.edist.SetForegroundColour("black")
...@@ -767,7 +767,7 @@ class PronterWindow(wx.Frame,pronsole.pronsole): ...@@ -767,7 +767,7 @@ class PronterWindow(wx.Frame,pronsole.pronsole):
self.zfeedc.SetBackgroundColour((180,255,180)) self.zfeedc.SetBackgroundColour((180,255,180))
self.zfeedc.SetForegroundColour("black") self.zfeedc.SetForegroundColour("black")
# lls.Add((10,0),pos=(0,11),span=(1,1)) # lls.Add((10,0),pos=(0,11),span=(1,1))
#self.hottgauge=TempGauge(self.panel,size=(200,24),title=_("Heater:"),maxval=230) #self.hottgauge=TempGauge(self.panel,size=(200,24),title=_("Heater:"),maxval=230)
#lls.Add(self.hottgauge,pos=(7,0),span=(1,4)) #lls.Add(self.hottgauge,pos=(7,0),span=(1,4))
#self.bedtgauge=TempGauge(self.panel,size=(200,24),title=_("Bed:"),maxval=130) #self.bedtgauge=TempGauge(self.panel,size=(200,24),title=_("Bed:"),maxval=130)
...@@ -778,11 +778,11 @@ class PronterWindow(wx.Frame,pronsole.pronsole): ...@@ -778,11 +778,11 @@ class PronterWindow(wx.Frame,pronsole.pronsole):
# elif e.GetWheelRotation()<0: # elif e.GetWheelRotation()<0:
# self.do_settemp(str(max(0,self.hsetpoint-1))) # self.do_settemp(str(max(0,self.hsetpoint-1)))
#self.tgauge.Bind(wx.EVT_MOUSEWHEEL,scroll_setpoint) #self.tgauge.Bind(wx.EVT_MOUSEWHEEL,scroll_setpoint)
self.graph = Graph(self.panel, wx.ID_ANY) self.graph = Graph(self.panel, wx.ID_ANY)
lls.Add(self.graph, pos=(3,5), span=(3,3)) lls.Add(self.graph, pos=(3,5), span=(3,3))
lls.Add(self.tempdisp,pos=(6,0),span=(1,1)) lls.Add(self.tempdisp,pos=(6,0),span=(1,1))
self.gviz=gviz.gviz(self.panel,(300,300), self.gviz=gviz.gviz(self.panel,(300,300),
build_dimensions=self.build_dimensions_list, build_dimensions=self.build_dimensions_list,
grid=(self.settings.preview_grid_step1,self.settings.preview_grid_step2), grid=(self.settings.preview_grid_step1,self.settings.preview_grid_step2),
...@@ -845,12 +845,12 @@ class PronterWindow(wx.Frame,pronsole.pronsole): ...@@ -845,12 +845,12 @@ class PronterWindow(wx.Frame,pronsole.pronsole):
self.commandbox.SetSelection(0,len(self.commandbox.history[self.commandbox.histindex])) self.commandbox.SetSelection(0,len(self.commandbox.history[self.commandbox.histindex]))
elif e.GetKeyCode()==wx.WXK_DOWN: elif e.GetKeyCode()==wx.WXK_DOWN:
if self.commandbox.histindex==len(self.commandbox.history): if self.commandbox.histindex==len(self.commandbox.history):
self.commandbox.history+=[self.commandbox.GetValue()] #save current command self.commandbox.history+=[self.commandbox.GetValue()] #save current command
if len(self.commandbox.history): if len(self.commandbox.history):
self.commandbox.histindex=(self.commandbox.histindex+1)%len(self.commandbox.history) self.commandbox.histindex=(self.commandbox.histindex+1)%len(self.commandbox.history)
self.commandbox.SetValue(self.commandbox.history[self.commandbox.histindex]) self.commandbox.SetValue(self.commandbox.history[self.commandbox.histindex])
self.commandbox.SetSelection(0,len(self.commandbox.history[self.commandbox.histindex])) self.commandbox.SetSelection(0,len(self.commandbox.history[self.commandbox.histindex]))
else: else:
e.Skip() e.Skip()
...@@ -957,10 +957,10 @@ class PronterWindow(wx.Frame,pronsole.pronsole): ...@@ -957,10 +957,10 @@ class PronterWindow(wx.Frame,pronsole.pronsole):
b.SetToolTip(wx.ToolTip(_("click to add new custom button"))) b.SetToolTip(wx.ToolTip(_("click to add new custom button")))
b.Bind(wx.EVT_BUTTON,self.cbutton_edit) b.Bind(wx.EVT_BUTTON,self.cbutton_edit)
else: else:
b=wx.Button(self.panel,-1,".",size=(1,1)) b=wx.Button(self.panel,-1,".",size=(1,1))
#b=wx.StaticText(self.panel,-1,"",size=(72,22),style=wx.ALIGN_CENTRE+wx.ST_NO_AUTORESIZE) #+wx.SIMPLE_BORDER #b=wx.StaticText(self.panel,-1,"",size=(72,22),style=wx.ALIGN_CENTRE+wx.ST_NO_AUTORESIZE) #+wx.SIMPLE_BORDER
b.Disable() b.Disable()
#continue #continue
b.custombutton=i b.custombutton=i
b.properties=btndef b.properties=btndef
if btndef is not None: if btndef is not None:
...@@ -984,9 +984,9 @@ class PronterWindow(wx.Frame,pronsole.pronsole): ...@@ -984,9 +984,9 @@ class PronterWindow(wx.Frame,pronsole.pronsole):
def nextarg(rest): def nextarg(rest):
rest=rest.lstrip() rest=rest.lstrip()
if rest.startswith('"'): if rest.startswith('"'):
return rest[1:].split('"',1) return rest[1:].split('"',1)
else: else:
return rest.split(None,1) return rest.split(None,1)
#try: #try:
num,argstr=nextarg(argstr) num,argstr=nextarg(argstr)
num=int(num) num=int(num)
...@@ -1385,7 +1385,7 @@ class PronterWindow(wx.Frame,pronsole.pronsole): ...@@ -1385,7 +1385,7 @@ class PronterWindow(wx.Frame,pronsole.pronsole):
except: except:
break break
wx.CallAfter(self.status.SetStatusText,_("Not connected to printer.")) wx.CallAfter(self.status.SetStatusText,_("Not connected to printer."))
def capture(self, func, *args, **kwargs): def capture(self, func, *args, **kwargs):
stdout=sys.stdout stdout=sys.stdout
cout=None cout=None
...@@ -1518,7 +1518,7 @@ class PronterWindow(wx.Frame,pronsole.pronsole): ...@@ -1518,7 +1518,7 @@ class PronterWindow(wx.Frame,pronsole.pronsole):
self.f=[i.replace("\n","").replace("\r","") for i in of] self.f=[i.replace("\n","").replace("\r","") for i in of]
of.close() of.close()
if self.p.online: if self.p.online:
wx.CallAfter(self.printbtn.Enable) wx.CallAfter(self.printbtn.Enable)
wx.CallAfter(self.status.SetStatusText,_("Loaded ")+self.filename+_(", %d lines") % (len(self.f),)) wx.CallAfter(self.status.SetStatusText,_("Loaded ")+self.filename+_(", %d lines") % (len(self.f),))
wx.CallAfter(self.pausebtn.Disable) wx.CallAfter(self.pausebtn.Disable)
...@@ -1553,7 +1553,7 @@ class PronterWindow(wx.Frame,pronsole.pronsole): ...@@ -1553,7 +1553,7 @@ class PronterWindow(wx.Frame,pronsole.pronsole):
except: except:
pass pass
dlg=wx.FileDialog(self,_("Open file to print"),basedir,style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST) dlg=wx.FileDialog(self,_("Open file to print"),basedir,style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST)
dlg.SetWildcard(_("OBJ, STL, and GCODE files (*.gcode;*.gco;*.g;*.stl;*.STL;*.obj;*.OBJ)|*.gcode;*.gco;*.g;*.stl;*.STL;*.obj;*.OBJ|All Files (*.*)|*.*")) dlg.SetWildcard(_("OBJ, STL, and GCODE files (*.gcode;*.gco;*.g;*.stl;*.STL;*.obj;*.OBJ)|*.gcode;*.gco;*.g;*.stl;*.STL;*.obj;*.OBJ|All Files (*.*)|*.*"))
if(filename is not None or dlg.ShowModal() == wx.ID_OK): if(filename is not None or dlg.ShowModal() == wx.ID_OK):
if filename is not None: if filename is not None:
name=filename name=filename
...@@ -1810,4 +1810,3 @@ if __name__ == '__main__': ...@@ -1810,4 +1810,3 @@ if __name__ == '__main__':
app.MainLoop() app.MainLoop()
except: except:
pass pass
#!/usr/bin/env python #!/usr/bin/env python
# This file is part of the Printrun suite. # This file is part of the Printrun suite.
# #
# Printrun is free software: you can redistribute it and/or modify # Printrun is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or # the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version. # (at your option) any later version.
# #
# Printrun is distributed in the hope that it will be useful, # Printrun is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with Printrun. If not, see <http://www.gnu.org/licenses/>. # along with Printrun. If not, see <http://www.gnu.org/licenses/>.
...@@ -43,7 +43,7 @@ class install (_install): ...@@ -43,7 +43,7 @@ class install (_install):
except: except:
self.warn ("Could not write installed files list %s" % \ self.warn ("Could not write installed files list %s" % \
INSTALLED_FILES) INSTALLED_FILES)
return return
file.write (data) file.write (data)
file.close () file.close ()
...@@ -66,7 +66,7 @@ class uninstall (_install): ...@@ -66,7 +66,7 @@ class uninstall (_install):
except: except:
self.warn ("Could not read installed files list %s" % \ self.warn ("Could not read installed files list %s" % \
INSTALLED_FILES) INSTALLED_FILES)
return return
files = file.readlines () files = file.readlines ()
file.close () file.close ()
prepend = "" prepend = ""
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment