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 self.printTypeNormal = wx.RadioButton(configPanel, -1, 'Normal quality print', style=wx.RB_GROUP)
68 self.printTypeLow = wx.RadioButton(configPanel, -1, 'Fast low quality print')
69 self.printTypeHigh = wx.RadioButton(configPanel, -1, 'High quality print')
70 self.printTypeJoris = wx.RadioButton(configPanel, -1, 'Thin walled cup or vase')
72 self.printMaterialPLA = wx.RadioButton(configPanel, -1, 'PLA', style=wx.RB_GROUP)
73 self.printMaterialABS = wx.RadioButton(configPanel, -1, 'ABS')
74 self.printMaterialDiameter = wx.TextCtrl(configPanel, -1, profile.getProfileSetting('filament_diameter'))
76 self.printSupport = wx.CheckBox(configPanel, -1, 'Print support structure')
78 sizer = wx.GridBagSizer()
79 configPanel.SetSizer(sizer)
81 sb = wx.StaticBox(configPanel, label="Select a print type:")
82 boxsizer = wx.StaticBoxSizer(sb, wx.VERTICAL)
83 boxsizer.Add(self.printTypeNormal)
84 boxsizer.Add(self.printTypeLow)
85 boxsizer.Add(self.printTypeHigh)
86 boxsizer.Add(self.printTypeJoris)
87 sizer.Add(boxsizer, (0,0), flag=wx.EXPAND)
89 sb = wx.StaticBox(configPanel, label="Material:")
90 boxsizer = wx.StaticBoxSizer(sb, wx.VERTICAL)
91 boxsizer.Add(self.printMaterialPLA)
92 boxsizer.Add(self.printMaterialABS)
93 boxsizer.Add(wx.StaticText(configPanel, -1, 'Diameter:'))
94 boxsizer.Add(self.printMaterialDiameter)
95 sizer.Add(boxsizer, (1,0), flag=wx.EXPAND)
97 sb = wx.StaticBox(configPanel, label="Other:")
98 boxsizer = wx.StaticBoxSizer(sb, wx.VERTICAL)
99 boxsizer.Add(self.printSupport)
100 sizer.Add(boxsizer, (2,0), flag=wx.EXPAND)
102 # load and slice buttons.
103 loadButton = wx.Button(self, -1, 'Load Model')
104 sliceButton = wx.Button(self, -1, 'Prepare print')
105 printButton = wx.Button(self, -1, 'Print')
106 self.Bind(wx.EVT_BUTTON, self.OnLoadModel, loadButton)
107 self.Bind(wx.EVT_BUTTON, self.OnSlice, sliceButton)
108 self.Bind(wx.EVT_BUTTON, self.OnPrint, printButton)
109 #Also bind double clicking the 3D preview to load an STL file.
110 self.preview3d.glCanvas.Bind(wx.EVT_LEFT_DCLICK, self.OnLoadModel, self.preview3d.glCanvas)
112 #Main sizer, to position the preview window, buttons and tab control
113 sizer = wx.GridBagSizer()
115 sizer.Add(configPanel, (0,0), span=(1,1), flag=wx.EXPAND)
116 sizer.Add(self.preview3d, (0,1), span=(1,3), flag=wx.EXPAND)
117 sizer.AddGrowableCol(2)
118 sizer.AddGrowableRow(0)
119 sizer.Add(loadButton, (1,1), flag=wx.RIGHT|wx.BOTTOM|wx.TOP, border=5)
120 sizer.Add(sliceButton, (1,2), flag=wx.RIGHT|wx.BOTTOM|wx.TOP, border=5)
121 sizer.Add(printButton, (1,3), flag=wx.RIGHT|wx.BOTTOM|wx.TOP, border=5)
124 if len(self.filelist) > 0:
125 self.preview3d.loadModelFiles(self.filelist)
127 self.SetBackgroundColour(configPanel.GetBackgroundColour())
129 self.updateProfileToControls()
131 self.printTypeNormal.SetValue(True)
132 self.printMaterialPLA.SetValue(True)
136 self.SetMinSize(self.GetSize())
140 def OnPreferences(self, e):
141 prefDialog = preferencesDialog.preferencesDialog(self)
143 prefDialog.Show(True)
145 def OnLoadModel(self, e):
146 dlg=wx.FileDialog(self, "Open file to print", os.path.split(profile.getPreference('lastFile'))[0], style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST)
147 dlg.SetWildcard(meshLoader.wildcardFilter())
148 if dlg.ShowModal() == wx.ID_OK:
149 self.filelist = [dlg.GetPath()]
150 profile.putPreference('lastFile', ';'.join(self.filelist))
151 self.preview3d.loadModelFiles(self.filelist, True)
152 self.preview3d.setViewMode("Normal")
155 def OnDropFiles(self, filenames):
156 self.filelist = filenames
157 profile.putPreference('lastFile', ';'.join(self.filelist))
158 self.preview3d.loadModelFiles(self.filelist, True)
159 self.preview3d.setViewMode("Normal")
161 def OnSlice(self, e):
162 if len(self.filelist) < 1:
163 wx.MessageBox('You need to load a file before you can prepare it.', 'Print error', wx.OK | wx.ICON_INFORMATION)
165 #save the current profile so we can put it back latter
166 oldProfile = profile.getGlobalProfileString()
168 put = profile.putProfileSetting
169 get = profile.getProfileSetting
171 put('layer_height', '0.2')
172 put('wall_thickness', '0.8')
173 put('solid_layer_thickness', '0.6')
174 put('fill_density', '20')
175 put('skirt_line_count', '1')
176 put('skirt_gap', '6.0')
177 put('print_speed', '50')
178 put('print_temperature', '220')
179 put('support', 'None')
180 #put('machine_center_x', '100')
181 #put('machine_center_y', '100')
182 put('retraction_enable', 'False')
183 put('retraction_min_travel', '5.0')
184 put('retraction_speed', '40.0')
185 put('retraction_amount', '4.5')
186 put('retraction_extra', '0.0')
187 put('travel_speed', '150')
188 put('max_z_speed', '3.0')
189 put('bottom_layer_speed', '25')
190 put('cool_min_layer_time', '10')
191 put('fan_enabled', 'True')
192 put('fan_layer', '1')
193 put('fan_speed', '100')
194 #put('model_scale', '1.0')
195 #put('flip_x', 'False')
196 #put('flip_y', 'False')
197 #put('flip_z', 'False')
198 #put('model_rotate_base', '0')
199 #put('model_multiply_x', '1')
200 #put('model_multiply_y', '1')
201 put('extra_base_wall_thickness', '0.0')
202 put('sequence', 'Loops > Perimeter > Infill')
203 put('force_first_layer_sequence', 'True')
204 put('infill_type', 'Line')
205 put('solid_top', 'True')
206 put('fill_overlap', '15')
207 put('support_rate', '50')
208 put('support_distance', '0.5')
209 put('joris', 'False')
210 put('cool_min_feedrate', '5')
211 put('bridge_speed', '100')
212 put('raft_margin', '5')
213 put('raft_base_material_amount', '100')
214 put('raft_interface_material_amount', '100')
215 put('bottom_thickness', '0.0')
217 if self.printSupport.GetValue():
218 put('support', 'Exterior Only')
220 nozzle_size = float(get('nozzle_size'))
221 if self.printTypeNormal.GetValue():
222 put('wall_thickness', nozzle_size * 2.0)
223 put('layer_height', '0.2')
224 put('fill_density', '20')
225 elif self.printTypeLow.GetValue():
226 put('wall_thickness', nozzle_size * 1.4)
227 put('layer_height', '0.25')
228 put('fill_density', '10')
229 put('print_speed', '80')
230 put('cool_min_layer_time', '3')
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()