1 __copyright__ = "Copyright (C) 2013 David Braam - Released under terms of the AGPLv3 License"
12 from Cura.gui import firmwareInstall
13 from Cura.gui import printWindow
14 from Cura.util import machineCom
15 from Cura.util import profile
16 from Cura.util import gcodeGenerator
17 from Cura.util import resources
20 class InfoBox(wx.Panel):
21 def __init__(self, parent):
22 super(InfoBox, self).__init__(parent)
23 self.SetBackgroundColour('#FFFF80')
25 self.sizer = wx.GridBagSizer(5, 5)
26 self.SetSizer(self.sizer)
28 self.attentionBitmap = wx.Bitmap(resources.getPathForImage('attention.png'))
29 self.errorBitmap = wx.Bitmap(resources.getPathForImage('error.png'))
30 self.readyBitmap = wx.Bitmap(resources.getPathForImage('ready.png'))
32 wx.Bitmap(resources.getPathForImage('busy-0.png')),
33 wx.Bitmap(resources.getPathForImage('busy-1.png')),
34 wx.Bitmap(resources.getPathForImage('busy-2.png')),
35 wx.Bitmap(resources.getPathForImage('busy-3.png'))
38 self.bitmap = wx.StaticBitmap(self, -1, wx.EmptyBitmapRGBA(24, 24, red=255, green=255, blue=255, alpha=1))
39 self.text = wx.StaticText(self, -1, '')
40 self.extraInfoButton = wx.Button(self, -1, 'i', style=wx.BU_EXACTFIT)
41 self.sizer.Add(self.bitmap, pos=(0, 0), flag=wx.ALL, border=5)
42 self.sizer.Add(self.text, pos=(0, 1), flag=wx.TOP | wx.BOTTOM | wx.ALIGN_CENTER_VERTICAL, border=5)
43 self.sizer.Add(self.extraInfoButton, pos=(0,2), flag=wx.ALL|wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL, border=5)
44 self.sizer.AddGrowableCol(1)
46 self.extraInfoButton.Show(False)
48 self.extraInfoUrl = ''
50 self.timer = wx.Timer(self)
51 self.Bind(wx.EVT_TIMER, self.doBusyUpdate, self.timer)
52 self.Bind(wx.EVT_BUTTON, self.doExtraInfo, self.extraInfoButton)
55 def SetInfo(self, info):
56 self.SetBackgroundColour('#FFFF80')
57 self.text.SetLabel(info)
58 self.extraInfoButton.Show(False)
61 def SetError(self, info, extraInfoUrl):
62 self.extraInfoUrl = extraInfoUrl
63 self.SetBackgroundColour('#FF8080')
64 self.text.SetLabel(info)
65 self.extraInfoButton.Show(True)
67 self.SetErrorIndicator()
70 def SetAttention(self, info):
71 self.SetBackgroundColour('#FFFF80')
72 self.text.SetLabel(info)
73 self.extraInfoButton.Show(False)
74 self.SetAttentionIndicator()
78 def SetBusy(self, info):
80 self.SetBusyIndicator()
82 def SetBusyIndicator(self):
84 self.bitmap.SetBitmap(self.busyBitmap[self.busyState])
86 def doExtraInfo(self, e):
87 webbrowser.open(self.extraInfoUrl)
89 def doBusyUpdate(self, e):
90 if self.busyState is None:
93 if self.busyState >= len(self.busyBitmap):
95 self.bitmap.SetBitmap(self.busyBitmap[self.busyState])
97 def SetReadyIndicator(self):
99 self.bitmap.SetBitmap(self.readyBitmap)
101 def SetErrorIndicator(self):
102 self.busyState = None
103 self.bitmap.SetBitmap(self.errorBitmap)
105 def SetAttentionIndicator(self):
106 self.busyState = None
107 self.bitmap.SetBitmap(self.attentionBitmap)
109 class ImageButton(wx.Panel):
110 DefaultOverlay = wx.Bitmap(resources.getPathForImage('ImageButton_Overlay.png'))
113 __last_group__ = None
114 def __init__(self, parent, label, bitmap, extra_label=None, overlay=DefaultOverlay, style=None):
115 super(ImageButton, self).__init__(parent)
117 if style is ImageButton.IB_GROUP:
118 ImageButton.__last_group__ = self
119 ImageButton.__groups__[self] = [self]
122 if ImageButton.__last_group__:
123 ImageButton.__groups__[ImageButton.__last_group__].append(self)
124 self.group = ImageButton.__last_group__
127 self.sizer = wx.StaticBoxSizer(wx.StaticBox(self), wx.VERTICAL)
128 self.SetSizer(self.sizer)
130 self.original_overlay = overlay
131 self.overlay = self.createOverlay(bitmap, overlay)
132 self.text = wx.StaticText(self, -1, label)
133 self.bmp = wx.StaticBitmap(self, -1, self.bitmap)
135 self.extra_text = wx.StaticText(self, -1, extra_label)
137 self.extra_text = None
138 self.selected = False
141 self.sizer.Add(self.text, 0, flag=wx.LEFT|wx.RIGHT|wx.ALIGN_CENTER, border=5)
142 self.sizer.Add(self.bmp, 1, flag=wx.ALL|wx.ALIGN_CENTER|wx.EXPAND, border=5)
144 self.sizer.Add(self.extra_text, 0, flag=wx.LEFT|wx.RIGHT|wx.ALIGN_CENTER, border=5)
145 self.bmp.Bind(wx.EVT_LEFT_UP, self.OnLeftClick)
149 ImageButton.__groups__[self.group].remove(self)
150 if self == self.group:
151 for ib in ImageButton.__groups__[self.group]:
153 del ImageButton.__groups__[self.group]
154 if ImageButton.__last_group__ == self:
155 ImageButton.__last_group__ = None
157 def OnLeftClick(self, e):
163 def SetValue(self, value):
164 old_value = self.selected
165 self.selected = bool(value)
166 self.bmp.SetBitmap(self.overlay if self.GetValue() else self.bitmap)
167 if self.selected and self.group:
168 for ib in ImageButton.__groups__[self.group]:
173 if self.callback and not old_value and self.selected:
176 def SetLabel(self, label):
177 self.text.SetLabel(label)
180 def SetExtraLabel(self, label):
182 self.extra_text.SetLabel(label)
184 self.extra_text = wx.StaticText(self, -1, label)
185 self.sizer.Add(self.extra_text, 0, flag=wx.LEFT|wx.RIGHT|wx.ALIGN_CENTER, border=5)
188 def SetBitmap(self, bitmap):
190 self.overlay = self.createOverlay(bitmap, self.original_overlay)
191 self.bmp.SetBitmap(self.overlay if self.GetValue() else self.bitmap)
194 def SetOverlay(self, overlay):
195 self.original_overlay = overlay
196 self.overlay = self.createOverlay(self.bitmap, self.original_overlay)
197 self.bmp.SetBitmap(self.overlay if self.GetValue() else self.bitmap)
200 def OnSelected(self, callback):
201 self.callback = callback
203 def createOverlay(self, bitmap, overlay):
204 result = bitmap.GetSubBitmap(wx.Rect(0, 0, *bitmap.Size))
205 (width, height) = bitmap.GetSize()
206 overlay_image = wx.ImageFromBitmap(overlay)
207 overlay_image = overlay_image.Scale(width, height, wx.IMAGE_QUALITY_HIGH)
208 overlay_scaled = wx.BitmapFromImage(overlay_image)
210 dc.SelectObject(result)
211 dc.DrawBitmap(overlay_scaled, 0, 0)
212 dc.SelectObject(wx.NullBitmap)
216 class InfoPage(wx.wizard.WizardPageSimple):
217 def __init__(self, parent, title):
218 wx.wizard.WizardPageSimple.__init__(self, parent)
220 parent.GetPageAreaSizer().Add(self)
221 sizer = wx.GridBagSizer(5, 5)
225 self.title = wx.StaticText(self, -1, title)
226 font = wx.Font(18, wx.SWISS, wx.NORMAL, wx.BOLD)
227 self.title.SetFont(font)
228 # HACK ALERT: For some reason, the StaticText keeps its same size as if
229 # the font was not modified, this causes the text to wrap and to
230 # get out of bounds of the widgets area and hide other widgets.
231 # The only way I found for the widget to get its right size was to calculate
232 # the new font's extent and set the min size on the widget
233 self.title.SetMinSize(self.GetTextExtent(font, title))
234 sizer.Add(self.title, pos=(0, 0), span=(1, 2), flag=wx.ALIGN_CENTRE | wx.ALL)
235 sizer.Add(wx.StaticLine(self, -1), pos=(1, 0), span=(1, 2), flag=wx.EXPAND | wx.ALL)
236 sizer.AddGrowableCol(1)
240 def GetTextExtent(self, font, text):
243 w,h = dc.GetTextExtent(text)
246 def AddText(self, info):
247 text = wx.StaticText(self, -1, info)
248 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1, 2), flag=wx.LEFT | wx.RIGHT)
252 def AddSeperator(self):
253 self.GetSizer().Add(wx.StaticLine(self, -1), pos=(self.rowNr, 0), span=(1, 2), flag=wx.EXPAND | wx.ALL)
256 def AddHiddenSeperator(self):
259 def AddInfoBox(self):
260 infoBox = InfoBox(self)
261 self.GetSizer().Add(infoBox, pos=(self.rowNr, 0), span=(1, 2), flag=wx.LEFT | wx.RIGHT | wx.EXPAND)
265 def AddRadioButton(self, label, style=0):
266 radio = wx.RadioButton(self, -1, label, style=style)
267 self.GetSizer().Add(radio, pos=(self.rowNr, 0), span=(1, 2), flag=wx.EXPAND | wx.ALL)
271 def AddCheckbox(self, label, checked=False):
272 check = wx.CheckBox(self, -1)
273 text = wx.StaticText(self, -1, label)
274 check.SetValue(checked)
275 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1, 1), flag=wx.LEFT | wx.RIGHT)
276 self.GetSizer().Add(check, pos=(self.rowNr, 1), span=(1, 2), flag=wx.ALL)
280 def AddButton(self, label):
281 button = wx.Button(self, -1, label)
282 self.GetSizer().Add(button, pos=(self.rowNr, 0), span=(1, 2), flag=wx.LEFT)
286 def AddDualButton(self, label1, label2):
287 button1 = wx.Button(self, -1, label1)
288 self.GetSizer().Add(button1, pos=(self.rowNr, 0), flag=wx.RIGHT)
289 button2 = wx.Button(self, -1, label2)
290 self.GetSizer().Add(button2, pos=(self.rowNr, 1))
292 return button1, button2
294 def AddTextCtrl(self, value):
295 ret = wx.TextCtrl(self, -1, value)
296 self.GetSizer().Add(ret, pos=(self.rowNr, 0), span=(1, 2), flag=wx.LEFT)
300 def AddLabelTextCtrl(self, info, value):
301 text = wx.StaticText(self, -1, info)
302 ret = wx.TextCtrl(self, -1, value)
303 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1, 1), flag=wx.LEFT)
304 self.GetSizer().Add(ret, pos=(self.rowNr, 1), span=(1, 1), flag=wx.LEFT)
308 def AddTextCtrlButton(self, value, buttonText):
309 text = wx.TextCtrl(self, -1, value)
310 button = wx.Button(self, -1, buttonText)
311 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1, 1), flag=wx.LEFT)
312 self.GetSizer().Add(button, pos=(self.rowNr, 1), span=(1, 1), flag=wx.LEFT)
316 def AddBitmap(self, bitmap):
317 bitmap = wx.StaticBitmap(self, -1, bitmap)
318 self.GetSizer().Add(bitmap, pos=(self.rowNr, 0), span=(1, 2), flag=wx.LEFT | wx.RIGHT)
323 panel = wx.Panel(self, -1)
324 sizer = wx.GridBagSizer(2, 2)
325 panel.SetSizer(sizer)
326 self.GetSizer().Add(panel, pos=(self.rowNr, 0), span=(1, 2), flag=wx.ALL | wx.EXPAND)
330 def AddCheckmark(self, label, bitmap):
331 check = wx.StaticBitmap(self, -1, bitmap)
332 text = wx.StaticText(self, -1, label)
333 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1, 1), flag=wx.LEFT | wx.RIGHT)
334 self.GetSizer().Add(check, pos=(self.rowNr, 1), span=(1, 1), flag=wx.ALL)
338 def AddCombo(self, label, options):
339 combo = wx.ComboBox(self, -1, options[0], choices=options, style=wx.CB_DROPDOWN|wx.CB_READONLY)
340 text = wx.StaticText(self, -1, label)
341 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1, 1), flag=wx.LEFT | wx.RIGHT | wx.ALIGN_CENTER)
342 self.GetSizer().Add(combo, pos=(self.rowNr, 1), span=(1, 1), flag=wx.LEFT | wx.RIGHT | wx.EXPAND)
346 def AddImageButton(self, panel, x, y, label, filename, image_size=None,
347 extra_label=None, overlay=ImageButton.DefaultOverlay, style=None):
348 ib = ImageButton(panel, label, self.GetBitmap(filename, image_size), extra_label, overlay, style)
349 panel.GetSizer().Add(ib, pos=(x, y), flag=wx.LEFT | wx.RIGHT | wx.BOTTOM, border=10)
352 def GetBitmap(self, filename, image_size):
353 if image_size == None:
354 return wx.Bitmap(resources.getPathForImage(filename))
356 image = wx.Image(resources.getPathForImage(filename))
357 image_scaled = image.Scale(image_size[0], image_size[1], wx.IMAGE_QUALITY_HIGH)
358 return wx.BitmapFromImage(image_scaled)
369 class PrintrbotPage(InfoPage):
370 def __init__(self, parent):
371 self._printer_info = [
372 # X, Y, Z, Nozzle Size, Filament Diameter, PrintTemperature, Print Speed, Travel Speed, Retract speed, Retract amount, use bed level sensor
373 ("Simple Metal", 150, 150, 150, 0.4, 1.75, 208, 40, 70, 30, 1, True),
374 ("Metal Plus", 250, 250, 250, 0.4, 1.75, 208, 40, 70, 30, 1, True),
375 ("Simple Makers Kit", 100, 100, 100, 0.4, 1.75, 208, 40, 70, 30, 1, True),
376 (":" + _("Older models"),),
377 ("Original", 130, 130, 130, 0.5, 2.95, 208, 40, 70, 30, 1, False),
378 ("Simple Maker's Edition v1", 100, 100, 100, 0.4, 1.75, 208, 40, 70, 30, 1, False),
379 ("Simple Maker's Edition v2 (2013 Printrbot Simple)", 100, 100, 100, 0.4, 1.75, 208, 40, 70, 30, 1, False),
380 ("Simple Maker's Edition v3 (2014 Printrbot Simple)", 100, 100, 100, 0.4, 1.75, 208, 40, 70, 30, 1, False),
381 ("Jr v1", 115, 120, 80, 0.4, 1.75, 208, 40, 70, 30, 1, False),
382 ("Jr v2", 150, 150, 150, 0.4, 1.75, 208, 40, 70, 30, 1, False),
383 ("LC v1", 150, 150, 150, 0.4, 1.75, 208, 40, 70, 30, 1, False),
384 ("LC v2", 150, 150, 150, 0.4, 1.75, 208, 40, 70, 30, 1, False),
385 ("Plus v1", 200, 200, 200, 0.4, 1.75, 208, 40, 70, 30, 1, False),
386 ("Plus v2", 200, 200, 200, 0.4, 1.75, 208, 40, 70, 30, 1, False),
387 ("Plus v2.1", 185, 220, 200, 0.4, 1.75, 208, 40, 70, 30, 1, False),
388 ("Plus v2.2 (Model 1404/140422/140501/140507)", 250, 250, 250, 0.4, 1.75, 208, 40, 70, 30, 1, True),
389 ("Go v2 Large", 505, 306, 310, 0.4, 1.75, 208, 35, 70, 30, 1, True),
392 super(PrintrbotPage, self).__init__(parent, _("Printrbot Selection"))
393 self.AddBitmap(wx.Bitmap(resources.getPathForImage('Printrbot_logo.png')))
394 self.AddText(_("Select which Printrbot machine you have:"))
396 for printer in self._printer_info:
397 if printer[0].startswith(":"):
399 self.AddText(printer[0][1:])
401 item = self.AddRadioButton(printer[0])
402 item.data = printer[1:]
403 self._items.append(item)
406 profile.putMachineSetting('machine_name', 'Printrbot ???')
407 for item in self._items:
410 profile.putMachineSetting('machine_name', 'Printrbot ' + item.GetLabel())
411 profile.putMachineSetting('machine_width', data[0])
412 profile.putMachineSetting('machine_depth', data[1])
413 profile.putMachineSetting('machine_height', data[2])
414 profile.putProfileSetting('nozzle_size', data[3])
415 profile.putProfileSetting('filament_diameter', data[4])
416 profile.putProfileSetting('print_temperature', data[5])
417 profile.putProfileSetting('print_speed', data[6])
418 profile.putProfileSetting('travel_speed', data[7])
419 profile.putProfileSetting('retraction_speed', data[8])
420 profile.putProfileSetting('retraction_amount', data[9])
421 profile.putProfileSetting('wall_thickness', float(profile.getProfileSettingFloat('nozzle_size')) * 2)
422 profile.putMachineSetting('has_heated_bed', 'False')
423 profile.putMachineSetting('machine_center_is_zero', 'False')
424 profile.putMachineSetting('extruder_head_size_min_x', '0')
425 profile.putMachineSetting('extruder_head_size_min_y', '0')
426 profile.putMachineSetting('extruder_head_size_max_x', '0')
427 profile.putMachineSetting('extruder_head_size_max_y', '0')
428 profile.putMachineSetting('extruder_head_size_height', '0')
430 profile.setAlterationFile('start.gcode', """;Sliced at: {day} {date} {time}
431 ;Basic settings: Layer height: {layer_height} Walls: {wall_thickness} Fill: {fill_density}
432 ;Print time: {print_time}
433 ;Filament used: {filament_amount}m {filament_weight}g
434 ;Filament cost: {filament_cost}
435 ;M190 S{print_bed_temperature} ;Uncomment to add your own bed temperature line
436 ;M109 S{print_temperature} ;Uncomment to add your own temperature line
438 G90 ;absolute positioning
439 M82 ;set extruder to absolute mode
440 M107 ;start with the fan off
441 G28 X0 Y0 ;move X/Y to min endstops
442 G28 Z0 ;move Z to min endstops
443 G29 ;Run the auto bed leveling
444 G1 Z15.0 F{travel_speed} ;move the platform down 15mm
445 G92 E0 ;zero the extruded length
446 G1 F200 E3 ;extrude 3mm of feed stock
447 G92 E0 ;zero the extruded length again
449 ;Put printing message on LCD screen
453 class OtherMachineSelectPage(InfoPage):
454 def __init__(self, parent):
455 super(OtherMachineSelectPage, self).__init__(parent, _("Other machine information"))
456 self.AddText(_("The following pre-defined machine profiles are available"))
457 self.AddText(_("Note that these profiles are not guaranteed to give good results,\nor work at all. Extra tweaks might be required.\nIf you find issues with the predefined profiles,\nor want an extra profile.\nPlease report it at the github issue tracker."))
459 machines = resources.getDefaultMachineProfiles()
461 for filename in machines:
462 name = os.path.splitext(os.path.basename(filename))[0]
463 item = self.AddRadioButton(name)
464 item.filename = filename
465 item.Bind(wx.EVT_RADIOBUTTON, self.OnProfileSelect)
466 self.options.append(item)
468 item = self.AddRadioButton(_('Custom...'))
470 item.Bind(wx.EVT_RADIOBUTTON, self.OnOtherSelect)
472 def OnProfileSelect(self, e):
473 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().otherMachineInfoPage)
475 def OnOtherSelect(self, e):
476 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().customRepRapInfoPage)
479 for option in self.options:
480 if option.GetValue():
481 profile.loadProfile(option.filename)
482 profile.loadMachineSettings(option.filename)
484 class OtherMachineInfoPage(InfoPage):
485 def __init__(self, parent):
486 super(OtherMachineInfoPage, self).__init__(parent, _("Cura Ready!"))
487 self.AddText(_("Cura is now ready to be used!"))
489 class CustomRepRapInfoPage(InfoPage):
490 def __init__(self, parent):
491 super(CustomRepRapInfoPage, self).__init__(parent, _("Custom RepRap information"))
492 self.AddText(_("RepRap machines can be vastly different, so here you can set your own settings."))
493 self.AddText(_("Be sure to review the default profile before running it on your machine."))
494 self.AddText(_("If you like a default profile for your machine added,\nthen make an issue on github."))
496 self.AddText(_("You will have to manually install Marlin or Sprinter firmware."))
498 self.machineName = self.AddLabelTextCtrl(_("Machine name"), "RepRap")
499 self.machineWidth = self.AddLabelTextCtrl(_("Machine width X (mm)"), "80")
500 self.machineDepth = self.AddLabelTextCtrl(_("Machine depth Y (mm)"), "80")
501 self.machineHeight = self.AddLabelTextCtrl(_("Machine height Z (mm)"), "55")
502 self.nozzleSize = self.AddLabelTextCtrl(_("Nozzle size (mm)"), "0.5")
503 self.heatedBed = self.AddCheckbox(_("Heated bed"))
504 self.HomeAtCenter = self.AddCheckbox(_("Bed center is 0,0,0 (RoStock)"))
507 profile.putMachineSetting('machine_name', self.machineName.GetValue())
508 profile.putMachineSetting('machine_width', self.machineWidth.GetValue())
509 profile.putMachineSetting('machine_depth', self.machineDepth.GetValue())
510 profile.putMachineSetting('machine_height', self.machineHeight.GetValue())
511 profile.putProfileSetting('nozzle_size', self.nozzleSize.GetValue())
512 profile.putProfileSetting('wall_thickness', float(profile.getProfileSettingFloat('nozzle_size')) * 2)
513 profile.putMachineSetting('has_heated_bed', str(self.heatedBed.GetValue()))
514 profile.putMachineSetting('machine_center_is_zero', str(self.HomeAtCenter.GetValue()))
515 profile.putMachineSetting('extruder_head_size_min_x', '0')
516 profile.putMachineSetting('extruder_head_size_min_y', '0')
517 profile.putMachineSetting('extruder_head_size_max_x', '0')
518 profile.putMachineSetting('extruder_head_size_max_y', '0')
519 profile.putMachineSetting('extruder_head_size_height', '0')
520 profile.checkAndUpdateMachineName()
522 class MachineSelectPage(InfoPage):
523 def __init__(self, parent):
524 super(MachineSelectPage, self).__init__(parent, _("Select your machine"))
525 self.AddText(_("What kind of machine do you have:"))
527 self.Ultimaker2Radio = self.AddRadioButton("Ultimaker2")
528 self.Ultimaker2Radio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimaker2Select)
529 self.Ultimaker2ExtRadio = self.AddRadioButton("Ultimaker2extended")
530 self.Ultimaker2ExtRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimaker2Select)
531 self.Ultimaker2GoRadio = self.AddRadioButton("Ultimaker2go")
532 self.Ultimaker2GoRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimaker2Select)
533 self.UltimakerRadio = self.AddRadioButton("Ultimaker Original")
534 self.UltimakerRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimakerSelect)
535 self.UltimakerOPRadio = self.AddRadioButton("Ultimaker Original+")
536 self.UltimakerOPRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimakerOPSelect)
537 self.PrintrbotRadio = self.AddRadioButton("Printrbot")
538 self.PrintrbotRadio.Bind(wx.EVT_RADIOBUTTON, self.OnPrintrbotSelect)
539 self.OtherRadio = self.AddRadioButton(_("Other (Ex: RepRap, MakerBot, Witbox)"))
540 self.OtherRadio.Bind(wx.EVT_RADIOBUTTON, self.OnOtherSelect)
542 def OnUltimaker2Select(self, e):
543 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().ultimaker2ReadyPage)
545 def OnUltimakerSelect(self, e):
546 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().ultimakerSelectParts)
548 def OnUltimakerOPSelect(self, e):
549 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().ultimakerFirmwareUpgradePage)
551 def OnPrintrbotSelect(self, e):
552 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().printrbotSelectType)
554 def OnOtherSelect(self, e):
555 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().otherMachineSelectPage)
558 profile.putProfileSetting('retraction_enable', 'True')
559 if self.Ultimaker2Radio.GetValue() or self.Ultimaker2GoRadio.GetValue() or self.Ultimaker2ExtRadio.GetValue():
560 if self.Ultimaker2Radio.GetValue():
561 profile.putMachineSetting('machine_width', '230')
562 profile.putMachineSetting('machine_depth', '225')
563 profile.putMachineSetting('machine_height', '205')
564 profile.putMachineSetting('machine_name', 'ultimaker2')
565 profile.putMachineSetting('machine_type', 'ultimaker2')
566 profile.putMachineSetting('has_heated_bed', 'True')
567 if self.Ultimaker2GoRadio.GetValue():
568 profile.putMachineSetting('machine_width', '120')
569 profile.putMachineSetting('machine_depth', '120')
570 profile.putMachineSetting('machine_height', '115')
571 profile.putMachineSetting('machine_name', 'ultimaker2go')
572 profile.putMachineSetting('machine_type', 'ultimaker2go')
573 profile.putMachineSetting('has_heated_bed', 'False')
574 if self.Ultimaker2ExtRadio.GetValue():
575 profile.putMachineSetting('machine_width', '230')
576 profile.putMachineSetting('machine_depth', '225')
577 profile.putMachineSetting('machine_height', '315')
578 profile.putMachineSetting('machine_name', 'ultimaker2extended')
579 profile.putMachineSetting('machine_type', 'ultimaker2extended')
580 profile.putMachineSetting('has_heated_bed', 'False')
581 profile.putMachineSetting('machine_center_is_zero', 'False')
582 profile.putMachineSetting('gcode_flavor', 'UltiGCode')
583 profile.putMachineSetting('extruder_head_size_min_x', '40.0')
584 profile.putMachineSetting('extruder_head_size_min_y', '10.0')
585 profile.putMachineSetting('extruder_head_size_max_x', '60.0')
586 profile.putMachineSetting('extruder_head_size_max_y', '30.0')
587 profile.putMachineSetting('extruder_head_size_height', '48.0')
588 profile.putProfileSetting('nozzle_size', '0.4')
589 profile.putProfileSetting('fan_full_height', '5.0')
590 profile.putMachineSetting('extruder_offset_x1', '18.0')
591 profile.putMachineSetting('extruder_offset_y1', '0.0')
592 elif self.UltimakerRadio.GetValue():
593 profile.putMachineSetting('machine_width', '205')
594 profile.putMachineSetting('machine_depth', '205')
595 profile.putMachineSetting('machine_height', '200')
596 profile.putMachineSetting('machine_name', 'ultimaker original')
597 profile.putMachineSetting('machine_type', 'ultimaker')
598 profile.putMachineSetting('machine_center_is_zero', 'False')
599 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
600 profile.putProfileSetting('nozzle_size', '0.4')
601 profile.putMachineSetting('extruder_head_size_min_x', '75.0')
602 profile.putMachineSetting('extruder_head_size_min_y', '18.0')
603 profile.putMachineSetting('extruder_head_size_max_x', '18.0')
604 profile.putMachineSetting('extruder_head_size_max_y', '35.0')
605 profile.putMachineSetting('extruder_head_size_height', '55.0')
606 elif self.UltimakerOPRadio.GetValue():
607 profile.putMachineSetting('machine_width', '205')
608 profile.putMachineSetting('machine_depth', '205')
609 profile.putMachineSetting('machine_height', '200')
610 profile.putMachineSetting('machine_name', 'ultimaker original+')
611 profile.putMachineSetting('machine_type', 'ultimaker_plus')
612 profile.putMachineSetting('machine_center_is_zero', 'False')
613 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
614 profile.putProfileSetting('nozzle_size', '0.4')
615 profile.putMachineSetting('extruder_head_size_min_x', '75.0')
616 profile.putMachineSetting('extruder_head_size_min_y', '18.0')
617 profile.putMachineSetting('extruder_head_size_max_x', '18.0')
618 profile.putMachineSetting('extruder_head_size_max_y', '35.0')
619 profile.putMachineSetting('extruder_head_size_height', '55.0')
620 profile.putMachineSetting('has_heated_bed', 'True')
621 profile.putMachineSetting('extruder_amount', '1')
622 profile.putProfileSetting('retraction_enable', 'True')
624 profile.putMachineSetting('machine_width', '80')
625 profile.putMachineSetting('machine_depth', '80')
626 profile.putMachineSetting('machine_height', '60')
627 profile.putMachineSetting('machine_name', 'reprap')
628 profile.putMachineSetting('machine_type', 'reprap')
629 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
630 profile.putPreference('startMode', 'Normal')
631 profile.putProfileSetting('nozzle_size', '0.5')
632 profile.checkAndUpdateMachineName()
633 profile.putProfileSetting('wall_thickness', float(profile.getProfileSetting('nozzle_size')) * 2)
635 class SelectParts(InfoPage):
636 def __init__(self, parent):
637 super(SelectParts, self).__init__(parent, _("Select upgraded parts you have"))
638 self.AddText(_("To assist you in having better default settings for your Ultimaker\nCura would like to know which upgrades you have in your machine."))
640 self.springExtruder = self.AddCheckbox(_("Extruder drive upgrade"))
641 self.heatedBedKit = self.AddCheckbox(_("Heated printer bed (kit)"))
642 self.heatedBed = self.AddCheckbox(_("Heated printer bed (self built)"))
643 self.dualExtrusion = self.AddCheckbox(_("Dual extrusion (experimental)"))
645 self.AddText(_("If you have an Ultimaker bought after october 2012 you will have the\nExtruder drive upgrade. If you do not have this upgrade,\nit is highly recommended to improve reliability."))
646 self.AddText(_("This upgrade can be bought from the Ultimaker webshop\nor found on thingiverse as thing:26094"))
647 self.springExtruder.SetValue(True)
650 profile.putMachineSetting('ultimaker_extruder_upgrade', str(self.springExtruder.GetValue()))
651 if self.heatedBed.GetValue() or self.heatedBedKit.GetValue():
652 profile.putMachineSetting('has_heated_bed', 'True')
654 profile.putMachineSetting('has_heated_bed', 'False')
655 if self.dualExtrusion.GetValue():
656 profile.putMachineSetting('extruder_amount', '2')
657 profile.putMachineSetting('machine_depth', '195')
659 profile.putMachineSetting('extruder_amount', '1')
660 if profile.getMachineSetting('ultimaker_extruder_upgrade') == 'True':
661 profile.putProfileSetting('retraction_enable', 'True')
663 profile.putProfileSetting('retraction_enable', 'False')
666 class UltimakerFirmwareUpgradePage(InfoPage):
667 def __init__(self, parent):
668 super(UltimakerFirmwareUpgradePage, self).__init__(parent, _("Upgrade Ultimaker Firmware"))
669 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."))
670 self.AddHiddenSeperator()
671 self.AddText(_("The firmware shipping with new Ultimakers works, but upgrades\nhave been made to make better prints, and make calibration easier."))
672 self.AddHiddenSeperator()
673 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."))
674 upgradeButton, skipUpgradeButton = self.AddDualButton(_('Upgrade to Marlin firmware'), _('Skip upgrade'))
675 upgradeButton.Bind(wx.EVT_BUTTON, self.OnUpgradeClick)
676 skipUpgradeButton.Bind(wx.EVT_BUTTON, self.OnSkipClick)
677 self.AddHiddenSeperator()
678 if profile.getMachineSetting('machine_type') == 'ultimaker':
679 self.AddText(_("Do not upgrade to this firmware if:"))
680 self.AddText(_("* You have an older machine based on ATMega1280 (Rev 1 machine)"))
681 self.AddText(_("* Build your own heated bed"))
682 self.AddText(_("* Have other changes in the firmware"))
683 # button = self.AddButton('Goto this page for a custom firmware')
684 # button.Bind(wx.EVT_BUTTON, self.OnUrlClick)
689 def OnUpgradeClick(self, e):
690 if firmwareInstall.InstallFirmware():
691 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
693 def OnSkipClick(self, e):
694 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
695 self.GetParent().ShowPage(self.GetNext())
697 def OnUrlClick(self, e):
698 webbrowser.open('http://marlinbuilder.robotfuzz.com/')
700 class UltimakerCheckupPage(InfoPage):
701 def __init__(self, parent):
702 super(UltimakerCheckupPage, self).__init__(parent, _("Ultimaker Checkup"))
704 self.checkBitmap = wx.Bitmap(resources.getPathForImage('checkmark.png'))
705 self.crossBitmap = wx.Bitmap(resources.getPathForImage('cross.png'))
706 self.unknownBitmap = wx.Bitmap(resources.getPathForImage('question.png'))
707 self.endStopNoneBitmap = wx.Bitmap(resources.getPathForImage('endstop_none.png'))
708 self.endStopXMinBitmap = wx.Bitmap(resources.getPathForImage('endstop_xmin.png'))
709 self.endStopXMaxBitmap = wx.Bitmap(resources.getPathForImage('endstop_xmax.png'))
710 self.endStopYMinBitmap = wx.Bitmap(resources.getPathForImage('endstop_ymin.png'))
711 self.endStopYMaxBitmap = wx.Bitmap(resources.getPathForImage('endstop_ymax.png'))
712 self.endStopZMinBitmap = wx.Bitmap(resources.getPathForImage('endstop_zmin.png'))
713 self.endStopZMaxBitmap = wx.Bitmap(resources.getPathForImage('endstop_zmax.png'))
716 _("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."))
717 b1, b2 = self.AddDualButton(_("Run checks"), _("Skip checks"))
718 b1.Bind(wx.EVT_BUTTON, self.OnCheckClick)
719 b2.Bind(wx.EVT_BUTTON, self.OnSkipClick)
721 self.commState = self.AddCheckmark(_("Communication:"), self.unknownBitmap)
722 self.tempState = self.AddCheckmark(_("Temperature:"), self.unknownBitmap)
723 self.stopState = self.AddCheckmark(_("Endstops:"), self.unknownBitmap)
725 self.infoBox = self.AddInfoBox()
726 self.machineState = self.AddText("")
727 self.temperatureLabel = self.AddText("")
728 self.errorLogButton = self.AddButton(_("Show error log"))
729 self.errorLogButton.Show(False)
731 self.endstopBitmap = self.AddBitmap(self.endStopNoneBitmap)
733 self.xMinStop = False
734 self.xMaxStop = False
735 self.yMinStop = False
736 self.yMaxStop = False
737 self.zMinStop = False
738 self.zMaxStop = False
740 self.Bind(wx.EVT_BUTTON, self.OnErrorLog, self.errorLogButton)
743 if self.comm is not None:
747 self.endstopBitmap.Show(False)
750 def OnSkipClick(self, e):
751 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
752 self.GetParent().ShowPage(self.GetNext())
754 def OnCheckClick(self, e=None):
755 self.errorLogButton.Show(False)
756 if self.comm is not None:
760 wx.CallAfter(self.OnCheckClick)
762 self.infoBox.SetBusy(_("Connecting to machine."))
763 self.commState.SetBitmap(self.unknownBitmap)
764 self.tempState.SetBitmap(self.unknownBitmap)
765 self.stopState.SetBitmap(self.unknownBitmap)
766 self.checkupState = 0
767 self.checkExtruderNr = 0
768 self.comm = machineCom.MachineCom(callbackObject=self)
770 def OnErrorLog(self, e):
771 printWindow.LogWindow('\n'.join(self.comm.getLog()))
773 def mcLog(self, message):
776 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
777 if not self.comm.isOperational():
779 if self.checkupState == 0:
780 self.tempCheckTimeout = 20
781 if temp[self.checkExtruderNr] > 70:
782 self.checkupState = 1
783 wx.CallAfter(self.infoBox.SetInfo, _("Cooldown before temperature check."))
784 self.comm.sendCommand("M104 S0 T%d" % (self.checkExtruderNr))
785 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
787 self.startTemp = temp[self.checkExtruderNr]
788 self.checkupState = 2
789 wx.CallAfter(self.infoBox.SetInfo, _("Checking the heater and temperature sensor."))
790 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
791 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
792 elif self.checkupState == 1:
793 if temp[self.checkExtruderNr] < 60:
794 self.startTemp = temp[self.checkExtruderNr]
795 self.checkupState = 2
796 wx.CallAfter(self.infoBox.SetInfo, _("Checking the heater and temperature sensor."))
797 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
798 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
799 elif self.checkupState == 2:
800 #print "WARNING, TEMPERATURE TEST DISABLED FOR TESTING!"
801 if temp[self.checkExtruderNr] > self.startTemp + 40:
802 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
803 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
804 if self.checkExtruderNr < int(profile.getMachineSetting('extruder_amount')):
805 self.checkExtruderNr = 0
806 self.checkupState = 3
807 wx.CallAfter(self.infoBox.SetAttention, _("Please make sure none of the endstops are pressed."))
808 wx.CallAfter(self.endstopBitmap.Show, True)
809 wx.CallAfter(self.Layout)
810 self.comm.sendCommand('M119')
811 wx.CallAfter(self.tempState.SetBitmap, self.checkBitmap)
813 self.checkupState = 0
814 self.checkExtruderNr += 1
816 self.tempCheckTimeout -= 1
817 if self.tempCheckTimeout < 1:
818 self.checkupState = -1
819 wx.CallAfter(self.tempState.SetBitmap, self.crossBitmap)
820 wx.CallAfter(self.infoBox.SetError, _("Temperature measurement FAILED!"), 'http://wiki.ultimaker.com/Cura:_Temperature_measurement_problems')
821 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
822 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
823 elif self.checkupState >= 3 and self.checkupState < 10:
824 self.comm.sendCommand('M119')
825 wx.CallAfter(self.temperatureLabel.SetLabel, _("Head temperature: %d") % (temp[self.checkExtruderNr]))
827 def mcStateChange(self, state):
828 if self.comm is None:
830 if self.comm.isOperational():
831 wx.CallAfter(self.commState.SetBitmap, self.checkBitmap)
832 wx.CallAfter(self.machineState.SetLabel, _("Communication State: %s") % (self.comm.getStateString()))
833 elif self.comm.isError():
834 wx.CallAfter(self.commState.SetBitmap, self.crossBitmap)
835 wx.CallAfter(self.infoBox.SetError, _("Failed to establish connection with the printer."), 'http://wiki.ultimaker.com/Cura:_Connection_problems')
836 wx.CallAfter(self.endstopBitmap.Show, False)
837 wx.CallAfter(self.machineState.SetLabel, '%s' % (self.comm.getErrorString()))
838 wx.CallAfter(self.errorLogButton.Show, True)
839 wx.CallAfter(self.Layout)
841 wx.CallAfter(self.machineState.SetLabel, _("Communication State: %s") % (self.comm.getStateString()))
843 def mcMessage(self, message):
844 if self.checkupState >= 3 and self.checkupState < 10 and ('_min' in message or '_max' in message):
845 for data in message.split(' '):
847 tag, value = data.split(':', 1)
849 self.xMinStop = (value == 'H' or value == 'TRIGGERED')
851 self.xMaxStop = (value == 'H' or value == 'TRIGGERED')
853 self.yMinStop = (value == 'H' or value == 'TRIGGERED')
855 self.yMaxStop = (value == 'H' or value == 'TRIGGERED')
857 self.zMinStop = (value == 'H' or value == 'TRIGGERED')
859 self.zMaxStop = (value == 'H' or value == 'TRIGGERED')
861 tag, value = map(str.strip, message.split(':', 1))
863 self.xMinStop = (value == 'H' or value == 'TRIGGERED')
865 self.xMaxStop = (value == 'H' or value == 'TRIGGERED')
867 self.yMinStop = (value == 'H' or value == 'TRIGGERED')
869 self.yMaxStop = (value == 'H' or value == 'TRIGGERED')
871 self.zMinStop = (value == 'H' or value == 'TRIGGERED')
873 self.zMaxStop = (value == 'H' or value == 'TRIGGERED')
874 if 'z_max' in message:
875 self.comm.sendCommand('M119')
877 if self.checkupState == 3:
878 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
879 if profile.getMachineSetting('machine_type') == 'ultimaker_plus':
880 self.checkupState = 5
881 wx.CallAfter(self.infoBox.SetAttention, _("Please press the left X endstop."))
882 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMinBitmap)
884 self.checkupState = 4
885 wx.CallAfter(self.infoBox.SetAttention, _("Please press the right X endstop."))
886 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMaxBitmap)
887 elif self.checkupState == 4:
888 if not self.xMinStop and self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
889 self.checkupState = 5
890 wx.CallAfter(self.infoBox.SetAttention, _("Please press the left X endstop."))
891 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMinBitmap)
892 elif self.checkupState == 5:
893 if self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
894 self.checkupState = 6
895 wx.CallAfter(self.infoBox.SetAttention, _("Please press the front Y endstop."))
896 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopYMinBitmap)
897 elif self.checkupState == 6:
898 if not self.xMinStop and not self.xMaxStop and self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
899 if profile.getMachineSetting('machine_type') == 'ultimaker_plus':
900 self.checkupState = 8
901 wx.CallAfter(self.infoBox.SetAttention, _("Please press the top Z endstop."))
902 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMinBitmap)
904 self.checkupState = 7
905 wx.CallAfter(self.infoBox.SetAttention, _("Please press the back Y endstop."))
906 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopYMaxBitmap)
907 elif self.checkupState == 7:
908 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and self.yMaxStop and not self.zMinStop and not self.zMaxStop:
909 self.checkupState = 8
910 wx.CallAfter(self.infoBox.SetAttention, _("Please press the top Z endstop."))
911 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMinBitmap)
912 elif self.checkupState == 8:
913 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and self.zMinStop and not self.zMaxStop:
914 if profile.getMachineSetting('machine_type') == 'ultimaker_plus':
915 self.checkupState = 10
917 wx.CallAfter(self.infoBox.SetInfo, _("Checkup finished"))
918 wx.CallAfter(self.infoBox.SetReadyIndicator)
919 wx.CallAfter(self.endstopBitmap.Show, False)
920 wx.CallAfter(self.stopState.SetBitmap, self.checkBitmap)
921 wx.CallAfter(self.OnSkipClick, None)
923 self.checkupState = 9
924 wx.CallAfter(self.infoBox.SetAttention, _("Please press the bottom Z endstop."))
925 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMaxBitmap)
926 elif self.checkupState == 9:
927 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and self.zMaxStop:
928 self.checkupState = 10
930 wx.CallAfter(self.infoBox.SetInfo, _("Checkup finished"))
931 wx.CallAfter(self.infoBox.SetReadyIndicator)
932 wx.CallAfter(self.endstopBitmap.Show, False)
933 wx.CallAfter(self.stopState.SetBitmap, self.checkBitmap)
934 wx.CallAfter(self.OnSkipClick, None)
936 def mcProgress(self, lineNr):
939 def mcZChange(self, newZ):
943 class UltimakerCalibrationPage(InfoPage):
944 def __init__(self, parent):
945 super(UltimakerCalibrationPage, self).__init__(parent, _("Ultimaker Calibration"))
947 self.AddText("Your Ultimaker requires some calibration.")
948 self.AddText("This calibration is needed for a proper extrusion amount.")
950 self.AddText("The following values are needed:")
951 self.AddText("* Diameter of filament")
952 self.AddText("* Number of steps per mm of filament extrusion")
954 self.AddText("The better you have calibrated these values, the better your prints\nwill become.")
956 self.AddText("First we need the diameter of your filament:")
957 self.filamentDiameter = self.AddTextCtrl(profile.getProfileSetting('filament_diameter'))
959 "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.")
960 self.AddText("Note: This value can be changed later at any time.")
963 profile.putProfileSetting('filament_diameter', self.filamentDiameter.GetValue())
966 class UltimakerCalibrateStepsPerEPage(InfoPage):
967 def __init__(self, parent):
968 super(UltimakerCalibrateStepsPerEPage, self).__init__(parent, _("Ultimaker Calibration"))
970 #if profile.getMachineSetting('steps_per_e') == '0':
971 # profile.putMachineSetting('steps_per_e', '865.888')
973 self.AddText(_("Calibrating the Steps Per E requires some manual actions."))
974 self.AddText(_("First remove any filament from your machine."))
975 self.AddText(_("Next put in your filament so the tip is aligned with the\ntop of the extruder drive."))
976 self.AddText(_("We'll push the filament 100mm"))
977 self.extrudeButton = self.AddButton(_("Extrude 100mm filament"))
978 self.AddText(_("Now measure the amount of extruded filament:\n(this can be more or less then 100mm)"))
979 self.lengthInput, self.saveLengthButton = self.AddTextCtrlButton("100", _("Save"))
980 self.AddText(_("This results in the following steps per E:"))
981 self.stepsPerEInput = self.AddTextCtrl(profile.getMachineSetting('steps_per_e'))
982 self.AddText(_("You can repeat these steps to get better calibration."))
985 _("If you still have filament in your printer which needs\nheat to remove, press the heat up button below:"))
986 self.heatButton = self.AddButton(_("Heatup for filament removal"))
988 self.saveLengthButton.Bind(wx.EVT_BUTTON, self.OnSaveLengthClick)
989 self.extrudeButton.Bind(wx.EVT_BUTTON, self.OnExtrudeClick)
990 self.heatButton.Bind(wx.EVT_BUTTON, self.OnHeatClick)
992 def OnSaveLengthClick(self, e):
993 currentEValue = float(self.stepsPerEInput.GetValue())
994 realExtrudeLength = float(self.lengthInput.GetValue())
995 newEValue = currentEValue * 100 / realExtrudeLength
996 self.stepsPerEInput.SetValue(str(newEValue))
997 self.lengthInput.SetValue("100")
999 def OnExtrudeClick(self, e):
1000 t = threading.Thread(target=self.OnExtrudeRun)
1004 def OnExtrudeRun(self):
1005 self.heatButton.Enable(False)
1006 self.extrudeButton.Enable(False)
1007 currentEValue = float(self.stepsPerEInput.GetValue())
1008 self.comm = machineCom.MachineCom()
1009 if not self.comm.isOpen():
1011 _("Error: Failed to open serial port to machine\nIf this keeps happening, try disconnecting and reconnecting the USB cable"),
1012 'Printer error', wx.OK | wx.ICON_INFORMATION)
1013 self.heatButton.Enable(True)
1014 self.extrudeButton.Enable(True)
1017 line = self.comm.readline()
1022 #Wait 3 seconds for the SD card init to timeout if we have SD in our firmware but there is no SD card found.
1025 self.sendGCommand('M302') #Disable cold extrusion protection
1026 self.sendGCommand("M92 E%f" % (currentEValue))
1027 self.sendGCommand("G92 E0")
1028 self.sendGCommand("G1 E100 F600")
1031 self.extrudeButton.Enable()
1032 self.heatButton.Enable()
1034 def OnHeatClick(self, e):
1035 t = threading.Thread(target=self.OnHeatRun)
1039 def OnHeatRun(self):
1040 self.heatButton.Enable(False)
1041 self.extrudeButton.Enable(False)
1042 self.comm = machineCom.MachineCom()
1043 if not self.comm.isOpen():
1045 _("Error: Failed to open serial port to machine\nIf this keeps happening, try disconnecting and reconnecting the USB cable"),
1046 'Printer error', wx.OK | wx.ICON_INFORMATION)
1047 self.heatButton.Enable(True)
1048 self.extrudeButton.Enable(True)
1051 line = self.comm.readline()
1053 self.heatButton.Enable(True)
1054 self.extrudeButton.Enable(True)
1058 #Wait 3 seconds for the SD card init to timeout if we have SD in our firmware but there is no SD card found.
1061 self.sendGCommand('M104 S200') #Set the temperature to 200C, should be enough to get PLA and ABS out.
1063 'Wait till you can remove the filament from the machine, and press OK.\n(Temperature is set to 200C)',
1064 'Machine heatup', wx.OK | wx.ICON_INFORMATION)
1065 self.sendGCommand('M104 S0')
1068 self.heatButton.Enable(True)
1069 self.extrudeButton.Enable(True)
1071 def sendGCommand(self, cmd):
1072 self.comm.sendCommand(cmd) #Disable cold extrusion protection
1074 line = self.comm.readline()
1077 if line.startswith('ok'):
1080 def StoreData(self):
1081 profile.putPreference('steps_per_e', self.stepsPerEInput.GetValue())
1083 class Ultimaker2ReadyPage(InfoPage):
1084 def __init__(self, parent):
1085 super(Ultimaker2ReadyPage, self).__init__(parent, _("Ultimaker2"))
1086 self.AddText(_('Congratulations on your the purchase of your brand new Ultimaker2.'))
1087 self.AddText(_('Cura is now ready to be used with your Ultimaker2.'))
1090 class LulzbotMachineSelectPage(InfoPage):
1094 def __init__(self, parent):
1095 super(LulzbotMachineSelectPage, self).__init__(parent, _("Select your machine"))
1096 self.AddBitmap(wx.Bitmap(resources.getPathForImage('Lulzbot_logo.png')))
1097 self.AddText(_("Select your printer :"))
1099 self.panel = self.AddPanel()
1101 image_size=(LulzbotMachineSelectPage.IMAGE_WIDTH, LulzbotMachineSelectPage.IMAGE_HEIGHT)
1102 self.LulzbotMini = self.AddImageButton(self.panel, 0, 0, _("LulzBot Mini"),
1103 'Lulzbot_mini.jpg', image_size, style=ImageButton.IB_GROUP)
1104 self.LulzbotMini.OnSelected(self.OnLulzbotMiniSelected)
1105 self.LulzbotMini.SetValue(True)
1106 self.LulzbotTaz5 = self.AddImageButton(self.panel, 0, 1, _("LulzBot TAZ 5"),
1107 'Lulzbot_TAZ5.jpg', image_size)
1108 self.LulzbotTaz5.OnSelected(self.OnLulzbotTazSelected)
1109 self.LulzbotTaz4 = self.AddImageButton(self.panel, 1, 0, _("LulzBot TAZ 4"),
1110 'Lulzbot_TAZ4.jpg', image_size)
1111 self.LulzbotTaz4.OnSelected(self.OnLulzbotTazSelected)
1112 self.OtherPrinters = self.AddImageButton(self.panel, 1, 1, _("Other Printers"),
1113 'Generic-3D-Printer.png', image_size)
1114 self.OtherPrinters.OnSelected(self.OnOthersSelected)
1116 def OnOthersSelected(self):
1117 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().machineSelectPage)
1119 def OnLulzbotMiniSelected(self):
1120 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().lulzbotMiniToolheadPage)
1121 wx.wizard.WizardPageSimple.Chain(self.GetParent().lulzbotMiniToolheadPage,
1122 self.GetParent().lulzbotReadyPage)
1124 def OnLulzbotTazSelected(self):
1125 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().lulzbotTazHotendPage)
1127 def AllowNext(self):
1130 def AllowBack(self):
1133 def StoreData(self):
1134 if self.LulzbotTaz4.GetValue() or self.LulzbotTaz5.GetValue() or self.LulzbotMini.GetValue():
1135 if self.LulzbotTaz4.GetValue():
1136 # Nozzle size will be set in the toolhead selection page
1137 # We set the machine_type here so later pages can differenciate between TAZ 4 and 5
1138 profile.putMachineSetting('machine_width', '290')
1139 profile.putMachineSetting('machine_depth', '275')
1140 profile.putMachineSetting('machine_height', '250')
1141 profile.putMachineSetting('machine_type', 'lulzbot_TAZ_4')
1142 profile.putMachineSetting('serial_baud', '115200')
1143 elif self.LulzbotTaz5.GetValue():
1144 # Nozzle size will be set in the toolhead selection page
1145 # We set the machine_type here so later pages can differenciate between TAZ 4 and 5
1146 profile.putMachineSetting('machine_type', 'lulzbot_TAZ_5')
1147 profile.putMachineSetting('machine_width', '290')
1148 profile.putMachineSetting('machine_depth', '275')
1149 profile.putMachineSetting('machine_height', '250')
1150 profile.putMachineSetting('serial_baud', '115200')
1152 # Nozzle size and machine name/type will be set in the toolhead selection page
1153 profile.putMachineSetting('machine_width', '155')
1154 profile.putMachineSetting('machine_depth', '155')
1155 profile.putMachineSetting('machine_height', '163')
1156 profile.putMachineSetting('serial_baud', '115200')
1157 profile.putMachineSetting('extruder_head_size_min_x', '40')
1158 profile.putMachineSetting('extruder_head_size_max_x', '75')
1159 profile.putMachineSetting('extruder_head_size_min_y', '25')
1160 profile.putMachineSetting('extruder_head_size_max_y', '55')
1161 profile.putMachineSetting('extruder_head_size_height', '17')
1163 profile.putMachineSetting('machine_center_is_zero', 'False')
1164 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
1165 profile.putMachineSetting('has_heated_bed', 'True')
1166 profile.putMachineSetting('extruder_head_size_min_x', '0.0')
1167 profile.putMachineSetting('extruder_head_size_min_y', '0.0')
1168 profile.putMachineSetting('extruder_head_size_max_x', '0.0')
1169 profile.putMachineSetting('extruder_head_size_max_y', '0.0')
1170 profile.putMachineSetting('extruder_head_size_height', '0.0')
1171 profile.putProfileSetting('retraction_enable', 'True')
1172 profile.putPreference('startMode', 'Simple')
1173 profile.putProfileSetting('wall_thickness', float(profile.getProfileSetting('nozzle_size')) * 2)
1174 profile.checkAndUpdateMachineName()
1176 class LulzbotReadyPage(InfoPage):
1177 def __init__(self, parent):
1178 super(LulzbotReadyPage, self).__init__(parent, _("LulzBot TAZ/Mini"))
1179 self.AddBitmap(wx.Bitmap(resources.getPathForImage('Lulzbot_logo.png')))
1180 self.AddText(_('Cura is now ready to be used with your LulzBot 3D printer.'))
1182 self.AddText(_('For more information about using Cura with your LulzBot'))
1183 self.AddText(_('3D printer, please visit www.LulzBot.com/cura'))
1186 class LulzbotToolheadSelectPage(InfoPage):
1187 url='http://lulzbot.com/toolhead-identification'
1189 def __init__(self, parent, title):
1190 super(LulzbotToolheadSelectPage, self).__init__(parent, title)
1192 self.AddBitmap(wx.Bitmap(resources.getPathForImage('Lulzbot_logo.png')))
1194 self.AddText(_('Please select your currently installed Tool Head'))
1195 txt = self.AddText(_('WARNING: Carefully select the right Tool Head.\nFlashing the firmware with the wrong Tool Head can damage your LulzBot printer. Learn more here :'))
1196 txt.SetForegroundColour(wx.RED)
1197 button = self.AddButton(self.url)
1198 button.Bind(wx.EVT_BUTTON, self.OnUrlClick)
1202 def OnUrlClick(self, e):
1203 webbrowser.open(LulzbotMiniToolheadSelectPage.url)
1205 class LulzbotMiniToolheadSelectPage(LulzbotToolheadSelectPage):
1206 def __init__(self, parent, allowBack = True):
1207 super(LulzbotMiniToolheadSelectPage, self).__init__(parent, _("LulzBot Mini Toolhead Selection"))
1209 self.allowBack = allowBack
1210 self.panel = self.AddPanel()
1211 image_size=(LulzbotMachineSelectPage.IMAGE_WIDTH, LulzbotMachineSelectPage.IMAGE_HEIGHT)
1212 self.standard = self.AddImageButton(self.panel, 0, 0, _('Single Extruder v2'),
1213 'Lulzbot_Toolhead_Mini_Standard.jpg', image_size,
1214 style=ImageButton.IB_GROUP)
1215 self.flexy = self.AddImageButton(self.panel, 0, 1, _('Flexystruder v2'),
1216 'Lulzbot_Toolhead_Mini_Flexystruder.jpg', image_size)
1217 self.standard.SetValue(True)
1219 def AllowBack(self):
1220 return self.allowBack
1222 def StoreData(self):
1223 if self.standard.GetValue():
1224 profile.putProfileSetting('nozzle_size', '0.5')
1225 profile.putMachineSetting('extruder_amount', '1')
1226 profile.putMachineSetting('toolhead', 'Single Extruder V2')
1227 profile.putMachineSetting('machine_name', 'LulzBot Mini')
1228 profile.putMachineSetting('machine_type', 'lulzbot_mini')
1230 profile.putProfileSetting('nozzle_size', '0.6')
1231 profile.putMachineSetting('extruder_amount', '1')
1232 profile.putMachineSetting('toolhead', 'Flexystruder V2')
1233 profile.putMachineSetting('machine_name', 'LulzBot Mini (Flexy)')
1234 profile.putMachineSetting('machine_type', 'lulzbot_mini_flexy')
1237 class LulzbotTazToolheadSelectPage(LulzbotToolheadSelectPage):
1238 def __init__(self, parent):
1239 super(LulzbotTazToolheadSelectPage, self).__init__(parent, _("LulzBot TAZ Toolhead Selection"))
1241 self.panel = self.AddPanel()
1242 image_size=(LulzbotMachineSelectPage.IMAGE_WIDTH, LulzbotMachineSelectPage.IMAGE_HEIGHT)
1243 self.single = self.AddImageButton(self.panel, 0, 0, _('Single Extruder v1'),
1244 'Lulzbot_Toolhead_TAZ_Single_v1.jpg', image_size,
1245 style=ImageButton.IB_GROUP)
1246 self.flexy = self.AddImageButton(self.panel, 0, 1, _('Flexystruder v1'),
1247 'Lulzbot_Toolhead_TAZ_Flexystruder_v1.jpg', image_size)
1248 self.dually = self.AddImageButton(self.panel, 1, 0, _('Dual Extruder v1'),
1249 'Lulzbot_Toolhead_TAZ_Dually_v1.jpg', image_size)
1250 self.flexydually = self.AddImageButton(self.panel, 1, 1, _('FlexyDually v1'),
1251 'Lulzbot_Toolhead_TAZ_FlexyDually_v1.jpg', image_size)
1253 self.single.SetValue(True)
1255 def SetVersion(self, version):
1256 image_size=(LulzbotMachineSelectPage.IMAGE_WIDTH, LulzbotMachineSelectPage.IMAGE_HEIGHT)
1257 self.single.SetBitmap(self.GetBitmap('Lulzbot_Toolhead_TAZ_Single_v%d.jpg' % version, image_size))
1258 self.single.SetLabel(_('Single Extruder v%d' % version))
1259 self.flexy.SetBitmap(self.GetBitmap('Lulzbot_Toolhead_TAZ_Flexystruder_v%d.jpg' % version, image_size))
1260 self.flexy.SetLabel(_('Flexystruder v%d' % version))
1261 self.dually.SetBitmap(self.GetBitmap('Lulzbot_Toolhead_TAZ_Dually_v%d.jpg' % version, image_size))
1262 self.dually.SetLabel(_('Dual Extruder v%d' % version))
1263 self.flexydually.SetBitmap(self.GetBitmap('Lulzbot_Toolhead_TAZ_FlexyDually_v%d.jpg' % version, image_size))
1264 self.flexydually.SetLabel(_('FlexyDually v%d' % version))
1265 self.version = version
1267 self.single.OnSelected(None)
1268 self.flexy.OnSelected(None)
1269 self.dually.OnSelected(None)
1270 self.flexydually.OnSelected(None)
1271 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().lulzbotReadyPage)
1273 self.single.OnSelected(self.OnSingleV2)
1274 self.flexy.OnSelected(self.OnNonSingle)
1275 self.dually.OnSelected(self.OnNonSingle)
1276 self.flexydually.OnSelected(self.OnNonSingle)
1277 if self.single.GetValue():
1278 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().lulzbotTaz5NozzleSelectPage)
1279 wx.wizard.WizardPageSimple.Chain(self.GetParent().lulzbotTaz5NozzleSelectPage, self.GetParent().lulzbotReadyPage)
1281 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().lulzbotReadyPage)
1283 def OnSingleV2(self):
1284 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().lulzbotTaz5NozzleSelectPage)
1285 wx.wizard.WizardPageSimple.Chain(self.GetParent().lulzbotTaz5NozzleSelectPage, self.GetParent().lulzbotReadyPage)
1287 def OnNonSingle(self):
1288 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().lulzbotReadyPage)
1290 def StoreData(self):
1291 if profile.getMachineSetting('machine_type').startswith('lulzbot_TAZ_4'):
1295 version = (taz_version, self.version)
1296 if self.single.GetValue():
1297 profile.putProfileSetting('nozzle_size', '0.5' if self.version == 2 else '0.35')
1298 profile.putMachineSetting('extruder_amount', '1')
1299 profile.putMachineSetting('toolhead', 'Single Extruder V%d' % self.version)
1300 profile.putMachineSetting('machine_name', 'LulzBot TAZ %d' % taz_version)
1301 profile.putMachineSetting('machine_type', 'lulzbot_TAZ_%d_SingleV%d' % version)
1302 elif self.flexy.GetValue():
1303 profile.putProfileSetting('nozzle_size', '0.6')
1304 profile.putMachineSetting('extruder_amount', '1')
1305 profile.putMachineSetting('toolhead', 'Flexystruder V%d' % self.version)
1306 profile.putMachineSetting('machine_name', 'LulzBot TAZ %d (Flexy v%d)' % version)
1307 profile.putMachineSetting('machine_type', 'lulzbot_TAZ_%d_flexyV%d' % version)
1308 elif self.dually.GetValue():
1309 profile.putMachineSetting('extruder_amount', '2')
1310 profile.putProfileSetting('nozzle_size', '0.5')
1311 profile.putMachineSetting('toolhead', 'Dual Extruder V%d' % self.version)
1312 profile.putMachineSetting('machine_name', 'LulzBot TAZ %d (Dually v%d)' % version)
1313 profile.putMachineSetting('machine_type', 'lulzbot_TAZ_%d_DuallyV%d' % version)
1314 elif self.flexydually.GetValue():
1315 profile.putProfileSetting('nozzle_size', '0.6')
1316 profile.putMachineSetting('extruder_amount', '2')
1317 profile.putMachineSetting('toolhead', 'FlexyDually V%d' % self.version)
1318 profile.putMachineSetting('machine_name', 'LulzBot TAZ %d (FlexyDually v%d)' % version)
1319 profile.putMachineSetting('machine_type', 'lulzbot_TAZ_%d_FlexyDuallyV%d' % version)
1322 class LulzbotHotendSelectPage(LulzbotToolheadSelectPage):
1323 def __init__(self, parent, allowBack = True):
1324 super(LulzbotHotendSelectPage, self).__init__(parent, _("LulzBot Toolhead Hotend Selection"))
1326 self.allowBack = allowBack
1327 self.panel = self.AddPanel()
1328 image_size=(LulzbotMachineSelectPage.IMAGE_WIDTH, LulzbotMachineSelectPage.IMAGE_HEIGHT)
1329 self.v1 = self.AddImageButton(self.panel, 0, 0, _('v1 (Budaschnozzle Hotends)'),
1330 'Lulzbot_Toolhead_v1.jpg', image_size,
1331 style=ImageButton.IB_GROUP)
1332 self.v2 = self.AddImageButton(self.panel, 0, 1, _('v2 (Hexagon Hotends)'),
1333 'Lulzbot_Toolhead_v2.jpg', image_size)
1334 self.v1.SetValue(True)
1336 def AllowBack(self):
1337 return self.allowBack
1339 def StoreData(self):
1340 self.GetParent().lulzbotTazToolheadPage.SetVersion(1 if self.v1.GetValue() else 2)
1343 class LulzbotTaz5NozzleSelectPage(LulzbotToolheadSelectPage):
1344 url2='http://lulzbot.com/printer-identification'
1346 def __init__(self, parent):
1347 super(LulzbotTaz5NozzleSelectPage, self).__init__(parent, _("LulzBot TAZ Single V2 Nozzle Selection"))
1349 self.AddText(_('Please select your Hexagon hotend\'s nozzle size:'))
1350 self.Nozzle35Radio = self.AddRadioButton("0.35 mm", style=wx.RB_GROUP)
1351 self.Nozzle35Radio.SetValue(True)
1352 self.Nozzle50Radio = self.AddRadioButton("0.5 mm")
1353 self.AddText(_(' '))
1356 self.AddText(_('If you are not sure which nozzle size you have'))
1357 self.AddText(_('please check this webpage: '))
1358 button = self.AddButton(LulzbotTaz5NozzleSelectPage.url2)
1359 button.Bind(wx.EVT_BUTTON, self.OnUrlClick)
1361 def OnUrlClick(self, e):
1362 webbrowser.open(LulzbotTaz5NozzleSelectPage.url2)
1364 def StoreData(self):
1365 if self.Nozzle35Radio.GetValue():
1366 profile.putProfileSetting('nozzle_size', '0.35')
1367 profile.putMachineSetting('toolhead', 'Single Extruder V2 (0.35 nozzle)')
1368 profile.putMachineSetting('machine_name', 'LulzBot TAZ 5 (0.35 nozzle)')
1369 profile.putMachineSetting('machine_type', 'lulzbot_TAZ_5_035nozzle')
1372 profile.putProfileSetting('nozzle_size', '0.5')
1373 profile.putMachineSetting('toolhead', 'Single Extruder V2 (0.5 nozzle)')
1374 profile.putMachineSetting('machine_name', 'LulzBot TAZ 5 (0.5 nozzle)')
1375 profile.putMachineSetting('machine_type', 'lulzbot_TAZ_5_05nozzle')
1377 class LulzbotChangeToolheadWizard(wx.wizard.Wizard):
1379 super(LulzbotChangeToolheadWizard, self).__init__(None, -1, _("Change Lulzbot Toolhead Wizard"))
1381 self._nozzle_size = profile.getProfileSettingFloat('nozzle_size')
1382 self._machine_name = profile.getMachineSetting('machine_name')
1383 self._machine_type = profile.getMachineSetting('machine_type')
1384 self._extruder_amount = int(profile.getMachineSettingFloat('extruder_amount'))
1386 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
1387 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1388 self.Bind(wx.wizard.EVT_WIZARD_CANCEL, self.OnCancel)
1390 self.lulzbotReadyPage = LulzbotReadyPage(self)
1391 self.lulzbotMiniToolheadPage = LulzbotMiniToolheadSelectPage(self, False)
1392 self.lulzbotTazToolheadPage = LulzbotTazToolheadSelectPage(self)
1393 self.lulzbotTazHotendPage = LulzbotHotendSelectPage(self, False)
1394 self.lulzbotTaz5NozzleSelectPage = LulzbotTaz5NozzleSelectPage(self)
1396 wx.wizard.WizardPageSimple.Chain(self.lulzbotMiniToolheadPage, self.lulzbotReadyPage)
1397 wx.wizard.WizardPageSimple.Chain(self.lulzbotTazHotendPage, self.lulzbotTazToolheadPage)
1399 if profile.getMachineSetting('machine_type').startswith('lulzbot_mini'):
1400 self.RunWizard(self.lulzbotMiniToolheadPage)
1402 self.RunWizard(self.lulzbotTazHotendPage)
1405 def OnPageChanging(self, e):
1406 e.GetPage().StoreData()
1408 def OnPageChanged(self, e):
1409 if e.GetPage().AllowNext():
1410 self.FindWindowById(wx.ID_FORWARD).Enable()
1412 self.FindWindowById(wx.ID_FORWARD).Disable()
1413 if e.GetPage().AllowBack():
1414 self.FindWindowById(wx.ID_BACKWARD).Enable()
1416 self.FindWindowById(wx.ID_BACKWARD).Disable()
1418 def OnCancel(self, e):
1419 profile.putProfileSetting('nozzle_size', self._nozzle_size)
1420 profile.putMachineSetting('machine_name', self._machine_name)
1421 profile.putMachineSetting('machine_type', self._machine_type)
1422 profile.putMachineSetting('extruder_amount', self._extruder_amount)
1424 class ConfigWizard(wx.wizard.Wizard):
1425 def __init__(self, addNew = False):
1426 super(ConfigWizard, self).__init__(None, -1, _("Configuration Wizard"))
1428 self._old_machine_index = int(profile.getPreferenceFloat('active_machine'))
1430 profile.setActiveMachine(profile.getMachineCount())
1432 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
1433 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1434 self.Bind(wx.wizard.EVT_WIZARD_CANCEL, self.OnCancel)
1436 self.machineSelectPage = MachineSelectPage(self)
1437 self.ultimakerSelectParts = SelectParts(self)
1438 self.ultimakerFirmwareUpgradePage = UltimakerFirmwareUpgradePage(self)
1439 self.ultimakerCheckupPage = UltimakerCheckupPage(self)
1440 self.ultimakerCalibrationPage = UltimakerCalibrationPage(self)
1441 self.ultimakerCalibrateStepsPerEPage = UltimakerCalibrateStepsPerEPage(self)
1442 self.bedLevelPage = bedLevelWizardMain(self)
1443 self.headOffsetCalibration = headOffsetCalibrationPage(self)
1444 self.printrbotSelectType = PrintrbotPage(self)
1445 self.otherMachineSelectPage = OtherMachineSelectPage(self)
1446 self.customRepRapInfoPage = CustomRepRapInfoPage(self)
1447 self.otherMachineInfoPage = OtherMachineInfoPage(self)
1449 self.ultimaker2ReadyPage = Ultimaker2ReadyPage(self)
1450 self.lulzbotReadyPage = LulzbotReadyPage(self)
1451 self.lulzbotMiniToolheadPage = LulzbotMiniToolheadSelectPage(self)
1452 self.lulzbotTazToolheadPage = LulzbotTazToolheadSelectPage(self)
1453 self.lulzbotTazHotendPage = LulzbotHotendSelectPage(self)
1454 self.lulzbotTaz5NozzleSelectPage = LulzbotTaz5NozzleSelectPage(self)
1455 self.lulzbotMachineSelectPage = LulzbotMachineSelectPage(self)
1457 wx.wizard.WizardPageSimple.Chain(self.lulzbotMachineSelectPage, self.lulzbotMiniToolheadPage)
1458 wx.wizard.WizardPageSimple.Chain(self.lulzbotMiniToolheadPage, self.lulzbotReadyPage)
1459 wx.wizard.WizardPageSimple.Chain(self.lulzbotTazHotendPage, self.lulzbotTazToolheadPage)
1460 wx.wizard.WizardPageSimple.Chain(self.machineSelectPage, self.ultimakerSelectParts)
1461 wx.wizard.WizardPageSimple.Chain(self.ultimakerSelectParts, self.ultimakerFirmwareUpgradePage)
1462 wx.wizard.WizardPageSimple.Chain(self.ultimakerFirmwareUpgradePage, self.ultimakerCheckupPage)
1463 wx.wizard.WizardPageSimple.Chain(self.ultimakerCheckupPage, self.bedLevelPage)
1464 wx.wizard.WizardPageSimple.Chain(self.printrbotSelectType, self.otherMachineInfoPage)
1465 wx.wizard.WizardPageSimple.Chain(self.otherMachineSelectPage, self.customRepRapInfoPage)
1467 self.RunWizard(self.lulzbotMachineSelectPage)
1470 def OnPageChanging(self, e):
1471 e.GetPage().StoreData()
1473 def OnPageChanged(self, e):
1474 if e.GetPage().AllowNext():
1475 self.FindWindowById(wx.ID_FORWARD).Enable()
1477 self.FindWindowById(wx.ID_FORWARD).Disable()
1478 if e.GetPage().AllowBack():
1479 self.FindWindowById(wx.ID_BACKWARD).Enable()
1481 self.FindWindowById(wx.ID_BACKWARD).Disable()
1483 def OnCancel(self, e):
1484 new_machine_index = int(profile.getPreferenceFloat('active_machine'))
1485 profile.setActiveMachine(self._old_machine_index)
1486 profile.removeMachine(new_machine_index)
1488 class bedLevelWizardMain(InfoPage):
1489 def __init__(self, parent):
1490 super(bedLevelWizardMain, self).__init__(parent, _("Bed leveling wizard"))
1492 self.AddText(_('This wizard will help you in leveling your printer bed'))
1494 self.AddText(_('It will do the following steps'))
1495 self.AddText(_('* Move the printer head to each corner'))
1496 self.AddText(_(' and let you adjust the height of the bed to the nozzle'))
1497 self.AddText(_('* Print a line around the bed to check if it is level'))
1500 self.connectButton = self.AddButton(_('Connect to printer'))
1503 self.infoBox = self.AddInfoBox()
1504 self.resumeButton = self.AddButton(_('Resume'))
1505 self.upButton, self.downButton = self.AddDualButton(_('Up 0.2mm'), _('Down 0.2mm'))
1506 self.upButton2, self.downButton2 = self.AddDualButton(_('Up 10mm'), _('Down 10mm'))
1507 self.resumeButton.Enable(False)
1509 self.upButton.Enable(False)
1510 self.downButton.Enable(False)
1511 self.upButton2.Enable(False)
1512 self.downButton2.Enable(False)
1514 self.Bind(wx.EVT_BUTTON, self.OnConnect, self.connectButton)
1515 self.Bind(wx.EVT_BUTTON, self.OnResume, self.resumeButton)
1516 self.Bind(wx.EVT_BUTTON, self.OnBedUp, self.upButton)
1517 self.Bind(wx.EVT_BUTTON, self.OnBedDown, self.downButton)
1518 self.Bind(wx.EVT_BUTTON, self.OnBedUp2, self.upButton2)
1519 self.Bind(wx.EVT_BUTTON, self.OnBedDown2, self.downButton2)
1521 def OnConnect(self, e = None):
1522 if self.comm is not None:
1526 wx.CallAfter(self.OnConnect)
1528 self.connectButton.Enable(False)
1529 self.comm = machineCom.MachineCom(callbackObject=self)
1530 self.infoBox.SetBusy(_('Connecting to machine.'))
1531 self._wizardState = 0
1533 def OnBedUp(self, e):
1534 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1535 self.comm.sendCommand('G92 Z10')
1536 self.comm.sendCommand('G1 Z9.8 F%d' % (feedZ))
1537 self.comm.sendCommand('M400')
1539 def OnBedDown(self, e):
1540 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1541 self.comm.sendCommand('G92 Z10')
1542 self.comm.sendCommand('G1 Z10.2 F%d' % (feedZ))
1543 self.comm.sendCommand('M400')
1545 def OnBedUp2(self, e):
1546 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1547 self.comm.sendCommand('G92 Z10')
1548 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1549 self.comm.sendCommand('M400')
1551 def OnBedDown2(self, e):
1552 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1553 self.comm.sendCommand('G92 Z10')
1554 self.comm.sendCommand('G1 Z20 F%d' % (feedZ))
1555 self.comm.sendCommand('M400')
1557 def AllowNext(self):
1558 if self.GetParent().headOffsetCalibration is not None and int(profile.getMachineSetting('extruder_amount')) > 1:
1559 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().headOffsetCalibration)
1562 def OnResume(self, e):
1563 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1564 feedTravel = profile.getProfileSettingFloat('travel_speed') * 60
1565 if self._wizardState == -1:
1566 wx.CallAfter(self.infoBox.SetInfo, _('Homing printer...'))
1567 wx.CallAfter(self.upButton.Enable, False)
1568 wx.CallAfter(self.downButton.Enable, False)
1569 wx.CallAfter(self.upButton2.Enable, False)
1570 wx.CallAfter(self.downButton2.Enable, False)
1571 self.comm.sendCommand('M105')
1572 self.comm.sendCommand('G28')
1573 self._wizardState = 1
1574 elif self._wizardState == 2:
1575 if profile.getMachineSetting('has_heated_bed') == 'True':
1576 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to back center...'))
1577 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1578 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') / 2.0, profile.getMachineSettingFloat('machine_depth'), feedTravel))
1579 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1580 self.comm.sendCommand('M400')
1581 self._wizardState = 3
1583 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to back left corner...'))
1584 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1585 self.comm.sendCommand('G1 X%d Y%d F%d' % (0, profile.getMachineSettingFloat('machine_depth'), feedTravel))
1586 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1587 self.comm.sendCommand('M400')
1588 self._wizardState = 3
1589 elif self._wizardState == 4:
1590 if profile.getMachineSetting('has_heated_bed') == 'True':
1591 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to front right corner...'))
1592 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1593 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') - 5.0, 5, feedTravel))
1594 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1595 self.comm.sendCommand('M400')
1596 self._wizardState = 7
1598 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to back right corner...'))
1599 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1600 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') - 5.0, profile.getMachineSettingFloat('machine_depth') - 25, feedTravel))
1601 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1602 self.comm.sendCommand('M400')
1603 self._wizardState = 5
1604 elif self._wizardState == 6:
1605 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to front right corner...'))
1606 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1607 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') - 5.0, 20, feedTravel))
1608 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1609 self.comm.sendCommand('M400')
1610 self._wizardState = 7
1611 elif self._wizardState == 8:
1612 wx.CallAfter(self.infoBox.SetBusy, _('Heating up printer...'))
1613 self.comm.sendCommand('G1 Z15 F%d' % (feedZ))
1614 self.comm.sendCommand('M104 S%d' % (profile.getProfileSettingFloat('print_temperature')))
1615 self.comm.sendCommand('G1 X%d Y%d F%d' % (0, 0, feedTravel))
1616 self._wizardState = 9
1617 elif self._wizardState == 10:
1618 self._wizardState = 11
1619 wx.CallAfter(self.infoBox.SetInfo, _('Printing a square on the printer bed at 0.3mm height.'))
1620 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1621 feedPrint = profile.getProfileSettingFloat('print_speed') * 60
1622 feedTravel = profile.getProfileSettingFloat('travel_speed') * 60
1623 w = profile.getMachineSettingFloat('machine_width') - 10
1624 d = profile.getMachineSettingFloat('machine_depth')
1625 filamentRadius = profile.getProfileSettingFloat('filament_diameter') / 2
1626 filamentArea = math.pi * filamentRadius * filamentRadius
1627 ePerMM = (profile.calculateEdgeWidth() * 0.3) / filamentArea
1631 'G1 Z2 F%d' % (feedZ),
1633 'G1 X%d Y%d F%d' % (5, 5, feedTravel),
1634 'G1 Z0.3 F%d' % (feedZ)]
1636 gcodeList.append('G1 E%f F%d' % (eValue, profile.getProfileSettingFloat('retraction_speed') * 60))
1638 for i in xrange(0, 3):
1639 dist = 5.0 + 0.4 * float(i)
1640 eValue += (d - 2.0*dist) * ePerMM
1641 gcodeList.append('G1 X%f Y%f E%f F%d' % (dist, d - dist, eValue, feedPrint))
1642 eValue += (w - 2.0*dist) * ePerMM
1643 gcodeList.append('G1 X%f Y%f E%f F%d' % (w - dist, d - dist, eValue, feedPrint))
1644 eValue += (d - 2.0*dist) * ePerMM
1645 gcodeList.append('G1 X%f Y%f E%f F%d' % (w - dist, dist, eValue, feedPrint))
1646 eValue += (w - 2.0*dist) * ePerMM
1647 gcodeList.append('G1 X%f Y%f E%f F%d' % (dist, dist, eValue, feedPrint))
1649 gcodeList.append('M400')
1650 self.comm.printGCode(gcodeList)
1651 self.resumeButton.Enable(False)
1653 def mcLog(self, message):
1654 print 'Log:', message
1656 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
1657 if self._wizardState == 1:
1658 self._wizardState = 2
1659 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the front left screw of your printer bed\nSo the nozzle just hits the bed.'))
1660 wx.CallAfter(self.resumeButton.Enable, True)
1661 elif self._wizardState == 3:
1662 self._wizardState = 4
1663 if profile.getMachineSetting('has_heated_bed') == 'True':
1664 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the back screw of your printer bed\nSo the nozzle just hits the bed.'))
1666 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the back left screw of your printer bed\nSo the nozzle just hits the bed.'))
1667 wx.CallAfter(self.resumeButton.Enable, True)
1668 elif self._wizardState == 5:
1669 self._wizardState = 6
1670 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the back right screw of your printer bed\nSo the nozzle just hits the bed.'))
1671 wx.CallAfter(self.resumeButton.Enable, True)
1672 elif self._wizardState == 7:
1673 self._wizardState = 8
1674 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the front right screw of your printer bed\nSo the nozzle just hits the bed.'))
1675 wx.CallAfter(self.resumeButton.Enable, True)
1676 elif self._wizardState == 9:
1677 if temp[0] < profile.getProfileSettingFloat('print_temperature') - 5:
1678 wx.CallAfter(self.infoBox.SetInfo, _('Heating up printer: %d/%d') % (temp[0], profile.getProfileSettingFloat('print_temperature')))
1680 wx.CallAfter(self.infoBox.SetAttention, _('The printer is hot now. Please insert some PLA filament into the printer.'))
1681 wx.CallAfter(self.resumeButton.Enable, True)
1682 self._wizardState = 10
1684 def mcStateChange(self, state):
1685 if self.comm is None:
1687 if self.comm.isOperational():
1688 if self._wizardState == 0:
1689 wx.CallAfter(self.infoBox.SetAttention, _('Use the up/down buttons to move the bed and adjust your Z endstop.'))
1690 wx.CallAfter(self.upButton.Enable, True)
1691 wx.CallAfter(self.downButton.Enable, True)
1692 wx.CallAfter(self.upButton2.Enable, True)
1693 wx.CallAfter(self.downButton2.Enable, True)
1694 wx.CallAfter(self.resumeButton.Enable, True)
1695 self._wizardState = -1
1696 elif self._wizardState == 11 and not self.comm.isPrinting():
1697 self.comm.sendCommand('G1 Z15 F%d' % (profile.getProfileSettingFloat('print_speed') * 60))
1698 self.comm.sendCommand('G92 E0')
1699 self.comm.sendCommand('G1 E-10 F%d' % (profile.getProfileSettingFloat('retraction_speed') * 60))
1700 self.comm.sendCommand('M104 S0')
1701 wx.CallAfter(self.infoBox.SetInfo, _('Calibration finished.\nThe squares on the bed should slightly touch each other.'))
1702 wx.CallAfter(self.infoBox.SetReadyIndicator)
1703 wx.CallAfter(self.GetParent().FindWindowById(wx.ID_FORWARD).Enable)
1704 wx.CallAfter(self.connectButton.Enable, True)
1705 self._wizardState = 12
1706 elif self.comm.isError():
1707 wx.CallAfter(self.infoBox.SetError, _('Failed to establish connection with the printer.'), 'http://wiki.ultimaker.com/Cura:_Connection_problems')
1709 def mcMessage(self, message):
1712 def mcProgress(self, lineNr):
1715 def mcZChange(self, newZ):
1718 class headOffsetCalibrationPage(InfoPage):
1719 def __init__(self, parent):
1720 super(headOffsetCalibrationPage, self).__init__(parent, _("Printer head offset calibration"))
1722 self.AddText(_('This wizard will help you in calibrating the printer head offsets of your dual extrusion machine'))
1725 self.connectButton = self.AddButton(_('Connect to printer'))
1728 self.infoBox = self.AddInfoBox()
1729 self.textEntry = self.AddTextCtrl('')
1730 self.textEntry.Enable(False)
1731 self.resumeButton = self.AddButton(_('Resume'))
1732 self.resumeButton.Enable(False)
1734 self.Bind(wx.EVT_BUTTON, self.OnConnect, self.connectButton)
1735 self.Bind(wx.EVT_BUTTON, self.OnResume, self.resumeButton)
1737 def AllowBack(self):
1740 def OnConnect(self, e = None):
1741 if self.comm is not None:
1745 wx.CallAfter(self.OnConnect)
1747 self.connectButton.Enable(False)
1748 self.comm = machineCom.MachineCom(callbackObject=self)
1749 self.infoBox.SetBusy(_('Connecting to machine.'))
1750 self._wizardState = 0
1752 def OnResume(self, e):
1753 if self._wizardState == 2:
1754 self._wizardState = 3
1755 wx.CallAfter(self.infoBox.SetBusy, _('Printing initial calibration cross'))
1757 w = profile.getMachineSettingFloat('machine_width')
1758 d = profile.getMachineSettingFloat('machine_depth')
1760 gcode = gcodeGenerator.gcodeGenerator()
1761 gcode.setExtrusionRate(profile.getProfileSettingFloat('nozzle_size') * 1.5, 0.2)
1762 gcode.setPrintSpeed(profile.getProfileSettingFloat('bottom_layer_speed'))
1769 gcode.addMove(w/2, 5)
1770 gcode.addMove(z=0.2)
1772 gcode.addExtrude(w/2, d-5.0)
1774 gcode.addMove(5, d/2)
1776 gcode.addExtrude(w-5.0, d/2)
1777 gcode.addRetract(15)
1780 gcode.addMove(w/2, 5)
1782 gcode.addExtrude(w/2, d-5.0)
1784 gcode.addMove(5, d/2)
1786 gcode.addExtrude(w-5.0, d/2)
1787 gcode.addRetract(15)
1792 gcode.addCmd('M400')
1794 self.comm.printGCode(gcode.list())
1795 self.resumeButton.Enable(False)
1796 elif self._wizardState == 4:
1798 float(self.textEntry.GetValue())
1801 profile.putPreference('extruder_offset_x1', self.textEntry.GetValue())
1802 self._wizardState = 5
1803 self.infoBox.SetAttention(_('Please measure the distance between the horizontal lines in millimeters.'))
1804 self.textEntry.SetValue('0.0')
1805 self.textEntry.Enable(True)
1806 elif self._wizardState == 5:
1808 float(self.textEntry.GetValue())
1811 profile.putPreference('extruder_offset_y1', self.textEntry.GetValue())
1812 self._wizardState = 6
1813 self.infoBox.SetBusy(_('Printing the fine calibration lines.'))
1814 self.textEntry.SetValue('')
1815 self.textEntry.Enable(False)
1816 self.resumeButton.Enable(False)
1818 x = profile.getMachineSettingFloat('extruder_offset_x1')
1819 y = profile.getMachineSettingFloat('extruder_offset_y1')
1820 gcode = gcodeGenerator.gcodeGenerator()
1821 gcode.setExtrusionRate(profile.getProfileSettingFloat('nozzle_size') * 1.5, 0.2)
1822 gcode.setPrintSpeed(25)
1825 gcode.addMove(50, 40, 0.2)
1827 for n in xrange(0, 10):
1828 gcode.addExtrude(50 + n * 10, 150)
1829 gcode.addExtrude(50 + n * 10 + 5, 150)
1830 gcode.addExtrude(50 + n * 10 + 5, 40)
1831 gcode.addExtrude(50 + n * 10 + 10, 40)
1832 gcode.addMove(40, 50)
1833 for n in xrange(0, 10):
1834 gcode.addExtrude(150, 50 + n * 10)
1835 gcode.addExtrude(150, 50 + n * 10 + 5)
1836 gcode.addExtrude(40, 50 + n * 10 + 5)
1837 gcode.addExtrude(40, 50 + n * 10 + 10)
1838 gcode.addRetract(15)
1841 gcode.addMove(50 - x, 30 - y, 0.2)
1843 for n in xrange(0, 10):
1844 gcode.addExtrude(50 + n * 10.2 - 1.0 - x, 140 - y)
1845 gcode.addExtrude(50 + n * 10.2 - 1.0 + 5.1 - x, 140 - y)
1846 gcode.addExtrude(50 + n * 10.2 - 1.0 + 5.1 - x, 30 - y)
1847 gcode.addExtrude(50 + n * 10.2 - 1.0 + 10 - x, 30 - y)
1848 gcode.addMove(30 - x, 50 - y, 0.2)
1849 for n in xrange(0, 10):
1850 gcode.addExtrude(160 - x, 50 + n * 10.2 - 1.0 - y)
1851 gcode.addExtrude(160 - x, 50 + n * 10.2 - 1.0 + 5.1 - y)
1852 gcode.addExtrude(30 - x, 50 + n * 10.2 - 1.0 + 5.1 - y)
1853 gcode.addExtrude(30 - x, 50 + n * 10.2 - 1.0 + 10 - y)
1854 gcode.addRetract(15)
1856 gcode.addCmd('M400')
1857 gcode.addCmd('M104 T0 S0')
1858 gcode.addCmd('M104 T1 S0')
1859 self.comm.printGCode(gcode.list())
1860 elif self._wizardState == 7:
1862 n = int(self.textEntry.GetValue()) - 1
1865 x = profile.getMachineSettingFloat('extruder_offset_x1')
1867 profile.putPreference('extruder_offset_x1', '%0.2f' % (x))
1868 self.infoBox.SetAttention(_('Which horizontal line number lays perfect on top of each other? Front most line is zero.'))
1869 self.textEntry.SetValue('10')
1870 self._wizardState = 8
1871 elif self._wizardState == 8:
1873 n = int(self.textEntry.GetValue()) - 1
1876 y = profile.getMachineSettingFloat('extruder_offset_y1')
1878 profile.putPreference('extruder_offset_y1', '%0.2f' % (y))
1879 self.infoBox.SetInfo(_('Calibration finished. Offsets are: %s %s') % (profile.getMachineSettingFloat('extruder_offset_x1'), profile.getMachineSettingFloat('extruder_offset_y1')))
1880 self.infoBox.SetReadyIndicator()
1881 self._wizardState = 8
1883 self.resumeButton.Enable(False)
1885 def mcLog(self, message):
1886 print 'Log:', message
1888 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
1889 if self._wizardState == 1:
1890 if temp[0] >= 210 and temp[1] >= 210:
1891 self._wizardState = 2
1892 wx.CallAfter(self.infoBox.SetAttention, _('Please load both extruders with PLA.'))
1893 wx.CallAfter(self.resumeButton.Enable, True)
1894 wx.CallAfter(self.resumeButton.SetFocus)
1896 def mcStateChange(self, state):
1897 if self.comm is None:
1899 if self.comm.isOperational():
1900 if self._wizardState == 0:
1901 wx.CallAfter(self.infoBox.SetInfo, _('Homing printer and heating up both extruders.'))
1902 self.comm.sendCommand('M105')
1903 self.comm.sendCommand('M104 S220 T0')
1904 self.comm.sendCommand('M104 S220 T1')
1905 self.comm.sendCommand('G28')
1906 self.comm.sendCommand('G1 Z15 F%d' % (profile.getProfileSettingFloat('print_speed') * 60))
1907 self._wizardState = 1
1908 if not self.comm.isPrinting():
1909 if self._wizardState == 3:
1910 self._wizardState = 4
1911 wx.CallAfter(self.infoBox.SetAttention, _('Please measure the distance between the vertical lines in millimeters.'))
1912 wx.CallAfter(self.textEntry.SetValue, '0.0')
1913 wx.CallAfter(self.textEntry.Enable, True)
1914 wx.CallAfter(self.resumeButton.Enable, True)
1915 wx.CallAfter(self.resumeButton.SetFocus)
1916 elif self._wizardState == 6:
1917 self._wizardState = 7
1918 wx.CallAfter(self.infoBox.SetAttention, _('Which vertical line number lays perfect on top of each other? Leftmost line is zero.'))
1919 wx.CallAfter(self.textEntry.SetValue, '10')
1920 wx.CallAfter(self.textEntry.Enable, True)
1921 wx.CallAfter(self.resumeButton.Enable, True)
1922 wx.CallAfter(self.resumeButton.SetFocus)
1924 elif self.comm.isError():
1925 wx.CallAfter(self.infoBox.SetError, _('Failed to establish connection with the printer.'), 'http://wiki.ultimaker.com/Cura:_Connection_problems')
1927 def mcMessage(self, message):
1930 def mcProgress(self, lineNr):
1933 def mcZChange(self, newZ):
1936 class bedLevelWizard(wx.wizard.Wizard):
1938 super(bedLevelWizard, self).__init__(None, -1, _("Bed leveling wizard"))
1940 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
1941 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1943 self.mainPage = bedLevelWizardMain(self)
1944 self.headOffsetCalibration = None
1946 self.RunWizard(self.mainPage)
1949 def OnPageChanging(self, e):
1950 e.GetPage().StoreData()
1952 def OnPageChanged(self, e):
1953 if e.GetPage().AllowNext():
1954 self.FindWindowById(wx.ID_FORWARD).Enable()
1956 self.FindWindowById(wx.ID_FORWARD).Disable()
1957 if e.GetPage().AllowBack():
1958 self.FindWindowById(wx.ID_BACKWARD).Enable()
1960 self.FindWindowById(wx.ID_BACKWARD).Disable()
1962 class headOffsetWizard(wx.wizard.Wizard):
1964 super(headOffsetWizard, self).__init__(None, -1, _("Head offset wizard"))
1966 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
1967 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1969 self.mainPage = headOffsetCalibrationPage(self)
1971 self.RunWizard(self.mainPage)
1974 def OnPageChanging(self, e):
1975 e.GetPage().StoreData()
1977 def OnPageChanged(self, e):
1978 if e.GetPage().AllowNext():
1979 self.FindWindowById(wx.ID_FORWARD).Enable()
1981 self.FindWindowById(wx.ID_FORWARD).Disable()
1982 if e.GetPage().AllowBack():
1983 self.FindWindowById(wx.ID_BACKWARD).Enable()
1985 self.FindWindowById(wx.ID_BACKWARD).Disable()