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.updateProfileToControls()
129 self.printTypeNormal.SetValue(True)
130 self.printMaterialPLA.SetValue(True)
133 self.SetMinSize(self.GetSize())
137 def OnPreferences(self, e):
138 prefDialog = preferencesDialog.preferencesDialog(self)
140 prefDialog.Show(True)
142 def OnLoadModel(self, e):
143 dlg=wx.FileDialog(self, "Open file to print", os.path.split(profile.getPreference('lastFile'))[0], style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST)
144 dlg.SetWildcard(meshLoader.wildcardFilter())
145 if dlg.ShowModal() == wx.ID_OK:
146 self.filelist = [dlg.GetPath()]
147 profile.putPreference('lastFile', ';'.join(self.filelist))
148 self.preview3d.loadModelFiles(self.filelist, True)
149 self.preview3d.setViewMode("Normal")
152 def OnDropFiles(self, filenames):
153 self.filelist = filenames
154 profile.putPreference('lastFile', ';'.join(self.filelist))
155 self.preview3d.loadModelFiles(self.filelist, True)
156 self.preview3d.setViewMode("Normal")
158 def OnSlice(self, e):
159 if len(self.filelist) < 1:
160 wx.MessageBox('You need to load a file before you can prepare it.', 'Print error', wx.OK | wx.ICON_INFORMATION)
162 #save the current profile so we can put it back latter
163 oldProfile = profile.getGlobalProfileString()
165 put = profile.putProfileSetting
166 get = profile.getProfileSetting
168 put('layer_height', '0.2')
169 put('wall_thickness', '0.8')
170 put('solid_layer_thickness', '0.6')
171 put('fill_density', '20')
172 put('skirt_line_count', '1')
173 put('skirt_gap', '6.0')
174 put('print_speed', '50')
175 put('print_temperature', '220')
176 put('support', 'None')
177 #put('machine_center_x', '100')
178 #put('machine_center_y', '100')
179 put('retraction_enable', 'False')
180 put('retraction_min_travel', '5.0')
181 put('retraction_speed', '40.0')
182 put('retraction_amount', '4.5')
183 put('retraction_extra', '0.0')
184 put('travel_speed', '150')
185 put('max_z_speed', '3.0')
186 put('bottom_layer_speed', '25')
187 put('cool_min_layer_time', '10')
188 put('fan_enabled', 'True')
189 put('fan_layer', '1')
190 put('fan_speed', '100')
191 #put('model_scale', '1.0')
192 #put('flip_x', 'False')
193 #put('flip_y', 'False')
194 #put('flip_z', 'False')
195 #put('model_rotate_base', '0')
196 #put('model_multiply_x', '1')
197 #put('model_multiply_y', '1')
198 put('extra_base_wall_thickness', '0.0')
199 put('sequence', 'Loops > Perimeter > Infill')
200 put('force_first_layer_sequence', 'True')
201 put('infill_type', 'Line')
202 put('solid_top', 'True')
203 put('fill_overlap', '15')
204 put('support_rate', '50')
205 put('support_distance', '0.5')
206 put('joris', 'False')
207 put('cool_min_feedrate', '5')
208 put('bridge_speed', '100')
209 put('raft_margin', '5')
210 put('raft_base_material_amount', '100')
211 put('raft_interface_material_amount', '100')
212 put('bottom_thickness', '0.0')
214 if self.printSupport.GetValue():
215 put('support', 'Exterior Only')
217 nozzle_size = float(get('nozzle_size'))
218 if self.printTypeNormal.GetValue():
219 put('wall_thickness', nozzle_size * 2.0)
220 put('layer_height', '0.2')
221 put('fill_density', '20')
222 elif self.printTypeLow.GetValue():
223 put('wall_thickness', nozzle_size * 1.4)
224 put('layer_height', '0.25')
225 put('fill_density', '10')
226 put('print_speed', '80')
227 put('cool_min_layer_time', '3')
228 put('bottom_layer_speed', '40')
229 elif self.printTypeHigh.GetValue():
230 put('wall_thickness', nozzle_size * 2.0)
231 put('layer_height', '0.1')
232 put('fill_density', '30')
233 put('bottom_layer_speed', '15')
234 put('bottom_thickness', '0.2')
235 elif self.printTypeJoris.GetValue():
236 put('wall_thickness', nozzle_size * 1.5)
237 put('layer_height', '0.3')
238 put('solid_layer_thickness', '0.9')
239 put('fill_density', '0')
241 put('extra_base_wall_thickness', '15.0')
242 put('sequence', 'Infill > Loops > Perimeter')
243 put('force_first_layer_sequence', 'False')
244 put('solid_top', 'False')
245 put('support', 'None')
246 put('cool_min_layer_time', '3')
248 put('filament_diameter', self.printMaterialDiameter.GetValue())
249 if self.printMaterialPLA.GetValue():
250 put('filament_density', '1.00')
251 put('enable_raft', 'False')
252 put('skirt_line_count', '1')
253 if self.printMaterialABS.GetValue():
254 put('filament_density', '0.85')
255 put('enable_raft', 'True')
256 put('skirt_line_count', '0')
257 put('fan_layer', '1')
258 put('bottom_thickness', '0.0')
259 put('print_temperature', '260')
261 #Create a progress panel and add it to the window. The progress panel will start the Skein operation.
262 spp = sliceProgessPanel.sliceProgessPanel(self, self, self.filelist)
263 self.sizer.Add(spp, (len(self.progressPanelList)+2,0), span=(1,4), flag=wx.EXPAND)
265 newSize = self.GetSize();
266 newSize.IncBy(0, spp.GetSize().GetHeight())
267 self.SetSize(newSize)
268 self.progressPanelList.append(spp)
270 #Restore the old profile.
271 profile.loadGlobalProfileFromString(oldProfile)
273 def OnPrint(self, e):
274 if len(self.filelist) < 1:
275 wx.MessageBox('You need to load a file and prepare it before you can print.', 'Print error', wx.OK | wx.ICON_INFORMATION)
277 if not os.path.exists(sliceRun.getExportFilename(self.filelist[0])):
278 wx.MessageBox('You need to prepare the file before you can print.', 'Print error', wx.OK | wx.ICON_INFORMATION)
280 printWindow.printFile(sliceRun.getExportFilename(self.filelist[0]))
282 def OnNormalSwitch(self, e):
283 from gui import mainWindow
284 profile.putPreference('startMode', 'Normal')
285 mainWindow.mainWindow()
288 def removeSliceProgress(self, spp):
289 self.progressPanelList.remove(spp)
290 newSize = self.GetSize();
291 newSize.IncBy(0, -spp.GetSize().GetHeight())
292 self.SetSize(newSize)
293 self.sizer.Remove(spp)
295 for spp in self.progressPanelList:
296 self.sizer.Remove(spp)
298 for spp in self.progressPanelList:
299 self.sizer.Add(spp, (i,0), span=(1,4), flag=wx.EXPAND)
306 def OnClose(self, e):
309 def updateProfileToControls(self):
310 super(simpleModeWindow, self).updateProfileToControls()
311 self.preview3d.updateProfileToControls()