chiark / gitweb /
Merge commit '96d014b2c4cef94dbbe4c3adc1c8d7a8ce929ad2'
[cura.git] / Cura / gui / printWindow.py
1 from __future__ import absolute_import\r
2 import __init__\r
3 \r
4 import wx, threading\r
5 \r
6 from gui import machineCom\r
7 from gui import icon\r
8 from util import gcodeInterpreter\r
9 \r
10 printWindowHandle = None\r
11 \r
12 def printFile(filename):\r
13         global printWindowHandle\r
14         if printWindowHandle == None:\r
15                 printWindowHandle = printWindow()\r
16                 printWindowHandle.OnConnect(None)\r
17         printWindowHandle.Show(True)\r
18         printWindowHandle.Raise()\r
19         printWindowHandle.LoadGCodeFile(filename)\r
20 \r
21 class printWindow(wx.Frame):\r
22         "Main user interface window"\r
23         def __init__(self):\r
24                 super(printWindow, self).__init__(None, -1, title='Printing')\r
25                 self.machineCom = None\r
26                 self.machineConnected = False\r
27                 self.thread = None\r
28                 self.gcode = None\r
29                 self.gcodeList = None\r
30                 self.printIdx = None\r
31                 self.bufferLineCount = 4\r
32                 self.sendCnt = 0\r
33 \r
34                 #self.SetIcon(icon.getMainIcon())\r
35                 \r
36                 self.SetSizer(wx.BoxSizer())\r
37                 self.panel = wx.Panel(self)\r
38                 self.GetSizer().Add(self.panel, 1, flag=wx.EXPAND)\r
39                 self.sizer = wx.GridBagSizer(2, 2)\r
40                 self.panel.SetSizer(self.sizer)\r
41                 \r
42                 sb = wx.StaticBox(self.panel, label="Statistics")\r
43                 boxsizer = wx.StaticBoxSizer(sb, wx.VERTICAL)\r
44                 self.statsText = wx.StaticText(self.panel, -1, "Filament: ####.##m #.##g\nPrint time: #####:##")\r
45                 boxsizer.Add(self.statsText, flag=wx.LEFT, border=5)\r
46                 \r
47                 self.sizer.Add(boxsizer, pos=(0,0), span=(4,1), flag=wx.EXPAND)\r
48                 \r
49                 self.connectButton = wx.Button(self.panel, -1, 'Connect')\r
50                 #self.loadButton = wx.Button(self.panel, -1, 'Load GCode')\r
51                 self.printButton = wx.Button(self.panel, -1, 'Print GCode')\r
52                 self.cancelButton = wx.Button(self.panel, -1, 'Cancel print')\r
53                 self.progress = wx.Gauge(self.panel, -1)\r
54                 self.sizer.Add(self.connectButton, pos=(0,1))\r
55                 #self.sizer.Add(self.loadButton, pos=(1,1))\r
56                 self.sizer.Add(self.printButton, pos=(2,1))\r
57                 self.sizer.Add(self.cancelButton, pos=(3,1))\r
58                 self.sizer.Add(self.progress, pos=(4,0), span=(1,2), flag=wx.EXPAND)\r
59                 self.sizer.AddGrowableRow(3)\r
60                 self.sizer.AddGrowableCol(0)\r
61                 \r
62                 self.Bind(wx.EVT_CLOSE, self.OnClose)\r
63                 self.connectButton.Bind(wx.EVT_BUTTON, self.OnConnect)\r
64                 #self.loadButton.Bind(wx.EVT_BUTTON, self.OnLoad)\r
65                 self.printButton.Bind(wx.EVT_BUTTON, self.OnPrint)\r
66                 self.cancelButton.Bind(wx.EVT_BUTTON, self.OnCancel)\r
67                 \r
68                 self.Layout()\r
69                 self.Fit()\r
70                 self.Centre()\r
71                 \r
72                 self.UpdateButtonStates()\r
73                 self.UpdateProgress()\r
74         \r
75         def UpdateButtonStates(self):\r
76                 self.connectButton.Enable(not self.machineConnected)\r
77                 #self.loadButton.Enable(self.printIdx == None)\r
78                 self.printButton.Enable(self.machineConnected and self.gcodeList != None and self.printIdx == None)\r
79                 self.cancelButton.Enable(self.printIdx != None)\r
80         \r
81         def UpdateProgress(self):\r
82                 status = ""\r
83                 if self.gcode != None:\r
84                         status += "Filament: %.2fm %.2fg\n" % (self.gcode.extrusionAmount / 1000, self.gcode.calculateWeight() * 1000)\r
85                         status += "Print time: %02d:%02d\n" % (int(self.gcode.totalMoveTimeMinute / 60), int(self.gcode.totalMoveTimeMinute % 60))\r
86                 if self.printIdx == None:\r
87                         self.progress.SetValue(0)\r
88                         if self.gcodeList != None:\r
89                                 status += 'Line: -/%d\n' % (len(self.gcodeList))\r
90                 else:\r
91                         self.progress.SetValue(self.printIdx)\r
92                         status += 'Line: %d/%d\n' % (self.printIdx, len(self.gcodeList))\r
93                 self.statsText.SetLabel(status)\r
94         \r
95         def OnConnect(self, e):\r
96                 if self.machineCom != None:\r
97                         self.machineCom.close()\r
98                         self.thread.join()\r
99                 self.machineCom = machineCom.MachineCom()\r
100                 self.thread = threading.Thread(target=self.PrinterMonitor)\r
101                 self.thread.start()\r
102                 self.UpdateButtonStates()\r
103         \r
104         def OnLoad(self, e):\r
105                 pass\r
106         \r
107         def OnPrint(self, e):\r
108                 if not self.machineConnected:\r
109                         return\r
110                 if self.gcodeList == None:\r
111                         return\r
112                 if self.printIdx != None:\r
113                         return\r
114                 self.printIdx = 1\r
115                 self.sendLine(0)\r
116                 self.sendCnt = self.bufferLineCount\r
117                 self.UpdateButtonStates()\r
118         \r
119         def OnCancel(self, e):\r
120                 self.printIdx = None\r
121                 self.UpdateButtonStates()\r
122         \r
123         def OnClose(self, e):\r
124                 global printWindowHandle\r
125                 printWindowHandle = None\r
126                 if self.machineCom != None:\r
127                         self.machineCom.close()\r
128                         self.thread.join()\r
129                 self.Destroy()\r
130 \r
131         def LoadGCodeFile(self, filename):\r
132                 if self.printIdx != None:\r
133                         return\r
134                 gcodeList = ["M110"]\r
135                 for line in open(filename, 'r'):\r
136                         if ';' in line:\r
137                                 line = line[0:line.find(';')]\r
138                         line = line.strip()\r
139                         if len(line) > 0:\r
140                                 gcodeList.append(line)\r
141                 gcode = gcodeInterpreter.gcode()\r
142                 gcode.loadList(gcodeList)\r
143                 print "Loaded: %s (%d)" % (filename, len(gcodeList))\r
144                 self.progress.SetRange(len(gcodeList))\r
145                 self.gcode = gcode\r
146                 self.gcodeList = gcodeList\r
147                 self.UpdateButtonStates()\r
148                 self.UpdateProgress()\r
149 \r
150         def sendLine(self, lineNr):\r
151                 if lineNr >= len(self.gcodeList):\r
152                         return False\r
153                 checksum = reduce(lambda x,y:x^y, map(ord, "N%d%s" % (lineNr, self.gcodeList[lineNr])))\r
154                 self.machineCom.sendCommand("N%d%s*%d" % (lineNr, self.gcodeList[lineNr], checksum))\r
155                 return True\r
156 \r
157         def PrinterMonitor(self):\r
158                 skipCount = 0\r
159                 while True:\r
160                         line = self.machineCom.readline()\r
161                         if line == None:\r
162                                 self.machineConnected = False\r
163                                 wx.CallAfter(self.UpdateButtonStates)\r
164                                 return\r
165                         if self.machineConnected:\r
166                                 while self.sendCnt > 0:\r
167                                         self.sendLine(self.printIdx)\r
168                                         self.printIdx += 1\r
169                                         self.sendCnt -= 1\r
170                         elif line.startswith("start"):\r
171                                 self.machineConnected = True\r
172                                 wx.CallAfter(self.UpdateButtonStates)\r
173                         if self.printIdx != None:\r
174                                 if line.startswith("ok"):\r
175                                         if skipCount > 0:\r
176                                                 skipCount -= 1\r
177                                         else:\r
178                                                 if self.sendLine(self.printIdx):\r
179                                                         self.printIdx += 1\r
180                                                 else:\r
181                                                         self.printIdx = None\r
182                                                         wx.CallAfter(self.UpdateButtonStates)\r
183                                                 wx.CallAfter(self.UpdateProgress)\r
184                                 elif "resend" in line.lower() or "rs" in line:\r
185                                         try:\r
186                                                 lineNr=int(line.replace("N:"," ").replace("N"," ").replace(":"," ").split()[-1])\r
187                                         except:\r
188                                                 if "rs" in line:\r
189                                                         lineNr=int(line.split()[1])\r
190                                         self.printIdx = lineNr\r
191                                         #we should actually resend the line here, but we also get an "ok" for each error from Marlin. And thus we'll resend on the OK.\r
192 \r