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 validators
10 from gui import preferencesDialog
11 from gui import configWizard
12 from gui import firmwareInstall
13 from gui import printWindow
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')
39 expertMenu = wx.Menu()
40 i = expertMenu.Append(-1, 'Switch to Normal mode...')
41 self.Bind(wx.EVT_MENU, self.OnNormalSwitch, i)
42 expertMenu.AppendSeparator()
43 i = expertMenu.Append(-1, 'ReRun first run wizard...')
44 self.Bind(wx.EVT_MENU, self.OnFirstRunWizard, i)
45 menubar.Append(expertMenu, 'Expert')
48 i = helpMenu.Append(-1, 'Online documentation...')
49 self.Bind(wx.EVT_MENU, lambda e: webbrowser.open('https://github.com/daid/Cura/wiki'), i)
50 i = helpMenu.Append(-1, 'Report a problem...')
51 self.Bind(wx.EVT_MENU, lambda e: webbrowser.open('https://github.com/daid/Cura/issues'), i)
52 menubar.Append(helpMenu, 'Help')
53 self.SetMenuBar(menubar)
55 if profile.getPreference('lastFile') != '':
56 self.filelist = profile.getPreference('lastFile').split(';')
57 self.SetTitle(self.filelist[-1] + ' - Cura - ' + version.getVersion())
60 self.progressPanelList = []
63 self.preview3d = preview3d.previewPanel(self)
65 configPanel = wx.Panel(self)
66 self.printTypeNormal = wx.RadioButton(configPanel, -1, 'Normal quality print', style=wx.RB_GROUP)
67 self.printTypeLow = wx.RadioButton(configPanel, -1, 'Fast low quality print')
68 self.printTypeHigh = wx.RadioButton(configPanel, -1, 'High quality print')
69 self.printTypeJoris = wx.RadioButton(configPanel, -1, 'Thin walled cup or vase')
71 self.printMaterialPLA = wx.RadioButton(configPanel, -1, 'PLA', style=wx.RB_GROUP)
72 self.printMaterialABS = wx.RadioButton(configPanel, -1, 'ABS')
73 self.printMaterialDiameter = wx.TextCtrl(configPanel, -1, profile.getProfileSetting('filament_diameter'))
75 self.printSupport = wx.CheckBox(configPanel, -1, 'Print support structure')
77 sizer = wx.GridBagSizer()
78 configPanel.SetSizer(sizer)
80 sb = wx.StaticBox(configPanel, label="Select a print type:")
81 boxsizer = wx.StaticBoxSizer(sb, wx.VERTICAL)
82 boxsizer.Add(self.printTypeNormal)
83 boxsizer.Add(self.printTypeLow)
84 boxsizer.Add(self.printTypeHigh)
85 boxsizer.Add(self.printTypeJoris)
86 sizer.Add(boxsizer, (0,0), flag=wx.EXPAND)
88 sb = wx.StaticBox(configPanel, label="Material:")
89 boxsizer = wx.StaticBoxSizer(sb, wx.VERTICAL)
90 boxsizer.Add(self.printMaterialPLA)
91 boxsizer.Add(self.printMaterialABS)
92 boxsizer.Add(wx.StaticText(configPanel, -1, 'Diameter:'))
93 boxsizer.Add(self.printMaterialDiameter)
94 sizer.Add(boxsizer, (1,0), flag=wx.EXPAND)
96 sb = wx.StaticBox(configPanel, label="Other:")
97 boxsizer = wx.StaticBoxSizer(sb, wx.VERTICAL)
98 boxsizer.Add(self.printSupport)
99 sizer.Add(boxsizer, (2,0), flag=wx.EXPAND)
101 # load and slice buttons.
102 loadButton = wx.Button(self, -1, 'Load Model')
103 sliceButton = wx.Button(self, -1, 'Slice to GCode')
104 printButton = wx.Button(self, -1, 'Print GCode')
105 self.Bind(wx.EVT_BUTTON, self.OnLoadModel, loadButton)
106 self.Bind(wx.EVT_BUTTON, self.OnSlice, sliceButton)
107 self.Bind(wx.EVT_BUTTON, self.OnPrint, printButton)
108 #Also bind double clicking the 3D preview to load an STL file.
109 self.preview3d.glCanvas.Bind(wx.EVT_LEFT_DCLICK, self.OnLoadModel, self.preview3d.glCanvas)
111 #Main sizer, to position the preview window, buttons and tab control
112 sizer = wx.GridBagSizer()
114 sizer.Add(configPanel, (0,0), span=(1,1), flag=wx.EXPAND)
115 sizer.Add(self.preview3d, (0,1), span=(1,3), flag=wx.EXPAND)
116 sizer.AddGrowableCol(2)
117 sizer.AddGrowableRow(0)
118 sizer.Add(loadButton, (1,1), flag=wx.RIGHT, border=5)
119 sizer.Add(sliceButton, (1,2), flag=wx.RIGHT, border=5)
120 sizer.Add(printButton, (1,3), flag=wx.RIGHT, border=5)
123 if len(self.filelist) > 0:
124 self.preview3d.loadModelFiles(self.filelist)
126 self.updateProfileToControls()
129 self.SetMinSize(self.GetSize())
133 def OnPreferences(self, e):
134 prefDialog = preferencesDialog.preferencesDialog(self)
136 prefDialog.Show(True)
138 def OnDefaultMarlinFirmware(self, e):
139 firmwareInstall.InstallFirmware()
141 def OnCustomFirmware(self, e):
142 dlg=wx.FileDialog(self, "Open firmware to upload", os.path.split(profile.getPreference('lastFile'))[0], style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST)
143 dlg.SetWildcard("HEX file (*.hex)|*.hex;*.HEX")
144 if dlg.ShowModal() == wx.ID_OK:
145 filename = dlg.GetPath()
146 if not(os.path.exists(filename)):
148 #For some reason my Ubuntu 10.10 crashes here.
149 firmwareInstall.InstallFirmware(filename)
151 def OnFirstRunWizard(self, e):
152 configWizard.configWizard()
153 self.updateProfileToControls()
155 def OnLoadModel(self, e):
156 dlg=wx.FileDialog(self, "Open file to print", os.path.split(profile.getPreference('lastFile'))[0], style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST)
157 dlg.SetWildcard("STL files (*.stl)|*.stl;*.STL")
158 if dlg.ShowModal() == wx.ID_OK:
159 self.filelist = [dlg.GetPath()]
160 profile.putPreference('lastFile', ';'.join(self.filelist))
161 self.preview3d.loadModelFiles(self.filelist)
162 self.preview3d.setViewMode("Normal")
165 def OnSlice(self, e):
166 if len(self.filelist) < 1:
167 wx.MessageBox('You need to load a file before you can slice it.', 'Print error', wx.OK | wx.ICON_INFORMATION)
169 #save the current profile so we can put it back latter
170 oldProfile = profile.getGlobalProfileString()
172 put = profile.putProfileSetting
173 get = profile.getProfileSetting
175 put('layer_height', '0.2')
176 put('wall_thickness', '0.8')
177 put('solid_layer_thickness', '0.6')
178 put('fill_density', '20')
179 put('skirt_line_count', '1')
180 put('skirt_gap', '6.0')
181 put('print_speed', '50')
182 put('print_temperature', '0')
183 put('support', 'None')
184 #put('machine_center_x', '100')
185 #put('machine_center_y', '100')
186 #put('retraction_min_travel', '5.0')
187 #put('retraction_speed', '13.5')
188 #put('retraction_amount', '0.0')
189 #put('retraction_extra', '0.0')
190 put('travel_speed', '150')
191 put('max_z_speed', '3.0')
192 put('bottom_layer_speed', '25')
193 put('cool_min_layer_time', '10')
194 put('fan_enabled', 'True')
195 put('fan_layer', '1')
196 put('fan_speed', '100')
197 #put('model_scale', '1.0')
198 #put('flip_x', 'False')
199 #put('flip_y', 'False')
200 #put('flip_z', 'False')
201 #put('model_rotate_base', '0')
202 #put('model_multiply_x', '1')
203 #put('model_multiply_y', '1')
204 put('extra_base_wall_thickness', '0.0')
205 put('sequence', 'Loops > Perimeter > Infill')
206 put('force_first_layer_sequence', 'True')
207 put('infill_type', 'Line')
208 put('solid_top', 'True')
209 put('fill_overlap', '15')
210 put('support_rate', '50')
211 put('support_distance', '0.5')
212 put('joris', 'False')
213 put('cool_min_feedrate', '5')
214 put('bridge_speed', '100')
215 put('raft_margin', '5')
216 put('raft_base_material_amount', '100')
217 put('raft_interface_material_amount', '100')
218 put('bottom_thickness', '0.0')
220 if self.printSupport.GetValue():
221 put('support', 'Exterior Only')
223 nozzle_size = float(get('nozzle_size'))
224 if self.printTypeNormal.GetValue():
225 put('wall_thickness', nozzle_size * 2.0)
226 put('layer_height', '0.2')
227 put('fill_density', '20')
228 elif self.printTypeLow.GetValue():
229 put('wall_thickness', nozzle_size * 1.0)
230 put('layer_height', '0.3')
231 put('fill_density', '10')
232 put('print_speed', '80')
233 put('bottom_layer_speed', '40')
234 elif self.printTypeHigh.GetValue():
235 put('wall_thickness', nozzle_size * 3.0)
236 put('layer_height', '0.1')
237 put('fill_density', '30')
238 put('bottom_layer_speed', '15')
239 put('bottom_thickness', '0.2')
240 elif self.printTypeJoris.GetValue():
241 put('wall_thickness', nozzle_size * 1.5)
242 put('layer_height', '0.3')
243 put('fill_density', '0')
245 put('extra_base_wall_thickness', '15.0')
246 put('sequence', 'Infill > Loops > Perimeter')
247 put('force_first_layer_sequence', 'False')
248 put('solid_top', 'False')
249 put('support', 'None')
250 put('cool_min_layer_time', '3')
252 put('filament_diameter', self.printMaterialDiameter.GetValue())
253 if self.printMaterialPLA.GetValue():
254 put('filament_density', '1.00')
255 put('enable_raft', 'False')
256 put('skirt_line_count', '1')
257 if self.printMaterialABS.GetValue():
258 put('filament_density', '0.85')
259 put('enable_raft', 'True')
260 put('skirt_line_count', '0')
261 put('fan_layer', '1')
262 put('bottom_thickness', '0.0')
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 slice it before you can print it.', 'Print error', wx.OK | wx.ICON_INFORMATION)
280 if not os.path.exists(sliceRun.getExportFilename(self.filelist[0])):
281 wx.MessageBox('You need to slice the file to GCode before you can print it.', '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):