chiark / gitweb /
Add a tools menu for the project planner and the batch runner, makes them easier...
[cura.git] / Cura / gui / simpleMode.py
1 from __future__ import absolute_import
2 import __init__
3
4 import wx, os, platform, types, webbrowser
5
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
13 from gui import icon
14 from util import validators
15 from util import profile
16 from util import version
17 from util import sliceRun
18
19 class simpleModeWindow(configBase.configWindowBase):
20         "Main user interface window for Quickprint mode"
21         def __init__(self):
22                 super(simpleModeWindow, self).__init__(title='Cura - Quickprint - ' + version.getVersion())
23                 
24                 wx.EVT_CLOSE(self, self.OnClose)
25                 #self.SetIcon(icon.getMainIcon())
26                 
27                 menubar = wx.MenuBar()
28                 fileMenu = wx.Menu()
29                 i = fileMenu.Append(-1, 'Load model file...')
30                 self.Bind(wx.EVT_MENU, self.OnLoadModel, i)
31                 fileMenu.AppendSeparator()
32                 i = fileMenu.Append(-1, 'Preferences...')
33                 self.Bind(wx.EVT_MENU, self.OnPreferences, i)
34                 fileMenu.AppendSeparator()
35                 i = fileMenu.Append(wx.ID_EXIT, 'Quit')
36                 self.Bind(wx.EVT_MENU, self.OnQuit, i)
37                 menubar.Append(fileMenu, '&File')
38                 
39                 toolsMenu = wx.Menu()
40                 i = toolsMenu.Append(-1, 'Switch to Normal mode...')
41                 self.Bind(wx.EVT_MENU, self.OnNormalSwitch, i)
42                 menubar.Append(toolsMenu, 'Tools')
43                 
44                 helpMenu = wx.Menu()
45                 i = helpMenu.Append(-1, 'Online documentation...')
46                 self.Bind(wx.EVT_MENU, lambda e: webbrowser.open('https://daid.github.com/Cura'), i)
47                 i = helpMenu.Append(-1, 'Report a problem...')
48                 self.Bind(wx.EVT_MENU, lambda e: webbrowser.open('https://github.com/daid/Cura/issues'), i)
49                 menubar.Append(helpMenu, 'Help')
50                 self.SetMenuBar(menubar)
51                 
52                 if profile.getPreference('lastFile') != '':
53                         self.filelist = profile.getPreference('lastFile').split(';')
54                         self.SetTitle(self.filelist[-1] + ' - Cura - ' + version.getVersion())
55                 else:
56                         self.filelist = []
57                 self.progressPanelList = []
58
59                 #Preview window
60                 self.preview3d = preview3d.previewPanel(self)
61
62                 configPanel = wx.Panel(self)
63                 self.printTypeNormal = wx.RadioButton(configPanel, -1, 'Normal quality print', style=wx.RB_GROUP)
64                 self.printTypeLow = wx.RadioButton(configPanel, -1, 'Fast low quality print')
65                 self.printTypeHigh = wx.RadioButton(configPanel, -1, 'High quality print')
66                 self.printTypeJoris = wx.RadioButton(configPanel, -1, 'Thin walled cup or vase')
67
68                 self.printMaterialPLA = wx.RadioButton(configPanel, -1, 'PLA', style=wx.RB_GROUP)
69                 self.printMaterialABS = wx.RadioButton(configPanel, -1, 'ABS')
70                 self.printMaterialDiameter = wx.TextCtrl(configPanel, -1, profile.getProfileSetting('filament_diameter'))
71                 
72                 self.printSupport = wx.CheckBox(configPanel, -1, 'Print support structure')
73                 
74                 sizer = wx.GridBagSizer()
75                 configPanel.SetSizer(sizer)
76
77                 sb = wx.StaticBox(configPanel, label="Select a print type:")
78                 boxsizer = wx.StaticBoxSizer(sb, wx.VERTICAL)
79                 boxsizer.Add(self.printTypeNormal)
80                 boxsizer.Add(self.printTypeLow)
81                 boxsizer.Add(self.printTypeHigh)
82                 boxsizer.Add(self.printTypeJoris)
83                 sizer.Add(boxsizer, (0,0), flag=wx.EXPAND)
84
85                 sb = wx.StaticBox(configPanel, label="Material:")
86                 boxsizer = wx.StaticBoxSizer(sb, wx.VERTICAL)
87                 boxsizer.Add(self.printMaterialPLA)
88                 boxsizer.Add(self.printMaterialABS)
89                 boxsizer.Add(wx.StaticText(configPanel, -1, 'Diameter:'))
90                 boxsizer.Add(self.printMaterialDiameter)
91                 sizer.Add(boxsizer, (1,0), flag=wx.EXPAND)
92
93                 sb = wx.StaticBox(configPanel, label="Other:")
94                 boxsizer = wx.StaticBoxSizer(sb, wx.VERTICAL)
95                 boxsizer.Add(self.printSupport)
96                 sizer.Add(boxsizer, (2,0), flag=wx.EXPAND)
97
98                 # load and slice buttons.
99                 loadButton = wx.Button(self, -1, 'Load Model')
100                 sliceButton = wx.Button(self, -1, 'Prepare print')
101                 printButton = wx.Button(self, -1, 'Print')
102                 self.Bind(wx.EVT_BUTTON, self.OnLoadModel, loadButton)
103                 self.Bind(wx.EVT_BUTTON, self.OnSlice, sliceButton)
104                 self.Bind(wx.EVT_BUTTON, self.OnPrint, printButton)
105                 #Also bind double clicking the 3D preview to load an STL file.
106                 self.preview3d.glCanvas.Bind(wx.EVT_LEFT_DCLICK, self.OnLoadModel, self.preview3d.glCanvas)
107
108                 #Main sizer, to position the preview window, buttons and tab control
109                 sizer = wx.GridBagSizer()
110                 self.SetSizer(sizer)
111                 sizer.Add(configPanel, (0,0), span=(1,1), flag=wx.EXPAND)
112                 sizer.Add(self.preview3d, (0,1), span=(1,3), flag=wx.EXPAND)
113                 sizer.AddGrowableCol(2)
114                 sizer.AddGrowableRow(0)
115                 sizer.Add(loadButton, (1,1), flag=wx.RIGHT, border=5)
116                 sizer.Add(sliceButton, (1,2), flag=wx.RIGHT, border=5)
117                 sizer.Add(printButton, (1,3), flag=wx.RIGHT, border=5)
118                 self.sizer = sizer
119
120                 if len(self.filelist) > 0:
121                         self.preview3d.loadModelFiles(self.filelist)
122
123                 self.updateProfileToControls()
124
125                 self.Fit()
126                 self.SetMinSize(self.GetSize())
127                 self.Centre()
128                 self.Show(True)
129         
130         def OnPreferences(self, e):
131                 prefDialog = preferencesDialog.preferencesDialog(self)
132                 prefDialog.Centre()
133                 prefDialog.Show(True)
134         
135         def OnDefaultMarlinFirmware(self, e):
136                 firmwareInstall.InstallFirmware()
137
138         def OnCustomFirmware(self, e):
139                 dlg=wx.FileDialog(self, "Open firmware to upload", os.path.split(profile.getPreference('lastFile'))[0], style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST)
140                 dlg.SetWildcard("HEX file (*.hex)|*.hex;*.HEX")
141                 if dlg.ShowModal() == wx.ID_OK:
142                         filename = dlg.GetPath()
143                         if not(os.path.exists(filename)):
144                                 return
145                         #For some reason my Ubuntu 10.10 crashes here.
146                         firmwareInstall.InstallFirmware(filename)
147
148         def OnFirstRunWizard(self, e):
149                 configWizard.configWizard()
150                 self.updateProfileToControls()
151
152         def OnLoadModel(self, e):
153                 dlg=wx.FileDialog(self, "Open file to print", os.path.split(profile.getPreference('lastFile'))[0], style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST)
154                 dlg.SetWildcard("STL files (*.stl)|*.stl;*.STL")
155                 if dlg.ShowModal() == wx.ID_OK:
156                         self.filelist = [dlg.GetPath()]
157                         profile.putPreference('lastFile', ';'.join(self.filelist))
158                         self.preview3d.loadModelFiles(self.filelist, True)
159                         self.preview3d.setViewMode("Normal")
160                 dlg.Destroy()
161         
162         def OnSlice(self, e):
163                 if len(self.filelist) < 1:
164                         wx.MessageBox('You need to load a file before you can slice it.', 'Print error', wx.OK | wx.ICON_INFORMATION)
165                         return
166                 #save the current profile so we can put it back latter
167                 oldProfile = profile.getGlobalProfileString()
168                 
169                 put = profile.putProfileSetting
170                 get = profile.getProfileSetting
171
172                 put('layer_height', '0.2')
173                 put('wall_thickness', '0.8')
174                 put('solid_layer_thickness', '0.6')
175                 put('fill_density', '20')
176                 put('skirt_line_count', '1')
177                 put('skirt_gap', '6.0')
178                 put('print_speed', '50')
179                 put('print_temperature', '230')
180                 put('support', 'None')
181                 #put('machine_center_x', '100')
182                 #put('machine_center_y', '100')
183                 #put('retraction_min_travel', '5.0')
184                 #put('retraction_speed', '13.5')
185                 #put('retraction_amount', '0.0')
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')
216
217                 if self.printSupport.GetValue():
218                         put('support', 'Exterior Only')
219
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.0)
227                         put('layer_height', '0.3')
228                         put('fill_density', '10')
229                         put('print_speed', '80')
230                         put('bottom_layer_speed', '40')
231                 elif self.printTypeHigh.GetValue():
232                         put('wall_thickness', nozzle_size * 3.0)
233                         put('layer_height', '0.1')
234                         put('fill_density', '30')
235                         put('bottom_layer_speed', '15')
236                         put('bottom_thickness', '0.2')
237                 elif self.printTypeJoris.GetValue():
238                         put('wall_thickness', nozzle_size * 1.5)
239                         put('layer_height', '0.3')
240                         put('fill_density', '0')
241                         put('joris', 'True')
242                         put('extra_base_wall_thickness', '15.0')
243                         put('sequence', 'Infill > Loops > Perimeter')
244                         put('force_first_layer_sequence', 'False')
245                         put('solid_top', 'False')
246                         put('support', 'None')
247                         put('cool_min_layer_time', '3')
248
249                 put('filament_diameter', self.printMaterialDiameter.GetValue())
250                 if self.printMaterialPLA.GetValue():
251                         put('filament_density', '1.00')
252                         put('enable_raft', 'False')
253                         put('skirt_line_count', '1')
254                 if self.printMaterialABS.GetValue():
255                         put('filament_density', '0.85')
256                         put('enable_raft', 'True')
257                         put('skirt_line_count', '0')
258                         put('fan_layer', '1')
259                         put('bottom_thickness', '0.0')
260                         put('print_temperature', '260')
261                 
262                 #Create a progress panel and add it to the window. The progress panel will start the Skein operation.
263                 spp = sliceProgessPanel.sliceProgessPanel(self, self, self.filelist)
264                 self.sizer.Add(spp, (len(self.progressPanelList)+2,0), span=(1,4), flag=wx.EXPAND)
265                 self.sizer.Layout()
266                 newSize = self.GetSize();
267                 newSize.IncBy(0, spp.GetSize().GetHeight())
268                 self.SetSize(newSize)
269                 self.progressPanelList.append(spp)
270                 
271                 #Restore the old profile.
272                 profile.loadGlobalProfileFromString(oldProfile)
273         
274         def OnPrint(self, e):
275                 if len(self.filelist) < 1:
276                         wx.MessageBox('You need to load a file and slice it before you can print it.', 'Print error', wx.OK | wx.ICON_INFORMATION)
277                         return
278                 if not os.path.exists(sliceRun.getExportFilename(self.filelist[0])):
279                         wx.MessageBox('You need to slice the file to GCode before you can print it.', 'Print error', wx.OK | wx.ICON_INFORMATION)
280                         return
281                 printWindow.printFile(sliceRun.getExportFilename(self.filelist[0]))
282
283         def OnNormalSwitch(self, e):
284                 from gui import mainWindow
285                 profile.putPreference('startMode', 'Normal')
286                 mainWindow.mainWindow()
287                 self.Close()
288
289         def removeSliceProgress(self, spp):
290                 self.progressPanelList.remove(spp)
291                 newSize = self.GetSize();
292                 newSize.IncBy(0, -spp.GetSize().GetHeight())
293                 self.SetSize(newSize)
294                 self.sizer.Remove(spp)
295                 spp.Destroy()
296                 for spp in self.progressPanelList:
297                         self.sizer.Remove(spp)
298                 i = 2
299                 for spp in self.progressPanelList:
300                         self.sizer.Add(spp, (i,0), span=(1,4), flag=wx.EXPAND)
301                         i += 1
302                 self.sizer.Layout()
303
304         def OnQuit(self, e):
305                 self.Close()
306         
307         def OnClose(self, e):
308                 self.Destroy()
309
310         def updateProfileToControls(self):
311                 super(simpleModeWindow, self).updateProfileToControls()
312                 self.preview3d.updateProfileToControls()
313