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...')
34 self.Bind(wx.EVT_MENU, self.OnLoadModel, i)
35 fileMenu.AppendSeparator()
36 i = fileMenu.Append(-1, 'Preferences...')
37 self.Bind(wx.EVT_MENU, self.OnPreferences, i)
38 fileMenu.AppendSeparator()
39 i = fileMenu.Append(wx.ID_EXIT, 'Quit')
40 self.Bind(wx.EVT_MENU, self.OnQuit, i)
41 menubar.Append(fileMenu, '&File')
44 i = toolsMenu.Append(-1, 'Switch to Normal mode...')
45 self.Bind(wx.EVT_MENU, self.OnNormalSwitch, i)
46 menubar.Append(toolsMenu, 'Normal mode')
49 i = helpMenu.Append(-1, 'Online documentation...')
50 self.Bind(wx.EVT_MENU, lambda e: webbrowser.open('https://daid.github.com/Cura'), i)
51 i = helpMenu.Append(-1, 'Report a problem...')
52 self.Bind(wx.EVT_MENU, lambda e: webbrowser.open('https://github.com/daid/Cura/issues'), i)
53 menubar.Append(helpMenu, 'Help')
54 self.SetMenuBar(menubar)
56 if profile.getPreference('lastFile') != '':
57 self.filelist = profile.getPreference('lastFile').split(';')
58 self.SetTitle(self.filelist[-1] + ' - Cura - ' + version.getVersion())
61 self.progressPanelList = []
64 self.preview3d = preview3d.previewPanel(self)
66 configPanel = wx.Panel(self)
67 printTypePanel = wx.Panel(configPanel)
68 self.printTypeNormal = wx.RadioButton(printTypePanel, -1, 'Normal quality print', style=wx.RB_GROUP)
69 self.printTypeLow = wx.RadioButton(printTypePanel, -1, 'Fast low quality print')
70 self.printTypeHigh = wx.RadioButton(printTypePanel, -1, 'High quality print')
71 self.printTypeJoris = wx.RadioButton(printTypePanel, -1, 'Thin walled cup or vase')
73 printMaterialPanel = wx.Panel(configPanel)
74 self.printMaterialPLA = wx.RadioButton(printMaterialPanel, -1, 'PLA', style=wx.RB_GROUP)
75 self.printMaterialABS = wx.RadioButton(printMaterialPanel, -1, 'ABS')
76 self.printMaterialDiameter = wx.TextCtrl(printMaterialPanel, -1, profile.getProfileSetting('filament_diameter'))
78 self.printSupport = wx.CheckBox(configPanel, -1, 'Print support structure')
80 sizer = wx.GridBagSizer()
81 configPanel.SetSizer(sizer)
83 sb = wx.StaticBox(printTypePanel, label="Select a print type:")
84 boxsizer = wx.StaticBoxSizer(sb, wx.VERTICAL)
85 boxsizer.Add(self.printTypeNormal)
86 boxsizer.Add(self.printTypeLow)
87 boxsizer.Add(self.printTypeHigh)
88 boxsizer.Add(self.printTypeJoris)
89 printTypePanel.SetSizer(wx.BoxSizer(wx.VERTICAL))
90 printTypePanel.GetSizer().Add(boxsizer, flag=wx.EXPAND)
91 sizer.Add(printTypePanel, (0,0), flag=wx.EXPAND)
93 sb = wx.StaticBox(printMaterialPanel, label="Material:")
94 boxsizer = wx.StaticBoxSizer(sb, wx.VERTICAL)
95 boxsizer.Add(self.printMaterialPLA)
96 boxsizer.Add(self.printMaterialABS)
97 boxsizer.Add(wx.StaticText(printMaterialPanel, -1, 'Diameter:'))
98 boxsizer.Add(self.printMaterialDiameter)
99 printMaterialPanel.SetSizer(wx.BoxSizer(wx.VERTICAL))
100 printMaterialPanel.GetSizer().Add(boxsizer, flag=wx.EXPAND)
101 sizer.Add(printMaterialPanel, (1,0), flag=wx.EXPAND)
103 sb = wx.StaticBox(configPanel, label="Other:")
104 boxsizer = wx.StaticBoxSizer(sb, wx.VERTICAL)
105 boxsizer.Add(self.printSupport)
106 sizer.Add(boxsizer, (2,0), flag=wx.EXPAND)
108 # load and slice buttons.
109 loadButton = wx.Button(self, -1, 'Load Model')
110 sliceButton = wx.Button(self, -1, 'Prepare print')
111 printButton = wx.Button(self, -1, 'Print')
112 self.Bind(wx.EVT_BUTTON, self.OnLoadModel, loadButton)
113 self.Bind(wx.EVT_BUTTON, self.OnSlice, sliceButton)
114 self.Bind(wx.EVT_BUTTON, self.OnPrint, printButton)
115 #Also bind double clicking the 3D preview to load an STL file.
116 self.preview3d.glCanvas.Bind(wx.EVT_LEFT_DCLICK, self.OnLoadModel, self.preview3d.glCanvas)
118 #Main sizer, to position the preview window, buttons and tab control
119 sizer = wx.GridBagSizer()
121 sizer.Add(configPanel, (0,0), span=(1,1), flag=wx.EXPAND)
122 sizer.Add(self.preview3d, (0,1), span=(1,3), flag=wx.EXPAND)
123 sizer.AddGrowableCol(2)
124 sizer.AddGrowableRow(0)
125 sizer.Add(loadButton, (1,1), flag=wx.RIGHT|wx.BOTTOM|wx.TOP, border=5)
126 sizer.Add(sliceButton, (1,2), flag=wx.RIGHT|wx.BOTTOM|wx.TOP, border=5)
127 sizer.Add(printButton, (1,3), flag=wx.RIGHT|wx.BOTTOM|wx.TOP, border=5)
130 if len(self.filelist) > 0:
131 self.preview3d.loadModelFiles(self.filelist)
133 self.SetBackgroundColour(configPanel.GetBackgroundColour())
135 self.updateProfileToControls()
137 self.printTypeNormal.SetValue(True)
138 self.printMaterialPLA.SetValue(True)
142 self.SetMinSize(self.GetSize())
146 def OnPreferences(self, e):
147 prefDialog = preferencesDialog.preferencesDialog(self)
149 prefDialog.Show(True)
151 def OnLoadModel(self, e):
152 dlg=wx.FileDialog(self, "Open file to print", os.path.split(profile.getPreference('lastFile'))[0], style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST)
153 dlg.SetWildcard(meshLoader.wildcardFilter())
154 if dlg.ShowModal() == wx.ID_OK:
155 self.filelist = [dlg.GetPath()]
156 profile.putPreference('lastFile', ';'.join(self.filelist))
157 self.preview3d.loadModelFiles(self.filelist, True)
158 self.preview3d.setViewMode("Normal")
161 def OnDropFiles(self, filenames):
162 self.filelist = filenames
163 profile.putPreference('lastFile', ';'.join(self.filelist))
164 self.preview3d.loadModelFiles(self.filelist, True)
165 self.preview3d.setViewMode("Normal")
167 def OnSlice(self, e):
168 if len(self.filelist) < 1:
169 wx.MessageBox('You need to load a file before you can prepare it.', 'Print error', wx.OK | wx.ICON_INFORMATION)
171 #save the current profile so we can put it back latter
172 oldProfile = profile.getGlobalProfileString()
174 put = profile.putProfileSetting
175 get = profile.getProfileSetting
177 put('layer_height', '0.2')
178 put('wall_thickness', '0.8')
179 put('solid_layer_thickness', '0.6')
180 put('fill_density', '20')
181 put('skirt_line_count', '1')
182 put('skirt_gap', '6.0')
183 put('print_speed', '50')
184 put('print_temperature', '220')
185 put('support', 'None')
186 #put('machine_center_x', '100')
187 #put('machine_center_y', '100')
188 put('retraction_enable', 'False')
189 put('retraction_min_travel', '5.0')
190 put('retraction_speed', '40.0')
191 put('retraction_amount', '4.5')
192 put('retraction_extra', '0.0')
193 put('travel_speed', '150')
194 put('max_z_speed', '3.0')
195 put('bottom_layer_speed', '25')
196 put('cool_min_layer_time', '10')
197 put('fan_enabled', 'True')
198 put('fan_layer', '1')
199 put('fan_speed', '100')
200 #put('model_scale', '1.0')
201 #put('flip_x', 'False')
202 #put('flip_y', 'False')
203 #put('flip_z', 'False')
204 #put('model_rotate_base', '0')
205 #put('model_multiply_x', '1')
206 #put('model_multiply_y', '1')
207 put('extra_base_wall_thickness', '0.0')
208 put('sequence', 'Loops > Perimeter > Infill')
209 put('force_first_layer_sequence', 'True')
210 put('infill_type', 'Line')
211 put('solid_top', 'True')
212 put('fill_overlap', '15')
213 put('support_rate', '50')
214 put('support_distance', '0.5')
215 put('joris', 'False')
216 put('cool_min_feedrate', '5')
217 put('bridge_speed', '100')
218 put('raft_margin', '5')
219 put('raft_base_material_amount', '100')
220 put('raft_interface_material_amount', '100')
221 put('bottom_thickness', '0.0')
223 if self.printSupport.GetValue():
224 put('support', 'Exterior Only')
226 nozzle_size = float(get('nozzle_size'))
227 if self.printTypeNormal.GetValue():
228 put('wall_thickness', nozzle_size * 2.0)
229 put('layer_height', '0.2')
230 put('fill_density', '20')
231 elif self.printTypeLow.GetValue():
232 put('wall_thickness', nozzle_size * 1.4)
233 put('layer_height', '0.25')
234 put('fill_density', '10')
235 put('print_speed', '80')
236 put('cool_min_layer_time', '3')
237 put('bottom_layer_speed', '40')
238 elif self.printTypeHigh.GetValue():
239 put('wall_thickness', nozzle_size * 2.0)
240 put('layer_height', '0.1')
241 put('fill_density', '30')
242 put('bottom_layer_speed', '15')
243 put('bottom_thickness', '0.2')
244 elif self.printTypeJoris.GetValue():
245 put('wall_thickness', nozzle_size * 1.5)
246 put('layer_height', '0.3')
247 put('solid_layer_thickness', '0.9')
248 put('fill_density', '0')
250 put('extra_base_wall_thickness', '15.0')
251 put('sequence', 'Infill > Loops > Perimeter')
252 put('force_first_layer_sequence', 'False')
253 put('solid_top', 'False')
254 put('support', 'None')
255 put('cool_min_layer_time', '3')
257 put('filament_diameter', self.printMaterialDiameter.GetValue())
258 if self.printMaterialPLA.GetValue():
259 put('filament_density', '1.00')
260 put('enable_raft', 'False')
261 put('skirt_line_count', '1')
262 if self.printMaterialABS.GetValue():
263 put('filament_density', '0.85')
264 put('enable_raft', 'True')
265 put('skirt_line_count', '0')
266 put('fan_layer', '1')
267 put('bottom_thickness', '0.0')
268 put('print_temperature', '260')
270 #Create a progress panel and add it to the window. The progress panel will start the Skein operation.
271 spp = sliceProgessPanel.sliceProgessPanel(self, self, self.filelist)
272 self.sizer.Add(spp, (len(self.progressPanelList)+2,0), span=(1,4), flag=wx.EXPAND)
274 newSize = self.GetSize();
275 newSize.IncBy(0, spp.GetSize().GetHeight())
276 self.SetSize(newSize)
277 self.progressPanelList.append(spp)
279 #Restore the old profile.
280 profile.loadGlobalProfileFromString(oldProfile)
282 def OnPrint(self, e):
283 if len(self.filelist) < 1:
284 wx.MessageBox('You need to load a file and prepare it before you can print.', 'Print error', wx.OK | wx.ICON_INFORMATION)
286 if not os.path.exists(sliceRun.getExportFilename(self.filelist[0])):
287 wx.MessageBox('You need to prepare the file before you can print.', 'Print error', wx.OK | wx.ICON_INFORMATION)
289 printWindow.printFile(sliceRun.getExportFilename(self.filelist[0]))
291 def OnNormalSwitch(self, e):
292 from gui import mainWindow
293 profile.putPreference('startMode', 'Normal')
294 mainWindow.mainWindow()
297 def removeSliceProgress(self, spp):
298 self.progressPanelList.remove(spp)
299 newSize = self.GetSize();
300 newSize.IncBy(0, -spp.GetSize().GetHeight())
301 self.SetSize(newSize)
302 self.sizer.Remove(spp)
304 for spp in self.progressPanelList:
305 self.sizer.Remove(spp)
307 for spp in self.progressPanelList:
308 self.sizer.Add(spp, (i,0), span=(1,4), flag=wx.EXPAND)
315 def OnClose(self, e):
318 def updateProfileToControls(self):
319 super(simpleModeWindow, self).updateProfileToControls()
320 self.preview3d.updateProfileToControls()