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