chiark / gitweb /
Increment version number
[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') == _("All"):
82                                         selectedMaterialType = profile.getProfileSetting('simpleModeMaterialType')
83                                 elif selectedMaterial is None or len(selectedMaterial.types) == 0:
84                                         selectedMaterialType = _("Others")
85                                 else:
86                                         selectedMaterialType = selectedMaterial.types[0]
87
88                 # Decide to show the material types or not
89                 if self._print_material_types is None:
90                         self.printMaterialTypesPanel.Show(False)
91
92                 self.printTypePanel = wx.Panel(self)
93
94                 sizer = wx.GridBagSizer()
95                 self.SetSizer(sizer)
96
97                 boxsizer = wx.BoxSizer(wx.VERTICAL)
98                 boxsizer.SetMinSize((80, 20))
99                 if self._print_material_types is None:
100                         self.materialTypeCombo = None
101                 else:
102                         choices = self._print_material_types.keys()
103                         choices.sort(key=lambda type: sum([mat.order for mat in self._print_material_types[type]]))
104                         # Now we can add Others, so it appears towards the end
105                         if len(other_print_material_types) > 0:
106                                 self._print_material_types[_("Others")] = other_print_material_types
107                                 choices.append(_("Others"))
108                         choices.append(_("All"))
109                         label = wx.StaticText(self.printMaterialTypesPanel, label=_("Material ease of use:"))
110                         self.materialTypeCombo = wx.ComboBox(self.printMaterialTypesPanel, -1, selectedMaterialType,
111                                                                                                  choices=choices, style=wx.CB_READONLY)
112                         self.materialTypeCombo.Bind(wx.EVT_COMBOBOX, self._materialTypeSelected)
113                         boxsizer.Add(label, flag=wx.EXPAND)
114                         boxsizer.Add(self.materialTypeCombo, border=5, flag=wx.BOTTOM|wx.TOP|wx.EXPAND)
115                 self.printMaterialTypesPanel.SetSizer(boxsizer)
116                 sizer.Add(self.printMaterialTypesPanel, (0,0), border=10, flag=wx.EXPAND|wx.RIGHT|wx.LEFT|wx.TOP)
117
118                 if self._print_material_types is None:
119                         sb = wx.StaticBox(self.printMaterialPanel, label=_("Material:"))
120                         boxsizer = wx.StaticBoxSizer(sb, wx.VERTICAL)
121                         boxsizer.SetMinSize((80, 20))
122                         for button in self._print_material_options:
123                                 # wxpython 2.8 gives a 13 pixel high radio/checkbutton but wxpython 3.0
124                                 # gives it a 25 pixels height, so we add a border to compensate for the ugliness
125                                 if button.GetBestSize()[1] < 20:
126                                         border = 5
127                                 else:
128                                         border = 0
129                                 boxsizer.Add(button, border=border, flag=wx.ALL)
130                         self.printMaterialPanel.SetSizer(wx.BoxSizer(wx.VERTICAL))
131                         self.printMaterialPanel.GetSizer().Add(boxsizer, flag=wx.EXPAND)
132                         self.materialCombo = None
133                 else:
134                         boxsizer = wx.BoxSizer(wx.VERTICAL)
135                         boxsizer.SetMinSize((80, 20))
136                         label = wx.StaticText(self.printMaterialPanel, label=_("Material:"))
137                         self.materialCombo = wx.ComboBox(self.printMaterialPanel, -1, selectedMaterial.name,
138                                                                                          choices=[], style=wx.CB_READONLY)
139                         self.materialCombo.Bind(wx.EVT_COMBOBOX, self._materialSelected)
140                         boxsizer.Add(label, flag=wx.EXPAND)
141                         boxsizer.Add(self.materialCombo, border=5, flag=wx.BOTTOM|wx.TOP|wx.EXPAND)
142                         self.printMaterialPanel.SetSizer(boxsizer)
143                 self.materialHyperlink = wx.HyperlinkCtrl(self.printMaterialPanel, -1, label=_('Material Information'), url='',
144                                                                                                   style=wx.HL_ALIGN_LEFT|wx.BORDER_NONE|wx.HL_CONTEXTMENU)
145                 self.materialHyperlink.Show(False)
146                 self.materialDescription = wx.StaticText(self.printMaterialPanel, -1, '')
147                 self.materialDescription.Show(False)
148                 boxsizer.Add(self.materialDescription, border=5, flag=wx.BOTTOM|wx.TOP|wx.EXPAND)
149                 boxsizer.Add(self.materialHyperlink, border=5, flag=wx.BOTTOM|wx.TOP|wx.EXPAND)
150                 sizer.Add(self.printMaterialPanel, (1,0), border=10, flag=wx.EXPAND|wx.RIGHT|wx.LEFT|wx.TOP)
151
152                 sb = wx.StaticBox(self.printTypePanel, label=_("Select a quickprint profile:"))
153                 boxsizer = wx.StaticBoxSizer(sb, wx.VERTICAL)
154                 boxsizer.SetMinSize((180, 20))
155                 self.printTypePanel.SetSizer(wx.BoxSizer(wx.VERTICAL))
156                 self.printTypePanel.GetSizer().Add(boxsizer, flag=wx.EXPAND)
157                 sizer.Add(self.printTypePanel, (2,0), border=10, flag=wx.EXPAND|wx.RIGHT|wx.LEFT|wx.TOP)
158
159
160                 self.printOptionsBox = wx.StaticBox(self, label=_("Other options:"))
161                 boxsizer = wx.StaticBoxSizer(self.printOptionsBox, wx.VERTICAL)
162                 boxsizer.SetMinSize((100, 20))
163                 sizer.Add(boxsizer, (3,0), border=10, flag=wx.EXPAND|wx.RIGHT|wx.LEFT|wx.TOP)
164                 self.printOptionsSizer = boxsizer
165
166                 if selectedMaterialType:
167                         self.materialTypeCombo.SetValue(selectedMaterialType)
168                         self._materialTypeSelected(None)
169                 if selectedMaterial:
170                         if self.materialCombo:
171                                 self.materialCombo.SetValue(selectedMaterial.name)
172                         else:
173                                 for button in self._print_material_options:
174                                         if button.profile == selectedMaterial:
175                                                 button.SetValue(True)
176                                                 break
177                 self._materialSelected(None)
178                 self.Layout()
179
180         def _materialTypeSelected(self, e):
181                 materialType = self.materialTypeCombo.GetValue()
182                 selection = self.materialTypeCombo.GetSelection()
183                 choices = []
184
185                 if selection >= len(self._print_material_types.keys()) or \
186                    selection == -1:
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()) or \
223                            selection == -1:
224                                 materials = self._all_print_materials
225                         else:
226                                 materials = self._print_material_types[materialType]
227
228                         selection = self.materialCombo.GetSelection()
229
230                         return materials[selection]
231                 else:
232                         for button in self._print_material_options:
233                                 if button.GetValue():
234                                         return button.profile
235                         return None
236
237
238         def _materialSelected(self, e):
239                 material = self._getSelectedMaterial()
240
241                 # Delete profile options
242                 boxsizer = self.printTypePanel.GetSizer().GetItem(0).GetSizer()
243                 boxsizer.Clear(True)
244                 self._print_profile_options = []
245
246                 if material is None:
247                         self.printOptionsBox.Show(False)
248                         self.printTypePanel.Show(False)
249                         return
250                 self.printOptionsBox.Show(True)
251                 self.printTypePanel.Show(True)
252
253                 self.materialHyperlink.Show(material.url is not None)
254                 if material.url:
255                         self.materialHyperlink.SetURL(material.url)
256                 self.materialDescription.Show(material.description is not None)
257                 if material.description:
258                         self.materialDescription.SetLabel(material.description)
259
260                 # Add new profiles
261                 selectedProfile = None
262                 for print_profile in material.profiles:
263                         if print_profile.disabled:
264                                 continue
265                         button = wx.RadioButton(self.printTypePanel, -1, print_profile.name.replace('&', '&&'),
266                                                                         style=wx.RB_GROUP if len(self._print_profile_options) == 0 else 0)
267                         button.profile = print_profile
268                         self._print_profile_options.append(button)
269                         if profile.getProfileSetting('simpleModeProfile') == print_profile.name:
270                                 selectedProfile = button
271
272                 # Decide on the profile to be selected by default
273                 if selectedProfile is None:
274                         for button in self._print_profile_options:
275                                 if button.profile.default:
276                                         selectedProfile = button
277                                         break
278
279                 if selectedProfile is None and len(self._print_profile_options) > 0:
280                         selectedProfile = self._print_profile_options[0]
281
282                 # Decide if we show the profile panel or not
283                 if len(self._print_profile_options) < 2:
284                         self.printTypePanel.Show(len(self._print_profile_options) > 0 and \
285                                                                          self._print_profile_options[0].profile.always_visible)
286
287                 if selectedProfile:
288                         selectedProfile.SetValue(True)
289
290                 # Add profiles to the UI
291                 for button in self._print_profile_options:
292                         # wxpython 2.8 gives a 13 pixel high radio/checkbutton but wxpython 3.0
293                         # gives it a 25 pixels height, so we add a border to compensate for the ugliness
294                         if button.GetBestSize()[1] < 20:
295                                 border = 5
296                         else:
297                                 border = 0
298                         boxsizer.Add(button, border=border, flag=wx.ALL)
299                         button.Bind(wx.EVT_RADIOBUTTON, self._update)
300
301                 # Save current selected options
302                 selected_options = []
303                 deselected_options = []
304                 for button in self._print_other_options:
305                         if button.GetValue():
306                                 selected_options.append(button.profile.name)
307                         else:
308                                 deselected_options.append(button.profile.name)
309
310                 # Delete profile options
311                 boxsizer = self.printOptionsSizer
312                 boxsizer.Clear(True)
313                 self._print_other_options = []
314
315                 # Create new options
316                 for option in material.options:
317                         if option.disabled:
318                                 continue
319                         button = wx.CheckBox(self, -1, option.name.replace('&', '&&'))
320                         button.profile = option
321                         self._print_other_options.append(button)
322                         # Restore selection on similarly named options
323                         if option.name in selected_options or \
324                            ((not option.name in deselected_options) and option.default):
325                                 button.SetValue(True)
326
327                 # Decide if we show the profile panel or not
328                 # The always_visible doesn't make sense for options since they are checkboxes, and not radio buttons
329                 self.printOptionsBox.Show(len(self._print_other_options) > 0)
330
331                 # Add profiles to the UI
332                 for button in self._print_other_options:
333                         # wxpython 2.8 gives a 13 pixel high radio/checkbutton but wxpython 3.0
334                         # gives it a 25 pixels height, so we add a border to compensate for the ugliness
335                         if button.GetBestSize()[1] < 20:
336                                 border = 5
337                         else:
338                                 border = 0
339                         boxsizer.Add(button, border=border, flag=wx.ALL)
340                         button.Bind(wx.EVT_CHECKBOX, self._update)
341
342                 self.printTypePanel.Layout()
343                 self.Layout()
344                 self.GetParent().Fit()
345
346                 # Do not call the callback on the initial UI build
347                 if e is not None:
348                         self._update(e)
349
350         def _update(self, e):
351                 if self.materialTypeCombo:
352                         materialType = self.materialTypeCombo.GetValue()
353                         profile.putProfileSetting('simpleModeMaterialType', materialType)
354                 material = self._getSelectedMaterial()
355                 if material:
356                         profile.putProfileSetting('simpleModeMaterial', material.name)
357                 for button in self._print_profile_options:
358                         if button.GetValue():
359                                 profile.putProfileSetting('simpleModeProfile', button.profile.name)
360                 self._callback()
361
362         def getSettingOverrides(self):
363                 settings = {}
364                 for setting in profile.settingsList:
365                         if setting.isProfile() or setting.isAlteration():
366                                 settings[setting.getName()] = setting.getDefault()
367
368                 # Apply materials, profile, then options
369                 material = self._getSelectedMaterial()
370                 if material:
371                         settings.update(material.getProfileDict())
372                 for button in self._print_profile_options:
373                         if button.GetValue():
374                                 settings.update(button.profile.getProfileDict())
375                 for button in self._print_other_options:
376                         if button.GetValue():
377                                 settings.update(button.profile.getProfileDict())
378
379                 return settings
380
381         def updateProfileToControls(self):
382                 pass