chiark / gitweb /
Save the material type so the right value is restored when opening cura
[cura.git] / Cura / gui / simpleMode.py
1 __copyright__ = "Copyright (C) 2013 David Braam - Released under terms of the AGPLv3 License"
2
3 import wx
4 import ConfigParser as configparser
5 import os.path
6
7 from Cura.util import profile
8 from Cura.util import resources
9
10 class simpleModePanel(wx.Panel):
11         "Main user interface window for Quickprint mode"
12         def __init__(self, parent, callback):
13                 super(simpleModePanel, self).__init__(parent)
14                 self._callback = callback
15
16                 self._print_material_options = []
17                 self._print_profile_options = []
18                 self._print_other_options = []
19                 self._print_material_types = {}
20                 self._all_print_materials = []
21
22                 materials = resources.getSimpleModeMaterials()
23                 other_print_material_types = []
24                 for material in materials:
25                         if material.disabled:
26                                 continue
27                         if len(material.types) == 0:
28                                 other_print_material_types.append(material)
29                         else:
30                                 for type in material.types:
31                                         if self._print_material_types.has_key(type):
32                                                 self._print_material_types[type].append(material)
33                                         else:
34                                                 self._print_material_types[type] = [material]
35
36                 if len(self._print_material_types) == 0:
37                         self._print_material_types = None
38
39                 # Create material buttons
40                 self.printMaterialPanel = wx.Panel(self)
41                 selectedMaterial = None
42                 for material in materials:
43                         if material.disabled:
44                                 continue
45                         # Show radio buttons if there are no material types
46                         if self._print_material_types is None:
47                                 button = wx.RadioButton(self.printMaterialPanel, -1, material.name.replace('&', '&&'),
48                                                                                 style=wx.RB_GROUP if len(self._print_material_options) == 0 else 0)
49                                 button.profile = material
50                                 button.Bind(wx.EVT_RADIOBUTTON, self._materialSelected)
51                                 self._print_material_options.append(button)
52                         self._all_print_materials.append(material)
53                         if profile.getProfileSetting('simpleModeMaterial') == material.name:
54                                 selectedMaterial = material
55
56                 # Decide on the default selected material
57                 if selectedMaterial is None:
58                         for material in self._all_print_materials:
59                                 if material.default:
60                                         selectedMaterial = material
61                                         break
62
63                 if selectedMaterial is None and len(self._all_print_materials) > 0:
64                         selectedMaterial = self._all_print_materials[0]
65
66                 # Decide to show the panel or not
67                 if self._print_material_types is None and len(self._print_material_options) < 2:
68                         self.printMaterialPanel.Show(len(self._print_material_options) > 1 and \
69                                                                                  self._print_material_options[0].always_visible)
70
71                 # Create material types combobox
72                 self.printMaterialTypesPanel = wx.Panel(self)
73                 selectedMaterialType = None
74                 if self._print_material_types is not None:
75                         for material_type in self._print_material_types:
76                                 if profile.getProfileSetting('simpleModeMaterialType') == material_type and \
77                                    selectedMaterial in self._print_material_types[material_type]:
78                                         selectedMaterialType = material_type
79
80                         if selectedMaterialType is None:
81                                 if profile.getProfileSetting('simpleModeMaterialType') == _("Others") or \
82                                    profile.getProfileSetting('simpleModeMaterialType') == _("All"):
83                                         selectedMaterialType = profile.getProfileSetting('simpleModeMaterialType')
84                                 elif selectedMaterial is None or len(selectedMaterial.types) == 0:
85                                         selectedMaterialType = _("Others")
86                                 else:
87                                         selectedMaterialType = selectedMaterial.types[0]
88
89                 # Decide to show the material types or not
90                 if self._print_material_types is None:
91                         self.printMaterialTypesPanel.Show(False)
92
93                 self.printTypePanel = wx.Panel(self)
94
95                 sizer = wx.GridBagSizer()
96                 self.SetSizer(sizer)
97
98                 boxsizer = wx.BoxSizer(wx.VERTICAL)
99                 boxsizer.SetMinSize((80, 20))
100                 if self._print_material_types is None:
101                         self.materialTypeCombo = None
102                 else:
103                         choices = self._print_material_types.keys()
104                         choices.sort(key=lambda type: sum([mat.order for mat in self._print_material_types[type]]))
105                         # Now we can add Others, so it appears towards the end
106                         if len(other_print_material_types) > 0:
107                                 self._print_material_types[_("Others")] = other_print_material_types
108                                 choices.append(_("Others"))
109                         choices.append(_("All"))
110                         label = wx.StaticText(self.printMaterialTypesPanel, label=_("Material ease of use:"))
111                         self.materialTypeCombo = wx.ComboBox(self.printMaterialTypesPanel, -1, selectedMaterialType,
112                                                                                                  choices=choices, style=wx.CB_READONLY)
113                         self.materialTypeCombo.Bind(wx.EVT_COMBOBOX, self._materialTypeSelected)
114                         boxsizer.Add(label, flag=wx.EXPAND)
115                         boxsizer.Add(self.materialTypeCombo, border=5, flag=wx.BOTTOM|wx.TOP|wx.EXPAND)
116                 self.printMaterialTypesPanel.SetSizer(boxsizer)
117                 sizer.Add(self.printMaterialTypesPanel, (0,0), border=10, flag=wx.EXPAND|wx.RIGHT|wx.LEFT|wx.TOP)
118
119                 if self._print_material_types is None:
120                         sb = wx.StaticBox(self.printMaterialPanel, label=_("Material:"))
121                         boxsizer = wx.StaticBoxSizer(sb, wx.VERTICAL)
122                         boxsizer.SetMinSize((80, 20))
123                         for button in self._print_material_options:
124                                 # wxpython 2.8 gives a 13 pixel high radio/checkbutton but wxpython 3.0
125                                 # gives it a 25 pixels height, so we add a border to compensate for the ugliness
126                                 if button.GetBestSize()[1] < 20:
127                                         border = 5
128                                 else:
129                                         border = 0
130                                 boxsizer.Add(button, border=border, flag=wx.ALL)
131                         self.printMaterialPanel.SetSizer(wx.BoxSizer(wx.VERTICAL))
132                         self.printMaterialPanel.GetSizer().Add(boxsizer, flag=wx.EXPAND)
133                         self.materialCombo = None
134                 else:
135                         boxsizer = wx.BoxSizer(wx.VERTICAL)
136                         boxsizer.SetMinSize((80, 20))
137                         label = wx.StaticText(self.printMaterialPanel, label=_("Material:"))
138                         self.materialCombo = wx.ComboBox(self.printMaterialPanel, -1, selectedMaterial.name,
139                                                                                          choices=[], style=wx.CB_READONLY)
140                         self.materialCombo.Bind(wx.EVT_COMBOBOX, self._materialSelected)
141                         boxsizer.Add(label, flag=wx.EXPAND)
142                         boxsizer.Add(self.materialCombo, border=5, flag=wx.BOTTOM|wx.TOP|wx.EXPAND)
143                         self.printMaterialPanel.SetSizer(boxsizer)
144                 self.materialHyperlink = wx.HyperlinkCtrl(self.printMaterialPanel, -1, label=_('Material Information'), url='',
145                                                                                                   style=wx.HL_ALIGN_LEFT|wx.BORDER_NONE|wx.HL_CONTEXTMENU)
146                 self.materialHyperlink.Show(False)
147                 self.materialDescription = wx.StaticText(self.printMaterialPanel, -1, '')
148                 self.materialDescription.Show(False)
149                 boxsizer.Add(self.materialDescription, border=5, flag=wx.BOTTOM|wx.TOP|wx.EXPAND)
150                 boxsizer.Add(self.materialHyperlink, border=5, flag=wx.BOTTOM|wx.TOP|wx.EXPAND)
151                 sizer.Add(self.printMaterialPanel, (1,0), border=10, flag=wx.EXPAND|wx.RIGHT|wx.LEFT|wx.TOP)
152
153                 sb = wx.StaticBox(self.printTypePanel, label=_("Select a quickprint profile:"))
154                 boxsizer = wx.StaticBoxSizer(sb, wx.VERTICAL)
155                 boxsizer.SetMinSize((180, 20))
156                 self.printTypePanel.SetSizer(wx.BoxSizer(wx.VERTICAL))
157                 self.printTypePanel.GetSizer().Add(boxsizer, flag=wx.EXPAND)
158                 sizer.Add(self.printTypePanel, (2,0), border=10, flag=wx.EXPAND|wx.RIGHT|wx.LEFT|wx.TOP)
159
160
161                 self.printOptionsBox = wx.StaticBox(self, label=_("Other options:"))
162                 boxsizer = wx.StaticBoxSizer(self.printOptionsBox, wx.VERTICAL)
163                 boxsizer.SetMinSize((100, 20))
164                 sizer.Add(boxsizer, (3,0), border=10, flag=wx.EXPAND|wx.RIGHT|wx.LEFT|wx.TOP)
165                 self.printOptionsSizer = boxsizer
166
167                 if selectedMaterialType:
168                         self.materialTypeCombo.SetValue(selectedMaterialType)
169                         self._materialTypeSelected(None)
170                 if selectedMaterial:
171                         if self.materialCombo:
172                                 self.materialCombo.SetValue(selectedMaterial.name)
173                         else:
174                                 for button in self._print_material_options:
175                                         if button.profile == selectedMaterial:
176                                                 button.SetValue(True)
177                                                 break
178                 self._materialSelected(None)
179                 self.Layout()
180
181         def _materialTypeSelected(self, e):
182                 materialType = self.materialTypeCombo.GetValue()
183                 selection = self.materialTypeCombo.GetSelection()
184                 choices = []
185
186                 if selection >= len(self._print_material_types.keys()):
187                         materials = self._all_print_materials
188                         for material in materials:
189                                 choices.append(material.full_name)
190                 else:
191                         materials = self._print_material_types[materialType]
192                         for material in materials:
193                                 choices.append(material.name)
194
195                 # Decide on the default selected material
196                 selectedMaterial = None
197                 for material in materials:
198                         if material.default:
199                                 selectedMaterial = material
200                                 break
201
202                 if selectedMaterial is None and len(materials) > 0:
203                         selectedMaterial = materials[0]
204
205                 self.materialCombo.Clear()
206                 self.materialCombo.AppendItems(choices)
207                 if len(materials) == 0:
208                         self.printMaterialTypesPanel.Show(False)
209                 else:
210                         self.printMaterialTypesPanel.Show(True)
211                         self.materialCombo.SetValue(selectedMaterial.name)
212
213                 self.materialCombo.Layout()
214                 self.printMaterialPanel.Layout()
215                 self._materialSelected(e)
216
217         def _getSelectedMaterial(self):
218                 if self.materialCombo:
219                         materialType = self.materialTypeCombo.GetValue()
220                         selection = self.materialTypeCombo.GetSelection()
221
222                         if selection >= len(self._print_material_types.keys()):
223                                 materials = self._all_print_materials
224                         else:
225                                 materials = self._print_material_types[materialType]
226
227                         selection = self.materialCombo.GetSelection()
228
229                         # This is needed to avoid a wxpython 2.8 bug which returns -1
230                         # when the selection is made with SetValue
231                         if selection == -1:
232                                 material_name = self.materialCombo.GetValue()
233                                 for material in materials:
234                                         if material.name == material_name:
235                                                 return material
236
237                         return materials[selection]
238                 else:
239                         for button in self._print_material_options:
240                                 if button.GetValue():
241                                         return button.profile
242                         return None
243
244
245         def _materialSelected(self, e):
246                 material = self._getSelectedMaterial()
247
248                 # Delete profile options
249                 boxsizer = self.printTypePanel.GetSizer().GetItem(0).GetSizer()
250                 boxsizer.Clear(True)
251                 self._print_profile_options = []
252
253                 if material is None:
254                         self.printOptionsBox.Show(False)
255                         self.printTypePanel.Show(False)
256                         return
257                 self.printOptionsBox.Show(True)
258                 self.printTypePanel.Show(True)
259
260                 self.materialHyperlink.Show(material.url is not None)
261                 if material.url:
262                         self.materialHyperlink.SetURL(material.url)
263                 self.materialDescription.Show(material.description is not None)
264                 if material.description:
265                         self.materialDescription.SetLabel(material.description)
266
267                 # Add new profiles
268                 selectedProfile = None
269                 for print_profile in material.profiles:
270                         if print_profile.disabled:
271                                 continue
272                         button = wx.RadioButton(self.printTypePanel, -1, print_profile.name.replace('&', '&&'),
273                                                                         style=wx.RB_GROUP if len(self._print_profile_options) == 0 else 0)
274                         button.profile = print_profile
275                         self._print_profile_options.append(button)
276                         if profile.getProfileSetting('simpleModeProfile') == print_profile.name:
277                                 selectedProfile = button
278
279                 # Decide on the profile to be selected by default
280                 if selectedProfile is None:
281                         for button in self._print_profile_options:
282                                 if button.profile.default:
283                                         selectedProfile = button
284                                         break
285
286                 if selectedProfile is None and len(self._print_profile_options) > 0:
287                         selectedProfile = self._print_profile_options[0]
288
289                 # Decide if we show the profile panel or not
290                 if len(self._print_profile_options) < 2:
291                         self.printTypePanel.Show(len(self._print_profile_options) > 0 and \
292                                                                          self._print_profile_options[0].profile.always_visible)
293
294                 if selectedProfile:
295                         selectedProfile.SetValue(True)
296
297                 # Add profiles to the UI
298                 for button in self._print_profile_options:
299                         # wxpython 2.8 gives a 13 pixel high radio/checkbutton but wxpython 3.0
300                         # gives it a 25 pixels height, so we add a border to compensate for the ugliness
301                         if button.GetBestSize()[1] < 20:
302                                 border = 5
303                         else:
304                                 border = 0
305                         boxsizer.Add(button, border=border, flag=wx.ALL)
306                         button.Bind(wx.EVT_RADIOBUTTON, self._update)
307
308                 # Save current selected options
309                 selected_options = []
310                 deselected_options = []
311                 for button in self._print_other_options:
312                         if button.GetValue():
313                                 selected_options.append(button.profile.name)
314                         else:
315                                 deselected_options.append(button.profile.name)
316
317                 # Delete profile options
318                 boxsizer = self.printOptionsSizer
319                 boxsizer.Clear(True)
320                 self._print_other_options = []
321
322                 # Create new options
323                 for option in material.options:
324                         if option.disabled:
325                                 continue
326                         button = wx.CheckBox(self, -1, option.name.replace('&', '&&'))
327                         button.profile = option
328                         self._print_other_options.append(button)
329                         # Restore selection on similarly named options
330                         if option.name in selected_options or \
331                            ((not option.name in deselected_options) and option.default):
332                                 button.SetValue(True)
333
334                 # Decide if we show the profile panel or not
335                 # The always_visible doesn't make sense for options since they are checkboxes, and not radio buttons
336                 self.printOptionsBox.Show(len(self._print_other_options) > 0)
337
338                 # Add profiles to the UI
339                 for button in self._print_other_options:
340                         # wxpython 2.8 gives a 13 pixel high radio/checkbutton but wxpython 3.0
341                         # gives it a 25 pixels height, so we add a border to compensate for the ugliness
342                         if button.GetBestSize()[1] < 20:
343                                 border = 5
344                         else:
345                                 border = 0
346                         boxsizer.Add(button, border=border, flag=wx.ALL)
347                         button.Bind(wx.EVT_CHECKBOX, self._update)
348
349                 self.printTypePanel.Layout()
350                 self.Layout()
351                 self.GetParent().Fit()
352
353                 # Do not call the callback on the initial UI build
354                 if e is not None:
355                         self._update(e)
356
357         def _update(self, e):
358                 if self.materialTypeCombo:
359                         materialType = self.materialTypeCombo.GetValue()
360                         profile.putProfileSetting('simpleModeMaterialType', materialType)
361                 material = self._getSelectedMaterial()
362                 if material:
363                         profile.putProfileSetting('simpleModeMaterial', material.name)
364                 for button in self._print_profile_options:
365                         if button.GetValue():
366                                 profile.putProfileSetting('simpleModeProfile', button.profile.name)
367                 self._callback()
368
369         def getSettingOverrides(self):
370                 settings = {}
371                 for setting in profile.settingsList:
372                         if setting.isProfile() or setting.isAlteration():
373                                 settings[setting.getName()] = setting.getDefault()
374
375                 # Apply materials, profile, then options
376                 material = self._getSelectedMaterial()
377                 if material:
378                         settings.update(material.getProfileDict())
379                 for button in self._print_profile_options:
380                         if button.GetValue():
381                                 settings.update(button.profile.getProfileDict())
382                 for button in self._print_other_options:
383                         if button.GetValue():
384                                 settings.update(button.profile.getProfileDict())
385
386                 return settings
387
388         def updateProfileToControls(self):
389                 pass