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 dropTarget
13 from gui import printWindow
15 from util import validators
16 from util import profile
17 from util import version
18 from util import sliceRun
19 from util import meshLoader
21 class simpleModeWindow(configBase.configWindowBase):
22 "Main user interface window for Quickprint mode"
24 super(simpleModeWindow, self).__init__(title='Cura - Quickprint - ' + version.getVersion())
26 wx.EVT_CLOSE(self, self.OnClose)
27 #self.SetIcon(icon.getMainIcon())
29 self.SetDropTarget(dropTarget.FileDropTarget(self.OnDropFiles, meshLoader.supportedExtensions()))
31 menubar = wx.MenuBar()
33 i = fileMenu.Append(-1, 'Load model file...\tCTRL+L')
34 self.Bind(wx.EVT_MENU, self.OnLoadModel, i)
35 i = fileMenu.Append(-1, 'Prepare print...\tCTRL+R')
36 self.Bind(wx.EVT_MENU, self.OnSlice, i)
37 i = fileMenu.Append(-1, 'Print...\tCTRL+P')
38 self.Bind(wx.EVT_MENU, self.OnPrint, i)
39 fileMenu.AppendSeparator()
40 i = fileMenu.Append(-1, 'Preferences...')
41 self.Bind(wx.EVT_MENU, self.OnPreferences, i)
42 fileMenu.AppendSeparator()
43 i = fileMenu.Append(wx.ID_EXIT, 'Quit')
44 self.Bind(wx.EVT_MENU, self.OnQuit, i)
45 menubar.Append(fileMenu, '&File')
48 i = toolsMenu.Append(-1, 'Switch to Normal mode...')
49 self.Bind(wx.EVT_MENU, self.OnNormalSwitch, i)
50 menubar.Append(toolsMenu, 'Normal mode')
53 i = helpMenu.Append(-1, 'Online documentation...')
54 self.Bind(wx.EVT_MENU, lambda e: webbrowser.open('https://daid.github.com/Cura'), i)
55 i = helpMenu.Append(-1, 'Report a problem...')
56 self.Bind(wx.EVT_MENU, lambda e: webbrowser.open('https://github.com/daid/Cura/issues'), i)
57 menubar.Append(helpMenu, 'Help')
58 self.SetMenuBar(menubar)
60 if profile.getPreference('lastFile') != '':
61 self.filelist = profile.getPreference('lastFile').split(';')
62 self.SetTitle('Cura - %s - %s' % (version.getVersion(), self.filelist[-1]))
65 self.progressPanelList = []
68 self.preview3d = preview3d.previewPanel(self)
70 configPanel = wx.Panel(self)
71 printTypePanel = wx.Panel(configPanel)
72 self.printTypeNormal = wx.RadioButton(printTypePanel, -1, 'Normal quality print', style=wx.RB_GROUP)
73 self.printTypeLow = wx.RadioButton(printTypePanel, -1, 'Fast low quality print')
74 self.printTypeHigh = wx.RadioButton(printTypePanel, -1, 'High quality print')
75 self.printTypeJoris = wx.RadioButton(printTypePanel, -1, 'Thin walled cup or vase')
77 printMaterialPanel = wx.Panel(configPanel)
78 self.printMaterialPLA = wx.RadioButton(printMaterialPanel, -1, 'PLA', style=wx.RB_GROUP)
79 self.printMaterialABS = wx.RadioButton(printMaterialPanel, -1, 'ABS')
80 self.printMaterialDiameter = wx.TextCtrl(printMaterialPanel, -1, profile.getProfileSetting('filament_diameter'))
82 self.printSupport = wx.CheckBox(configPanel, -1, 'Print support structure')
84 sizer = wx.GridBagSizer()
85 configPanel.SetSizer(sizer)
87 sb = wx.StaticBox(printTypePanel, label="Select a print type:")
88 boxsizer = wx.StaticBoxSizer(sb, wx.VERTICAL)
89 boxsizer.Add(self.printTypeNormal)
90 boxsizer.Add(self.printTypeLow)
91 boxsizer.Add(self.printTypeHigh)
92 boxsizer.Add(self.printTypeJoris)
93 printTypePanel.SetSizer(wx.BoxSizer(wx.VERTICAL))
94 printTypePanel.GetSizer().Add(boxsizer, flag=wx.EXPAND)
95 sizer.Add(printTypePanel, (0,0), flag=wx.EXPAND)
97 sb = wx.StaticBox(printMaterialPanel, label="Material:")
98 boxsizer = wx.StaticBoxSizer(sb, wx.VERTICAL)
99 boxsizer.Add(self.printMaterialPLA)
100 boxsizer.Add(self.printMaterialABS)
101 boxsizer.Add(wx.StaticText(printMaterialPanel, -1, 'Diameter:'))
102 boxsizer.Add(self.printMaterialDiameter)
103 printMaterialPanel.SetSizer(wx.BoxSizer(wx.VERTICAL))
104 printMaterialPanel.GetSizer().Add(boxsizer, flag=wx.EXPAND)
105 sizer.Add(printMaterialPanel, (1,0), flag=wx.EXPAND)
107 sb = wx.StaticBox(configPanel, label="Other:")
108 boxsizer = wx.StaticBoxSizer(sb, wx.VERTICAL)
109 boxsizer.Add(self.printSupport)
110 sizer.Add(boxsizer, (2,0), flag=wx.EXPAND)
112 # load and slice buttons.
113 loadButton = wx.Button(self, -1, '&Load Model')
114 sliceButton = wx.Button(self, -1, 'P&repare print')
115 printButton = wx.Button(self, -1, '&Print')
116 self.Bind(wx.EVT_BUTTON, self.OnLoadModel, loadButton)
117 self.Bind(wx.EVT_BUTTON, self.OnSlice, sliceButton)
118 self.Bind(wx.EVT_BUTTON, self.OnPrint, printButton)
119 #Also bind double clicking the 3D preview to load an STL file.
120 self.preview3d.glCanvas.Bind(wx.EVT_LEFT_DCLICK, self.OnLoadModel, self.preview3d.glCanvas)
122 #Main sizer, to position the preview window, buttons and tab control
123 sizer = wx.GridBagSizer()
125 sizer.Add(configPanel, (0,0), span=(1,1), flag=wx.EXPAND)
126 sizer.Add(self.preview3d, (0,1), span=(1,3), flag=wx.EXPAND)
127 sizer.AddGrowableCol(2)
128 sizer.AddGrowableRow(0)
129 sizer.Add(loadButton, (1,1), flag=wx.RIGHT|wx.BOTTOM|wx.TOP, border=5)
130 sizer.Add(sliceButton, (1,2), flag=wx.RIGHT|wx.BOTTOM|wx.TOP, border=5)
131 sizer.Add(printButton, (1,3), flag=wx.RIGHT|wx.BOTTOM|wx.TOP, border=5)
134 if len(self.filelist) > 0:
135 self.preview3d.loadModelFiles(self.filelist)
137 self.SetBackgroundColour(configPanel.GetBackgroundColour())
139 self.updateProfileToControls()
141 self.printTypeNormal.SetValue(True)
142 self.printMaterialPLA.SetValue(True)
146 self.SetMinSize(self.GetSize())
150 def OnPreferences(self, e):
151 prefDialog = preferencesDialog.preferencesDialog(self)
153 prefDialog.Show(True)
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(meshLoader.wildcardFilter())
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, True)
162 self.preview3d.setViewMode("Normal")
165 def OnDropFiles(self, filenames):
166 self.filelist = filenames
167 profile.putPreference('lastFile', ';'.join(self.filelist))
168 self.preview3d.loadModelFiles(self.filelist, True)
169 self.preview3d.setViewMode("Normal")
171 def OnSlice(self, e):
172 if len(self.filelist) < 1:
173 wx.MessageBox('You need to load a file before you can prepare it.', 'Print error', wx.OK | wx.ICON_INFORMATION)
175 #save the current profile so we can put it back latter
176 oldProfile = profile.getGlobalProfileString()
178 put = profile.putProfileSetting
179 get = profile.getProfileSetting
181 put('layer_height', '0.2')
182 put('wall_thickness', '0.8')
183 put('solid_layer_thickness', '0.6')
184 put('fill_density', '20')
185 put('skirt_line_count', '1')
186 put('skirt_gap', '6.0')
187 put('print_speed', '50')
188 put('print_temperature', '220')
189 put('support', 'None')
190 #put('machine_center_x', '100')
191 #put('machine_center_y', '100')
192 put('retraction_enable', 'False')
193 put('retraction_min_travel', '5.0')
194 put('retraction_speed', '40.0')
195 put('retraction_amount', '4.5')
196 put('retraction_extra', '0.0')
197 put('travel_speed', '150')
198 put('max_z_speed', '3.0')
199 put('bottom_layer_speed', '25')
200 put('cool_min_layer_time', '10')
201 put('fan_enabled', 'True')
202 put('fan_layer', '1')
203 put('fan_speed', '100')
204 #put('model_scale', '1.0')
205 #put('flip_x', 'False')
206 #put('flip_y', 'False')
207 #put('flip_z', 'False')
208 #put('model_rotate_base', '0')
209 #put('model_multiply_x', '1')
210 #put('model_multiply_y', '1')
211 put('extra_base_wall_thickness', '0.0')
212 put('sequence', 'Loops > Perimeter > Infill')
213 put('force_first_layer_sequence', 'True')
214 put('infill_type', 'Line')
215 put('solid_top', 'True')
216 put('fill_overlap', '15')
217 put('support_rate', '50')
218 put('support_distance', '0.5')
219 put('joris', 'False')
220 put('cool_min_feedrate', '5')
221 put('bridge_speed', '100')
222 put('raft_margin', '5')
223 put('raft_base_material_amount', '100')
224 put('raft_interface_material_amount', '100')
225 put('bottom_thickness', '0.0')
227 if self.printSupport.GetValue():
228 put('support', 'Exterior Only')
230 nozzle_size = float(get('nozzle_size'))
231 if self.printTypeNormal.GetValue():
232 put('wall_thickness', nozzle_size * 2.0)
233 put('layer_height', '0.2')
234 put('fill_density', '20')
235 elif self.printTypeLow.GetValue():
236 put('wall_thickness', nozzle_size * 1.4)
237 put('layer_height', '0.25')
238 put('fill_density', '10')
239 put('print_speed', '80')
240 put('cool_min_layer_time', '3')
241 put('bottom_layer_speed', '40')
242 elif self.printTypeHigh.GetValue():
243 put('wall_thickness', nozzle_size * 2.0)
244 put('layer_height', '0.1')
245 put('fill_density', '30')
246 put('bottom_layer_speed', '15')
247 put('bottom_thickness', '0.2')
248 elif self.printTypeJoris.GetValue():
249 put('wall_thickness', nozzle_size * 1.5)
250 put('layer_height', '0.3')
251 put('solid_layer_thickness', '0.9')
252 put('fill_density', '0')
254 put('extra_base_wall_thickness', '15.0')
255 put('sequence', 'Infill > Loops > Perimeter')
256 put('force_first_layer_sequence', 'False')
257 put('solid_top', 'False')
258 put('support', 'None')
259 put('cool_min_layer_time', '3')
261 put('filament_diameter', self.printMaterialDiameter.GetValue())
262 if self.printMaterialPLA.GetValue():
263 put('filament_density', '1.00')
264 put('enable_raft', 'False')
265 put('skirt_line_count', '1')
266 if self.printMaterialABS.GetValue():
267 put('filament_density', '0.85')
268 put('enable_raft', 'True')
269 put('skirt_line_count', '0')
270 put('fan_layer', '1')
271 put('bottom_thickness', '0.0')
272 put('print_temperature', '260')
274 #Create a progress panel and add it to the window. The progress panel will start the Skein operation.
275 spp = sliceProgessPanel.sliceProgessPanel(self, self, self.filelist)
276 self.sizer.Add(spp, (len(self.progressPanelList)+2,0), span=(1,4), flag=wx.EXPAND)
278 newSize = self.GetSize();
279 newSize.IncBy(0, spp.GetSize().GetHeight())
280 if newSize.GetWidth() < wx.GetDisplaySize()[0]:
281 self.SetSize(newSize)
282 self.progressPanelList.append(spp)
284 #Restore the old profile.
285 profile.loadGlobalProfileFromString(oldProfile)
287 def OnPrint(self, e):
288 if len(self.filelist) < 1:
289 wx.MessageBox('You need to load a file and prepare it before you can print.', 'Print error', wx.OK | wx.ICON_INFORMATION)
291 if not os.path.exists(sliceRun.getExportFilename(self.filelist[0])):
292 wx.MessageBox('You need to prepare the file before you can print.', 'Print error', wx.OK | wx.ICON_INFORMATION)
294 printWindow.printFile(sliceRun.getExportFilename(self.filelist[0]))
296 def OnNormalSwitch(self, e):
297 from gui import mainWindow
298 profile.putPreference('startMode', 'Normal')
299 mainWindow.mainWindow()
302 def removeSliceProgress(self, spp):
303 self.progressPanelList.remove(spp)
304 newSize = self.GetSize();
305 newSize.IncBy(0, -spp.GetSize().GetHeight())
306 if newSize.GetWidth() < wx.GetDisplaySize()[0]:
307 self.SetSize(newSize)
309 self.sizer.Detach(spp)
310 for spp in self.progressPanelList:
311 self.sizer.Detach(spp)
313 for spp in self.progressPanelList:
314 self.sizer.Add(spp, (i,0), span=(1,4), flag=wx.EXPAND)
321 def OnClose(self, e):
324 def updateProfileToControls(self):
325 super(simpleModeWindow, self).updateProfileToControls()
326 self.preview3d.updateProfileToControls()