1 from __future__ import absolute_import
4 import wx, os, platform, types, webbrowser
6 from gui import configBase
7 from gui import preview3d
8 from gui import sliceProgessPanel
9 from gui import preferencesDialog
10 from gui import configWizard
11 from gui import firmwareInstall
12 from gui import printWindow
14 from util import validators
15 from util import profile
16 from util import version
17 from util import sliceRun
19 class simpleModeWindow(configBase.configWindowBase):
20 "Main user interface window for Quickprint mode"
22 super(simpleModeWindow, self).__init__(title='Cura - Quickprint - ' + version.getVersion())
24 wx.EVT_CLOSE(self, self.OnClose)
25 #self.SetIcon(icon.getMainIcon())
27 menubar = wx.MenuBar()
29 i = fileMenu.Append(-1, 'Load model file...')
30 self.Bind(wx.EVT_MENU, self.OnLoadModel, i)
31 fileMenu.AppendSeparator()
32 i = fileMenu.Append(-1, 'Preferences...')
33 self.Bind(wx.EVT_MENU, self.OnPreferences, i)
34 fileMenu.AppendSeparator()
35 i = fileMenu.Append(wx.ID_EXIT, 'Quit')
36 self.Bind(wx.EVT_MENU, self.OnQuit, i)
37 menubar.Append(fileMenu, '&File')
40 i = toolsMenu.Append(-1, 'Switch to Normal mode...')
41 self.Bind(wx.EVT_MENU, self.OnNormalSwitch, i)
42 menubar.Append(toolsMenu, 'Normal mode')
45 i = helpMenu.Append(-1, 'Online documentation...')
46 self.Bind(wx.EVT_MENU, lambda e: webbrowser.open('https://daid.github.com/Cura'), i)
47 i = helpMenu.Append(-1, 'Report a problem...')
48 self.Bind(wx.EVT_MENU, lambda e: webbrowser.open('https://github.com/daid/Cura/issues'), i)
49 menubar.Append(helpMenu, 'Help')
50 self.SetMenuBar(menubar)
52 if profile.getPreference('lastFile') != '':
53 self.filelist = profile.getPreference('lastFile').split(';')
54 self.SetTitle(self.filelist[-1] + ' - Cura - ' + version.getVersion())
57 self.progressPanelList = []
60 self.preview3d = preview3d.previewPanel(self)
62 configPanel = wx.Panel(self)
63 self.printTypeNormal = wx.RadioButton(configPanel, -1, 'Normal quality print', style=wx.RB_GROUP)
64 self.printTypeLow = wx.RadioButton(configPanel, -1, 'Fast low quality print')
65 self.printTypeHigh = wx.RadioButton(configPanel, -1, 'High quality print')
66 self.printTypeJoris = wx.RadioButton(configPanel, -1, 'Thin walled cup or vase')
68 self.printMaterialPLA = wx.RadioButton(configPanel, -1, 'PLA', style=wx.RB_GROUP)
69 self.printMaterialABS = wx.RadioButton(configPanel, -1, 'ABS')
70 self.printMaterialDiameter = wx.TextCtrl(configPanel, -1, profile.getProfileSetting('filament_diameter'))
72 self.printSupport = wx.CheckBox(configPanel, -1, 'Print support structure')
74 sizer = wx.GridBagSizer()
75 configPanel.SetSizer(sizer)
77 sb = wx.StaticBox(configPanel, label="Select a print type:")
78 boxsizer = wx.StaticBoxSizer(sb, wx.VERTICAL)
79 boxsizer.Add(self.printTypeNormal)
80 boxsizer.Add(self.printTypeLow)
81 boxsizer.Add(self.printTypeHigh)
82 boxsizer.Add(self.printTypeJoris)
83 sizer.Add(boxsizer, (0,0), flag=wx.EXPAND)
85 sb = wx.StaticBox(configPanel, label="Material:")
86 boxsizer = wx.StaticBoxSizer(sb, wx.VERTICAL)
87 boxsizer.Add(self.printMaterialPLA)
88 boxsizer.Add(self.printMaterialABS)
89 boxsizer.Add(wx.StaticText(configPanel, -1, 'Diameter:'))
90 boxsizer.Add(self.printMaterialDiameter)
91 sizer.Add(boxsizer, (1,0), flag=wx.EXPAND)
93 sb = wx.StaticBox(configPanel, label="Other:")
94 boxsizer = wx.StaticBoxSizer(sb, wx.VERTICAL)
95 boxsizer.Add(self.printSupport)
96 sizer.Add(boxsizer, (2,0), flag=wx.EXPAND)
98 # load and slice buttons.
99 loadButton = wx.Button(self, -1, 'Load Model')
100 sliceButton = wx.Button(self, -1, 'Prepare print')
101 printButton = wx.Button(self, -1, 'Print')
102 self.Bind(wx.EVT_BUTTON, self.OnLoadModel, loadButton)
103 self.Bind(wx.EVT_BUTTON, self.OnSlice, sliceButton)
104 self.Bind(wx.EVT_BUTTON, self.OnPrint, printButton)
105 #Also bind double clicking the 3D preview to load an STL file.
106 self.preview3d.glCanvas.Bind(wx.EVT_LEFT_DCLICK, self.OnLoadModel, self.preview3d.glCanvas)
108 #Main sizer, to position the preview window, buttons and tab control
109 sizer = wx.GridBagSizer()
111 sizer.Add(configPanel, (0,0), span=(1,1), flag=wx.EXPAND)
112 sizer.Add(self.preview3d, (0,1), span=(1,3), flag=wx.EXPAND)
113 sizer.AddGrowableCol(2)
114 sizer.AddGrowableRow(0)
115 sizer.Add(loadButton, (1,1), flag=wx.RIGHT, border=5)
116 sizer.Add(sliceButton, (1,2), flag=wx.RIGHT, border=5)
117 sizer.Add(printButton, (1,3), flag=wx.RIGHT, border=5)
120 if len(self.filelist) > 0:
121 self.preview3d.loadModelFiles(self.filelist)
123 self.updateProfileToControls()
126 self.SetMinSize(self.GetSize())
130 def OnPreferences(self, e):
131 prefDialog = preferencesDialog.preferencesDialog(self)
133 prefDialog.Show(True)
135 def OnDefaultMarlinFirmware(self, e):
136 firmwareInstall.InstallFirmware()
138 def OnCustomFirmware(self, e):
139 dlg=wx.FileDialog(self, "Open firmware to upload", os.path.split(profile.getPreference('lastFile'))[0], style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST)
140 dlg.SetWildcard("HEX file (*.hex)|*.hex;*.HEX")
141 if dlg.ShowModal() == wx.ID_OK:
142 filename = dlg.GetPath()
143 if not(os.path.exists(filename)):
145 #For some reason my Ubuntu 10.10 crashes here.
146 firmwareInstall.InstallFirmware(filename)
148 def OnFirstRunWizard(self, e):
149 configWizard.configWizard()
150 self.updateProfileToControls()
152 def OnLoadModel(self, e):
153 dlg=wx.FileDialog(self, "Open file to print", os.path.split(profile.getPreference('lastFile'))[0], style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST)
154 dlg.SetWildcard(meshLoader.wildcardFilter())
155 if dlg.ShowModal() == wx.ID_OK:
156 self.filelist = [dlg.GetPath()]
157 profile.putPreference('lastFile', ';'.join(self.filelist))
158 self.preview3d.loadModelFiles(self.filelist, True)
159 self.preview3d.setViewMode("Normal")
162 def OnSlice(self, e):
163 if len(self.filelist) < 1:
164 wx.MessageBox('You need to load a file before you can prepare it.', 'Print error', wx.OK | wx.ICON_INFORMATION)
166 #save the current profile so we can put it back latter
167 oldProfile = profile.getGlobalProfileString()
169 put = profile.putProfileSetting
170 get = profile.getProfileSetting
172 put('layer_height', '0.2')
173 put('wall_thickness', '0.8')
174 put('solid_layer_thickness', '0.6')
175 put('fill_density', '20')
176 put('skirt_line_count', '1')
177 put('skirt_gap', '6.0')
178 put('print_speed', '50')
179 put('print_temperature', '220')
180 put('support', 'None')
181 #put('machine_center_x', '100')
182 #put('machine_center_y', '100')
183 put('retraction_enable', 'False')
184 put('retraction_min_travel', '5.0')
185 put('retraction_speed', '40.0')
186 put('retraction_amount', '4.5')
187 put('retraction_extra', '0.0')
188 put('travel_speed', '150')
189 put('max_z_speed', '3.0')
190 put('bottom_layer_speed', '25')
191 put('cool_min_layer_time', '10')
192 put('fan_enabled', 'True')
193 put('fan_layer', '1')
194 put('fan_speed', '100')
195 #put('model_scale', '1.0')
196 #put('flip_x', 'False')
197 #put('flip_y', 'False')
198 #put('flip_z', 'False')
199 #put('model_rotate_base', '0')
200 #put('model_multiply_x', '1')
201 #put('model_multiply_y', '1')
202 put('extra_base_wall_thickness', '0.0')
203 put('sequence', 'Loops > Perimeter > Infill')
204 put('force_first_layer_sequence', 'True')
205 put('infill_type', 'Line')
206 put('solid_top', 'True')
207 put('fill_overlap', '15')
208 put('support_rate', '50')
209 put('support_distance', '0.5')
210 put('joris', 'False')
211 put('cool_min_feedrate', '5')
212 put('bridge_speed', '100')
213 put('raft_margin', '5')
214 put('raft_base_material_amount', '100')
215 put('raft_interface_material_amount', '100')
216 put('bottom_thickness', '0.0')
218 if self.printSupport.GetValue():
219 put('support', 'Exterior Only')
221 nozzle_size = float(get('nozzle_size'))
222 if self.printTypeNormal.GetValue():
223 put('wall_thickness', nozzle_size * 2.0)
224 put('layer_height', '0.2')
225 put('fill_density', '20')
226 elif self.printTypeLow.GetValue():
227 put('wall_thickness', nozzle_size * 1.0)
228 put('layer_height', '0.3')
229 put('fill_density', '10')
230 put('print_speed', '80')
231 put('bottom_layer_speed', '40')
232 elif self.printTypeHigh.GetValue():
233 put('wall_thickness', nozzle_size * 2.0)
234 put('layer_height', '0.1')
235 put('fill_density', '30')
236 put('bottom_layer_speed', '15')
237 put('bottom_thickness', '0.2')
238 elif self.printTypeJoris.GetValue():
239 put('wall_thickness', nozzle_size * 1.5)
240 put('layer_height', '0.3')
241 put('solid_layer_thickness', '0.9')
242 put('fill_density', '0')
244 put('extra_base_wall_thickness', '15.0')
245 put('sequence', 'Infill > Loops > Perimeter')
246 put('force_first_layer_sequence', 'False')
247 put('solid_top', 'False')
248 put('support', 'None')
249 put('cool_min_layer_time', '3')
251 put('filament_diameter', self.printMaterialDiameter.GetValue())
252 if self.printMaterialPLA.GetValue():
253 put('filament_density', '1.00')
254 put('enable_raft', 'False')
255 put('skirt_line_count', '1')
256 if self.printMaterialABS.GetValue():
257 put('filament_density', '0.85')
258 put('enable_raft', 'True')
259 put('skirt_line_count', '0')
260 put('fan_layer', '1')
261 put('bottom_thickness', '0.0')
262 put('print_temperature', '260')
264 #Create a progress panel and add it to the window. The progress panel will start the Skein operation.
265 spp = sliceProgessPanel.sliceProgessPanel(self, self, self.filelist)
266 self.sizer.Add(spp, (len(self.progressPanelList)+2,0), span=(1,4), flag=wx.EXPAND)
268 newSize = self.GetSize();
269 newSize.IncBy(0, spp.GetSize().GetHeight())
270 self.SetSize(newSize)
271 self.progressPanelList.append(spp)
273 #Restore the old profile.
274 profile.loadGlobalProfileFromString(oldProfile)
276 def OnPrint(self, e):
277 if len(self.filelist) < 1:
278 wx.MessageBox('You need to load a file and prepare it before you can print.', 'Print error', wx.OK | wx.ICON_INFORMATION)
280 if not os.path.exists(sliceRun.getExportFilename(self.filelist[0])):
281 wx.MessageBox('You need to prepare the file before you can print.', 'Print error', wx.OK | wx.ICON_INFORMATION)
283 printWindow.printFile(sliceRun.getExportFilename(self.filelist[0]))
285 def OnNormalSwitch(self, e):
286 from gui import mainWindow
287 profile.putPreference('startMode', 'Normal')
288 mainWindow.mainWindow()
291 def removeSliceProgress(self, spp):
292 self.progressPanelList.remove(spp)
293 newSize = self.GetSize();
294 newSize.IncBy(0, -spp.GetSize().GetHeight())
295 self.SetSize(newSize)
296 self.sizer.Remove(spp)
298 for spp in self.progressPanelList:
299 self.sizer.Remove(spp)
301 for spp in self.progressPanelList:
302 self.sizer.Add(spp, (i,0), span=(1,4), flag=wx.EXPAND)
309 def OnClose(self, e):
312 def updateProfileToControls(self):
313 super(simpleModeWindow, self).updateProfileToControls()
314 self.preview3d.updateProfileToControls()