chiark / gitweb /
Add bed temperature control to printer interface. Only show when we get an bed temper...
[cura.git] / Cura / gui / configWizard.py
1 from __future__ import absolute_import\r
2 import __init__\r
3 \r
4 import wx, os, platform, types, webbrowser, threading, time, re\r
5 import wx.wizard\r
6 \r
7 from gui import firmwareInstall\r
8 from util import machineCom\r
9 from util import profile\r
10 \r
11 class InfoPage(wx.wizard.WizardPageSimple):\r
12         def __init__(self, parent, title):\r
13                 wx.wizard.WizardPageSimple.__init__(self, parent)\r
14 \r
15                 sizer = wx.BoxSizer(wx.VERTICAL)\r
16                 self.sizer = sizer\r
17                 self.SetSizer(sizer)\r
18 \r
19                 title = wx.StaticText(self, -1, title)\r
20                 title.SetFont(wx.Font(18, wx.SWISS, wx.NORMAL, wx.BOLD))\r
21                 sizer.Add(title, 0, wx.ALIGN_CENTRE|wx.ALL, 5)\r
22                 sizer.Add(wx.StaticLine(self, -1), 0, wx.EXPAND|wx.ALL, 5)\r
23         \r
24         def AddText(self,info):\r
25                 text = wx.StaticText(self, -1, info)\r
26                 self.GetSizer().Add(text, 0, wx.LEFT|wx.RIGHT, 5)\r
27                 return text\r
28         \r
29         def AddSeperator(self):\r
30                 self.GetSizer().Add(wx.StaticLine(self, -1), 0, wx.EXPAND|wx.ALL, 5)\r
31         \r
32         def AddHiddenSeperator(self):\r
33                 self.AddText('')\r
34         \r
35         def AddRadioButton(self, label, style = 0):\r
36                 radio = wx.RadioButton(self, -1, label, style=style)\r
37                 self.GetSizer().Add(radio, 0, wx.EXPAND|wx.ALL, 5)\r
38                 return radio\r
39         \r
40         def AddButton(self, label):\r
41                 button = wx.Button(self, -1, label)\r
42                 self.GetSizer().Add(button, 0, wx.LEFT, 5)\r
43                 return button\r
44         \r
45         def AddDualButton(self, label1, label2):\r
46                 p = wx.Panel(self)\r
47                 p.SetSizer(wx.BoxSizer(wx.HORIZONTAL))\r
48                 button1 = wx.Button(p, -1, label1)\r
49                 p.GetSizer().Add(button1, 0, wx.RIGHT, 8)\r
50                 button2 = wx.Button(p, -1, label2)\r
51                 p.GetSizer().Add(button2, 0)\r
52                 self.GetSizer().Add(p, 0, wx.LEFT, 5)\r
53                 return button1, button2\r
54         \r
55         def AllowNext(self):\r
56                 return True\r
57         \r
58         def StoreData(self):\r
59                 pass\r
60 \r
61 class FirstInfoPage(InfoPage):\r
62         def __init__(self, parent):\r
63                 super(FirstInfoPage, self).__init__(parent, "First time run wizard")\r
64                 self.AddText('Welcome, and thanks for trying Cura!')\r
65                 self.AddSeperator()\r
66                 self.AddText('This wizard will help you with the following steps:')\r
67                 self.AddText('* Configure Cura for your machine')\r
68                 self.AddText('* Upgrade your firmware')\r
69                 self.AddText('* Calibrate your machine')\r
70                 #self.AddText('* Do your first print')\r
71 \r
72 class RepRapInfoPage(InfoPage):\r
73         def __init__(self, parent):\r
74                 super(RepRapInfoPage, self).__init__(parent, "RepRap information")\r
75                 self.AddText('Sorry, but this wizard will not help you with\nconfiguring and calibrating your RepRap.')\r
76                 self.AddSeperator()\r
77                 self.AddText('You will have to manually install Marlin or Sprinter firmware\nand configure Cura.')\r
78 \r
79 class MachineSelectPage(InfoPage):\r
80         def __init__(self, parent):\r
81                 super(MachineSelectPage, self).__init__(parent, "Select your machine")\r
82                 self.AddText('What kind of machine do you have:')\r
83 \r
84                 self.UltimakerRadio = self.AddRadioButton("Ultimaker", style=wx.RB_GROUP)\r
85                 self.UltimakerRadio.SetValue(True)\r
86                 self.UltimakerRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimakerSelect)\r
87                 self.OtherRadio = self.AddRadioButton("Other (Ex: RepRap)")\r
88                 self.OtherRadio.Bind(wx.EVT_RADIOBUTTON, self.OnOtherSelect)\r
89                 \r
90         def OnUltimakerSelect(self, e):\r
91                 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().ultimakerFirmwareUpgradePage)\r
92                 \r
93         def OnOtherSelect(self, e):\r
94                 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().repRapInfoPage)\r
95         \r
96         def StoreData(self):\r
97                 if self.UltimakerRadio.GetValue():\r
98                         profile.putPreference('machine_width', '205')\r
99                         profile.putPreference('machine_depth', '205')\r
100                         profile.putPreference('machine_height', '200')\r
101                         profile.putProfileSetting('nozzle_size', '0.4')\r
102                         profile.putProfileSetting('machine_center_x', '100')\r
103                         profile.putProfileSetting('machine_center_y', '100')\r
104                 else:\r
105                         profile.putPreference('machine_width', '80')\r
106                         profile.putPreference('machine_depth', '80')\r
107                         profile.putPreference('machine_height', '60')\r
108                         profile.putProfileSetting('nozzle_size', '0.5')\r
109                         profile.putProfileSetting('machine_center_x', '40')\r
110                         profile.putProfileSetting('machine_center_y', '40')\r
111                 profile.putProfileSetting('wall_thickness', float(profile.getProfileSetting('nozzle_size')) * 2)\r
112 \r
113 class FirmwareUpgradePage(InfoPage):\r
114         def __init__(self, parent):\r
115                 super(FirmwareUpgradePage, self).__init__(parent, "Upgrade Ultimaker Firmware")\r
116                 self.AddText('Firmware is the piece of software running directly on your 3D printer.\nThis firmware controls the step motors, regulates the temperature\nand ultimately makes your printer work.')\r
117                 self.AddHiddenSeperator()\r
118                 self.AddText('The firmware shipping with new Ultimakers works, but upgrades\nhave been made to make better prints, and make calibration easier.')\r
119                 self.AddHiddenSeperator()\r
120                 self.AddText('Cura requires these new features and thus\nyour firmware will most likely need to be upgraded.\nYou will get the chance to do so now.')\r
121                 upgradeButton, skipUpgradeButton = self.AddDualButton('Upgrade to Marlin firmware', 'Skip upgrade')\r
122                 upgradeButton.Bind(wx.EVT_BUTTON, self.OnUpgradeClick)\r
123                 skipUpgradeButton.Bind(wx.EVT_BUTTON, self.OnSkipClick)\r
124                 self.AddHiddenSeperator()\r
125                 self.AddText('Do not upgrade to this firmware if:')\r
126                 self.AddText('* You have an older machine based on ATMega1280')\r
127                 self.AddText('* Using an LCD panel')\r
128                 self.AddText('* Have other changes in the firmware')\r
129                 button = self.AddButton('Goto this page for a custom firmware')\r
130                 button.Bind(wx.EVT_BUTTON, self.OnUrlClick)\r
131         \r
132         def AllowNext(self):\r
133                 return False\r
134         \r
135         def OnUpgradeClick(self, e):\r
136                 if firmwareInstall.InstallFirmware(os.path.join(os.path.dirname(os.path.abspath(__file__)), "../firmware/default.hex")):\r
137                         self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()\r
138                 \r
139         def OnSkipClick(self, e):\r
140                 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()\r
141         \r
142         def OnUrlClick(self, e):\r
143                 webbrowser.open('http://daid.mine.nu/~daid/marlin_build/')\r
144 \r
145 class UltimakerCheckupPage(InfoPage):\r
146         def __init__(self, parent):\r
147                 super(UltimakerCheckupPage, self).__init__(parent, "Ultimaker Checkup")\r
148                 self.AddText('It is a good idea to do a few sanity checks now on your Ultimaker.\nYou can skip these if you know your machine is functional.')\r
149                 b1, b2 = self.AddDualButton('Run checks', 'Skip checks')\r
150                 b1.Bind(wx.EVT_BUTTON, self.OnCheckClick)\r
151                 b2.Bind(wx.EVT_BUTTON, self.OnSkipClick)\r
152                 self.AddSeperator();\r
153                 self.checkPanel = None\r
154         \r
155         def AllowNext(self):\r
156                 return False\r
157         \r
158         def OnSkipClick(self, e):\r
159                 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()\r
160         \r
161         def OnCheckClick(self, e):\r
162                 if self.checkPanel != None:\r
163                         self.checkPanel.Destroy()\r
164                 self.checkPanel = wx.Panel(self)\r
165                 self.checkPanel.SetSizer(wx.BoxSizer(wx.VERTICAL))\r
166                 self.GetSizer().Add(self.checkPanel, 0, wx.LEFT|wx.RIGHT, 5)\r
167                 threading.Thread(target=self.OnRun).start()\r
168 \r
169         def AddProgressText(self, info):\r
170                 text = wx.StaticText(self.checkPanel, -1, info)\r
171                 self.checkPanel.GetSizer().Add(text, 0)\r
172                 self.checkPanel.Layout()\r
173                 self.Layout()\r
174         \r
175         def OnRun(self):\r
176                 wx.CallAfter(self.AddProgressText, "Connecting to machine...")\r
177                 self.comm = machineCom.MachineCom()\r
178                 \r
179                 if not self.comm.isOpen():\r
180                         wx.CallAfter(self.AddProgressText, "Error: Failed to open serial port to machine")\r
181                         wx.CallAfter(self.AddProgressText, "If this keeps happening, try disconnecting and reconnecting the USB cable")\r
182                         return\r
183 \r
184                 wx.CallAfter(self.AddProgressText, "Checking start message...")\r
185                 if self.DoCommCommandWithTimeout(None, 'start') == False:\r
186                         wx.CallAfter(self.AddProgressText, "Error: Missing start message.")\r
187                         self.comm.close()\r
188                         return\r
189                 \r
190                 #Wait 3 seconds for the SD card init to timeout if we have SD in our firmware but there is no SD card found.\r
191                 time.sleep(3)\r
192                 \r
193                 wx.CallAfter(self.AddProgressText, "Disabling step motors...")\r
194                 if self.DoCommCommandWithTimeout('M84') == False:\r
195                         wx.CallAfter(self.AddProgressText, "Error: Missing reply to Deactivate steppers (M84).")\r
196                         self.comm.close()\r
197                         return\r
198 \r
199                 if self.DoCommCommandWithTimeout("M104 S0") == False:\r
200                         wx.CallAfter(self.AddProgressText, "Failed to set temperature")\r
201                         self.comm.close()\r
202                         return\r
203 \r
204                 wx.MessageBox('Please move the printer head to the center of the machine\nalso move the platform so it is not at the highest or lowest position,\nand make sure the machine is powered on.', 'Machine check', wx.OK | wx.ICON_INFORMATION)\r
205                 \r
206                 idleTemp = self.readTemp()\r
207                 if idleTemp > 40:\r
208                         wx.CallAfter(self.AddProgressText, "Waiting for head to cool down before temperature test...")\r
209                         while idleTemp > 40:\r
210                                 idleTemp = self.readTemp()\r
211                                 time.sleep(1)\r
212                 \r
213                 wx.CallAfter(self.AddProgressText, "Checking heater and temperature sensor...")\r
214                 wx.CallAfter(self.AddProgressText, "(This takes about 30 seconds)")\r
215                 if self.DoCommCommandWithTimeout("M104 S100") == False:\r
216                         wx.CallAfter(self.AddProgressText, "Failed to set temperature")\r
217                         self.comm.close()\r
218                         return\r
219                 \r
220                 time.sleep(25)\r
221                 tempInc = self.readTemp() - idleTemp\r
222                 \r
223                 if self.DoCommCommandWithTimeout("M104 S0") == False:\r
224                         wx.CallAfter(self.AddProgressText, "Failed to set temperature")\r
225                         self.comm.close()\r
226                         return\r
227                 \r
228                 if tempInc < 15:\r
229                         wx.CallAfter(self.AddProgressText, "Your temperature sensor or heater is not working!")\r
230                         self.comm.close()\r
231                         return\r
232                 wx.CallAfter(self.AddProgressText, "Heater and temperature sensor working\nWarning: head might still be hot!")\r
233 \r
234                 wx.CallAfter(self.AddProgressText, "Checking endstops")\r
235                 if self.DoCommCommandWithTimeout('M119', 'x_min') != "x_min:L x_max:L y_min:L y_max:L z_min:L z_max:L":\r
236                         wx.CallAfter(self.AddProgressText, "Error: There is a problem in your endstops!\nOne of them seems to be pressed while it shouldn't\ncheck the cable connections and the switches themselfs.")\r
237                         self.comm.close()\r
238                         return\r
239                 wx.CallAfter(self.AddProgressText, "Please press the X end switch in the front left corner.")\r
240                 if not self.DoCommCommandAndWaitForReply('M119', 'x_min', "x_min:H x_max:L y_min:L y_max:L z_min:L z_max:L"):\r
241                         wx.CallAfter(self.AddProgressText, "Failed to check the x_min endstop!")\r
242                         self.comm.close()\r
243                         return\r
244                 wx.CallAfter(self.AddProgressText, "Please press the X end switch in the front right corner.")\r
245                 if not self.DoCommCommandAndWaitForReply('M119', 'x_min', "x_min:L x_max:H y_min:L y_max:L z_min:L z_max:L"):\r
246                         wx.CallAfter(self.AddProgressText, "Failed to check the x_max endstop!")\r
247                         self.comm.close()\r
248                         return\r
249                 wx.CallAfter(self.AddProgressText, "Please press the Y end switch in the front left corner.")\r
250                 if not self.DoCommCommandAndWaitForReply('M119', 'x_min', "x_min:L x_max:L y_min:H y_max:L z_min:L z_max:L"):\r
251                         wx.CallAfter(self.AddProgressText, "Failed to check the x_max endstop!")\r
252                         self.comm.close()\r
253                         return\r
254                 wx.CallAfter(self.AddProgressText, "Please press the Y end switch in the back left corner.")\r
255                 if not self.DoCommCommandAndWaitForReply('M119', 'x_min', "x_min:L x_max:L y_min:L y_max:H z_min:L z_max:L"):\r
256                         wx.CallAfter(self.AddProgressText, "Failed to check the x_max endstop!")\r
257                         self.comm.close()\r
258                         return\r
259                 wx.CallAfter(self.AddProgressText, "Please press the Z end switch in the top.")\r
260                 if not self.DoCommCommandAndWaitForReply('M119', 'x_min', "x_min:L x_max:L y_min:L y_max:L z_min:H z_max:L"):\r
261                         wx.CallAfter(self.AddProgressText, "Failed to check the x_max endstop!")\r
262                         self.comm.close()\r
263                         return\r
264                 wx.CallAfter(self.AddProgressText, "Please press the Z end switch in the bottom.")\r
265                 if not self.DoCommCommandAndWaitForReply('M119', 'x_min', "x_min:L x_max:L y_min:L y_max:L z_min:L z_max:H"):\r
266                         wx.CallAfter(self.AddProgressText, "Failed to check the x_max endstop!")\r
267                         self.comm.close()\r
268                         return\r
269                 wx.CallAfter(self.AddProgressText, "End stops are working.")\r
270 \r
271                 wx.CallAfter(self.AddProgressText, "Done!")\r
272                 wx.CallAfter(self.GetParent().FindWindowById(wx.ID_FORWARD).Enable)\r
273                 self.comm.close()\r
274                 \r
275         def readTemp(self):\r
276                 line = self.DoCommCommandWithTimeout("M105", "ok T:")\r
277                 if line == False:\r
278                         return -1\r
279                 return int(re.search('T:([0-9]*)', line).group(1))\r
280         \r
281         def DoCommCommandAndWaitForReply(self, cmd, replyStart, reply):\r
282                 while True:\r
283                         ret = self.DoCommCommandWithTimeout(cmd, replyStart)\r
284                         if ret == reply:\r
285                                 return True\r
286                         if ret == False:\r
287                                 return False\r
288                         time.sleep(1)\r
289         \r
290         def DoCommCommandWithTimeout(self, cmd = None, replyStart = 'ok'):\r
291                 if cmd != None:\r
292                         self.comm.sendCommand(cmd)\r
293                 t = threading.Timer(5, self.OnSerialTimeout)\r
294                 t.start()\r
295                 while True:\r
296                         line = self.comm.readline()\r
297                         if line == '' or line == None:\r
298                                 self.comm.close()\r
299                                 return False\r
300                         print line.rstrip()\r
301                         if line.startswith(replyStart):\r
302                                 break\r
303                 t.cancel()\r
304                 return line.rstrip()\r
305         \r
306         def OnSerialTimeout(self):\r
307                 self.comm.close()\r
308 \r
309 class UltimakerCalibrationPage(InfoPage):\r
310         def __init__(self, parent):\r
311                 super(UltimakerCalibrationPage, self).__init__(parent, "Ultimaker Calibration")\r
312                 \r
313                 self.AddText("Your Ultimaker requires some calibration.");\r
314                 self.AddText("This calibration is needed for a proper extrusion amount.");\r
315                 self.AddSeperator()\r
316                 self.AddText("The following values are needed:");\r
317                 self.AddText("* Diameter of filament");\r
318                 self.AddText("* Number of steps per mm of filament extrusion");\r
319                 self.AddSeperator()\r
320                 self.AddText("The better you have calibrated these values, the better your prints\nwill become.");\r
321                 self.AddSeperator()\r
322                 self.AddText("First we need the diameter of your filament:");\r
323                 self.filamentDiameter = wx.TextCtrl(self, -1, profile.getProfileSetting('filament_diameter'))\r
324                 self.GetSizer().Add(self.filamentDiameter, 0, wx.LEFT, 5)\r
325                 self.AddText("If you do not own digital Calipers that can measure\nat least 2 digits then use 2.89mm.\nWhich is the average diameter of most filament.");\r
326                 self.AddText("Note: This value can be changed later at any time.");\r
327 \r
328         def StoreData(self):\r
329                 profile.putProfileSetting('filament_diameter', self.filamentDiameter.GetValue())\r
330 \r
331 class UltimakerCalibrateStepsPerEPage(InfoPage):\r
332         def __init__(self, parent):\r
333                 super(UltimakerCalibrateStepsPerEPage, self).__init__(parent, "Ultimaker Calibration")\r
334 \r
335                 if profile.getPreference('steps_per_e') == '0':\r
336                         profile.putPreference('steps_per_e', '865.888')\r
337                 \r
338                 self.AddText("Calibrating the Steps Per E requires some manual actions.")\r
339                 self.AddText("First remove any filament from your machine.")\r
340                 self.AddText("Next put in your filament so the tip is aligned with the\ntop of the extruder drive.")\r
341                 self.AddText("We'll push the filament 100mm")\r
342                 self.extrudeButton = self.AddButton("Extrude 100mm filament")\r
343                 self.AddText("Now measure the amount of extruded filament:\n(this can be more or less then 100mm)")\r
344                 p = wx.Panel(self)\r
345                 p.SetSizer(wx.BoxSizer(wx.HORIZONTAL))\r
346                 self.lengthInput = wx.TextCtrl(p, -1, '100')\r
347                 p.GetSizer().Add(self.lengthInput, 0, wx.RIGHT, 8)\r
348                 self.saveLengthButton = wx.Button(p, -1, 'Save')\r
349                 p.GetSizer().Add(self.saveLengthButton, 0)\r
350                 self.GetSizer().Add(p, 0, wx.LEFT, 5)\r
351                 self.AddText("This results in the following steps per E:")\r
352                 self.stepsPerEInput = wx.TextCtrl(self, -1, profile.getPreference('steps_per_e'))\r
353                 self.GetSizer().Add(self.stepsPerEInput, 0, wx.LEFT, 5)\r
354                 self.AddText("You can repeat these steps to get better calibration.")\r
355                 self.AddSeperator()\r
356                 self.AddText("If you still have filament in your printer which needs\nheat to remove, press the heat up button below:")\r
357                 self.heatButton = self.AddButton("Heatup for filament removal")\r
358                 \r
359                 self.saveLengthButton.Bind(wx.EVT_BUTTON, self.OnSaveLengthClick)\r
360                 self.extrudeButton.Bind(wx.EVT_BUTTON, self.OnExtrudeClick)\r
361                 self.heatButton.Bind(wx.EVT_BUTTON, self.OnHeatClick)\r
362         \r
363         def OnSaveLengthClick(self, e):\r
364                 currentEValue = float(self.stepsPerEInput.GetValue())\r
365                 realExtrudeLength = float(self.lengthInput.GetValue())\r
366                 newEValue = currentEValue * 100 / realExtrudeLength\r
367                 self.stepsPerEInput.SetValue(str(newEValue))\r
368                 self.lengthInput.SetValue("100")\r
369         \r
370         def OnExtrudeClick(self, e):\r
371                 threading.Thread(target=self.OnExtrudeRun).start()\r
372 \r
373         def OnExtrudeRun(self):\r
374                 self.heatButton.Enable(False)\r
375                 self.extrudeButton.Enable(False)\r
376                 currentEValue = float(self.stepsPerEInput.GetValue())\r
377                 self.comm = machineCom.MachineCom()\r
378                 if not self.comm.isOpen():\r
379                         wx.MessageBox("Error: Failed to open serial port to machine\nIf this keeps happening, try disconnecting and reconnecting the USB cable", 'Printer error', wx.OK | wx.ICON_INFORMATION)\r
380                         self.heatButton.Enable(True)\r
381                         self.extrudeButton.Enable(True)\r
382                         return\r
383                 while True:\r
384                         line = self.comm.readline()\r
385                         if line == '':\r
386                                 return\r
387                         if line.startswith('start'):\r
388                                 break\r
389                 #Wait 3 seconds for the SD card init to timeout if we have SD in our firmware but there is no SD card found.\r
390                 time.sleep(3)\r
391                 \r
392                 self.sendGCommand('M302') #Disable cold extrusion protection\r
393                 self.sendGCommand("M92 E%f" % (currentEValue));\r
394                 self.sendGCommand("G92 E0");\r
395                 self.sendGCommand("G1 E100 F600");\r
396                 time.sleep(15)\r
397                 self.comm.close()\r
398                 self.extrudeButton.Enable()\r
399                 self.heatButton.Enable()\r
400 \r
401         def OnHeatClick(self, e):\r
402                 threading.Thread(target=self.OnHeatRun).start()\r
403         \r
404         def OnHeatRun(self):\r
405                 self.heatButton.Enable(False)\r
406                 self.extrudeButton.Enable(False)\r
407                 self.comm = machineCom.MachineCom()\r
408                 if not self.comm.isOpen():\r
409                         wx.MessageBox("Error: Failed to open serial port to machine\nIf this keeps happening, try disconnecting and reconnecting the USB cable", 'Printer error', wx.OK | wx.ICON_INFORMATION)\r
410                         self.heatButton.Enable(True)\r
411                         self.extrudeButton.Enable(True)\r
412                         return\r
413                 while True:\r
414                         line = self.comm.readline()\r
415                         if line == '':\r
416                                 self.heatButton.Enable(True)\r
417                                 self.extrudeButton.Enable(True)\r
418                                 return\r
419                         if line.startswith('start'):\r
420                                 break\r
421                 #Wait 3 seconds for the SD card init to timeout if we have SD in our firmware but there is no SD card found.\r
422                 time.sleep(3)\r
423                 \r
424                 self.sendGCommand('M104 S200') #Set the temperature to 200C, should be enough to get PLA and ABS out.\r
425                 wx.MessageBox('Wait till you can remove the filament from the machine, and press OK.\n(Temperature is set to 200C)', 'Machine heatup', wx.OK | wx.ICON_INFORMATION)\r
426                 self.sendGCommand('M104 S0')\r
427                 time.sleep(1)\r
428                 self.comm.close()\r
429                 self.heatButton.Enable(True)\r
430                 self.extrudeButton.Enable(True)\r
431         \r
432         def sendGCommand(self, cmd):\r
433                 self.comm.sendCommand(cmd) #Disable cold extrusion protection\r
434                 while True:\r
435                         line = self.comm.readline()\r
436                         if line == '':\r
437                                 return\r
438                         if line.startswith('ok'):\r
439                                 break\r
440         \r
441         def StoreData(self):\r
442                 profile.putPreference('steps_per_e', self.stepsPerEInput.GetValue())\r
443 \r
444 class configWizard(wx.wizard.Wizard):\r
445         def __init__(self):\r
446                 super(configWizard, self).__init__(None, -1, "Configuration Wizard")\r
447                 \r
448                 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)\r
449                 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)\r
450 \r
451                 self.firstInfoPage = FirstInfoPage(self)\r
452                 self.machineSelectPage = MachineSelectPage(self)\r
453                 self.ultimakerFirmwareUpgradePage = FirmwareUpgradePage(self)\r
454                 self.ultimakerCheckupPage = UltimakerCheckupPage(self)\r
455                 self.ultimakerCalibrationPage = UltimakerCalibrationPage(self)\r
456                 self.ultimakerCalibrateStepsPerEPage = UltimakerCalibrateStepsPerEPage(self)\r
457                 self.repRapInfoPage = RepRapInfoPage(self)\r
458 \r
459                 wx.wizard.WizardPageSimple.Chain(self.firstInfoPage, self.machineSelectPage)\r
460                 wx.wizard.WizardPageSimple.Chain(self.machineSelectPage, self.ultimakerFirmwareUpgradePage)\r
461                 wx.wizard.WizardPageSimple.Chain(self.ultimakerFirmwareUpgradePage, self.ultimakerCheckupPage)\r
462                 wx.wizard.WizardPageSimple.Chain(self.ultimakerCheckupPage, self.ultimakerCalibrationPage)\r
463                 wx.wizard.WizardPageSimple.Chain(self.ultimakerCalibrationPage, self.ultimakerCalibrateStepsPerEPage)\r
464                 \r
465                 self.FitToPage(self.firstInfoPage)\r
466                 self.GetPageAreaSizer().Add(self.firstInfoPage)\r
467                 \r
468                 self.RunWizard(self.firstInfoPage)\r
469                 self.Destroy()\r
470 \r
471         def OnPageChanging(self, e):\r
472                 e.GetPage().StoreData()\r
473 \r
474         def OnPageChanged(self, e):\r
475                 if e.GetPage().AllowNext():\r
476                         self.FindWindowById(wx.ID_FORWARD).Enable() \r
477                 else:\r
478                         self.FindWindowById(wx.ID_FORWARD).Disable() \r
479                 self.FindWindowById(wx.ID_BACKWARD).Disable() \r