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