chiark / gitweb /
58b82ce51b1c10924ad69b6039456ed2c60f07d6
[cura.git] / Cura / cura_sf / fabmetheus_utilities / settings.py
1 """
2 Settings is a collection of utilities to display, read & write the settings and position widgets.
3
4 """
5
6 from __future__ import absolute_import
7 from __future__ import division
8 #Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module.
9 import __init__
10
11 import os, sys
12 import types, math
13
14 from util import profile
15 from fabmetheus_utilities import archive
16
17 def DEFSET(setting):
18         return setting.value
19
20 def storedSetting(name):
21         return lambda setting: profile.getProfileSetting(name)
22 def storedSettingFloat(name):
23         return lambda setting: profile.getProfileSettingFloat(name)
24 def storedSettingInt(name):
25         return lambda setting: int(profile.getProfileSettingFloat(name))
26 def storedPreference(name):
27         return lambda setting: profile.getPreference(name)
28
29 def ifSettingAboveZero(name):
30         return lambda setting: profile.getProfileSettingFloat(name) > 0
31
32 def ifSettingIs(name, value):
33         return lambda setting: profile.getProfileSetting(name) == value
34
35 def raftLayerCount(setting):
36         if profile.getProfileSetting('enable_raft') == "True":
37                 return '1'
38         return '0'
39
40 def storedPercentSetting(name):
41         return lambda setting: profile.getProfileSettingFloat(name) / 100
42
43 def calculateEdgeWidth(setting):
44         return profile.calculateEdgeWidth()
45
46 def calculateShells(setting):
47         return profile.calculateLineCount() - 1
48
49 def calculateShellsBase(setting):
50         edgeWidth = profile.calculateEdgeWidth()
51         extraWall = profile.getProfileSettingFloat('extra_base_wall_thickness')
52         
53         return profile.calculateLineCount() - 1 + int(extraWall / edgeWidth + 0.0001)
54
55 def calculateSolidLayerCount(setting):
56         return profile.calculateSolidLayerCount()
57
58 def firstLayerSpeedRatio(setting):
59         bottomSpeed = profile.getProfileSettingFloat('bottom_layer_speed')
60         speed = profile.getProfileSettingFloat('print_speed')
61         return bottomSpeed/speed
62
63 def calcSupportDistanceRatio(setting):
64         edgeWidth = calculateEdgeWidth(setting)
65         distance = profile.getProfileSettingFloat('support_distance')
66         return distance / edgeWidth
67
68 def calculateMultiplyDistance(setting):
69         edgeWidth = calculateEdgeWidth(setting)
70         return 10.0 / edgeWidth
71
72 def calcBottomLayerFlowRateRatio(setting):
73         bottomThickness = profile.getProfileSettingFloat('bottom_thickness')
74         layerThickness = profile.getProfileSettingFloat('layer_height')
75         if bottomThickness < layerThickness:
76                 return 1.0
77         return bottomThickness / layerThickness
78
79 def calcExtraBottomThickness(setting):
80         bottomThickness = profile.getProfileSettingFloat('bottom_thickness')
81         layerThickness = profile.getProfileSettingFloat('layer_height')
82         if bottomThickness < layerThickness:
83                 return 0.0
84         return bottomThickness - layerThickness
85
86 def calcLayerSkip(setting):
87         bottomThickness = profile.getProfileSettingFloat('bottom_thickness')
88         layerThickness = profile.getProfileSettingFloat('layer_height')
89         if bottomThickness < layerThickness:
90                 return 0
91         return int(math.ceil((bottomThickness - layerThickness) / layerThickness + 0.0001) - 1)
92
93 def getProfileInformation():
94         return {
95                 'carve': {
96                         'Add_Layer_Template_to_SVG': DEFSET,
97                         'Edge_Width_mm': calculateEdgeWidth,
98                         'Extra_Decimal_Places_float': DEFSET,
99                         'Import_Coarseness_ratio': DEFSET,
100                         'Layer_Height_mm': storedSettingFloat("layer_height"),
101                         'Layers_From_index': calcLayerSkip,
102                         'Layers_To_index': DEFSET,
103                         'Correct_Mesh': DEFSET,
104                         'Unproven_Mesh': DEFSET,
105                         'SVG_Viewer': DEFSET,
106                         'FlipX': storedSetting("flip_x"),
107                         'FlipY': storedSetting("flip_y"),
108                         'FlipZ': storedSetting("flip_z"),
109                         'SwapXZ': storedSetting("swap_xz"),
110                         'SwapYZ': storedSetting("swap_yz"),
111                         'Scale': storedSettingFloat("model_scale"),
112                         'Rotate': storedSettingFloat("model_rotate_base"),
113                 },'scale': {
114                         'Activate_Scale': "False",
115                         'XY_Plane_Scale_ratio': DEFSET,
116                         'Z_Axis_Scale_ratio': DEFSET,
117                         'SVG_Viewer': DEFSET,
118                 },'bottom': {
119                         'Activate_Bottom': DEFSET,
120                         'Additional_Height_over_Layer_Thickness_ratio': DEFSET,
121                         'Altitude_mm': calcExtraBottomThickness,
122                         'SVG_Viewer': DEFSET,
123                 },'preface': {
124                         'Meta': DEFSET,
125                         'Set_Positioning_to_Absolute': DEFSET,
126                         'Set_Units_to_Millimeters': DEFSET,
127                         'Start_at_Home': DEFSET,
128                         'Turn_Extruder_Off_at_Shut_Down': DEFSET,
129                         'Turn_Extruder_Off_at_Start_Up': DEFSET,
130                 },'widen': {
131                         'Activate_Widen': DEFSET,
132                         'Widen_Width_over_Edge_Width_ratio': DEFSET,
133                 },'inset': {
134                         'Add_Custom_Code_for_Temperature_Reading': "False",
135                         'Infill_in_Direction_of_Bridge': "True",
136                         'Infill_Width': storedSettingFloat("nozzle_size"),
137                         'Loop_Order_Choice': DEFSET,
138                         'Overlap_Removal_Width_over_Perimeter_Width_ratio': DEFSET,
139                         'Turn_Extruder_Heater_Off_at_Shut_Down': DEFSET,
140                         'Volume_Fraction_ratio': DEFSET,
141                 },'fill': {
142                         'Activate_Fill': "True",
143                         'Solid_Surface_Top': storedSetting("solid_top"),
144                         'Override_First_Layer_Sequence': storedSetting("force_first_layer_sequence"),
145                         'Diaphragm_Period_layers': DEFSET,
146                         'Diaphragm_Thickness_layers': DEFSET,
147                         'Extra_Shells_on_Alternating_Solid_Layer_layers': calculateShells,
148                         'Extra_Shells_on_Base_layers': calculateShellsBase,
149                         'Extra_Shells_on_Sparse_Layer_layers': calculateShells,
150                         'Grid_Circle_Separation_over_Perimeter_Width_ratio': DEFSET,
151                         'Grid_Extra_Overlap_ratio': DEFSET,
152                         'Grid_Junction_Separation_Band_Height_layers': DEFSET,
153                         'Grid_Junction_Separation_over_Octogon_Radius_At_End_ratio': DEFSET,
154                         'Grid_Junction_Separation_over_Octogon_Radius_At_Middle_ratio': DEFSET,
155                         'Infill_Begin_Rotation_degrees': DEFSET,
156                         'Infill_Begin_Rotation_Repeat_layers': DEFSET,
157                         'Infill_Odd_Layer_Extra_Rotation_degrees': DEFSET,
158                         'Grid_Circular': ifSettingIs('infill_type', 'Grid Circular'),
159                         'Grid_Hexagonal': ifSettingIs('infill_type', 'Grid Hexagonal'),
160                         'Grid_Rectangular': ifSettingIs('infill_type', 'Grid Rectangular'),
161                         'Line': ifSettingIs('infill_type', 'Line'),
162                         'Infill_Perimeter_Overlap_ratio': storedPercentSetting('fill_overlap'),
163                         'Infill_Solidity_ratio': storedPercentSetting('fill_density'),
164                         'Infill_Width': storedSettingFloat("nozzle_size"),
165                         'Sharpest_Angle_degrees': DEFSET,
166                         'Solid_Surface_Thickness_layers': calculateSolidLayerCount,
167                         'Start_From_Choice': DEFSET,
168                         'Surrounding_Angle_degrees': DEFSET,
169                         'Thread_Sequence_Choice': storedSetting('sequence'),
170                 },'multiply': {
171                         'Activate_Multiply': "True",
172                         'Center_X_mm': storedSettingFloat("machine_center_x"),
173                         'Center_Y_mm': storedSettingFloat("machine_center_y"),
174                         'Number_of_Columns_integer': storedSetting('model_multiply_x'),
175                         'Number_of_Rows_integer': storedSetting('model_multiply_y'),
176                         'Reverse_Sequence_every_Odd_Layer': DEFSET,
177                         'Separation_over_Perimeter_Width_ratio': calculateMultiplyDistance,
178                 },'speed': {
179                         'Activate_Speed': "True",
180                         'Add_Flow_Rate': "True",
181                         'Bridge_Feed_Rate_Multiplier_ratio': storedPercentSetting('bridge_speed'),
182                         'Bridge_Flow_Rate_Multiplier_ratio': storedPercentSetting('bridge_material_amount'),
183                         'Duty_Cyle_at_Beginning_portion': DEFSET,
184                         'Duty_Cyle_at_Ending_portion': DEFSET,
185                         'Feed_Rate_mm/s': storedSettingFloat("print_speed"),
186                         'Flow_Rate_Setting_float': storedSettingFloat("print_speed"),
187                         'Object_First_Layer_Feed_Rate_Infill_Multiplier_ratio': firstLayerSpeedRatio,
188                         'Object_First_Layer_Feed_Rate_Perimeter_Multiplier_ratio': firstLayerSpeedRatio,
189                         'Object_First_Layer_Feed_Rate_Travel_Multiplier_ratio': firstLayerSpeedRatio,
190                         'Object_First_Layer_Flow_Rate_Infill_Multiplier_ratio': firstLayerSpeedRatio,
191                         'Object_First_Layer_Flow_Rate_Perimeter_Multiplier_ratio': firstLayerSpeedRatio,
192                         'Object_First_Layers_Amount_Of_Layers_For_Speed_Change': DEFSET,
193                         'Orbital_Feed_Rate_over_Operating_Feed_Rate_ratio': DEFSET,
194                         'Maximum_Z_Feed_Rate_mm/s': DEFSET,
195                         'Perimeter_Feed_Rate_Multiplier_ratio': DEFSET,
196                         'Perimeter_Flow_Rate_Multiplier_ratio': DEFSET,
197                         'Travel_Feed_Rate_mm/s': storedSettingFloat("travel_speed"),
198                         'Bottom_layer_flow_rate_ratio': calcBottomLayerFlowRateRatio,
199                 },'temperature': {
200                         'Activate_Temperature': DEFSET,#ifSettingAboveZero('print_temperature'),
201                         'Cooling_Rate_Celcius/second': DEFSET,
202                         'Heating_Rate_Celcius/second': DEFSET,
203                         'Base_Temperature_Celcius': DEFSET,#storedSettingFloat("print_temperature"),
204                         'Interface_Temperature_Celcius': DEFSET,#storedSettingFloat("print_temperature"),
205                         'Object_First_Layer_Infill_Temperature_Celcius': DEFSET,#storedSettingFloat("print_temperature"),
206                         'Object_First_Layer_Perimeter_Temperature_Celcius': DEFSET,#storedSettingFloat("print_temperature"),
207                         'Object_Next_Layers_Temperature_Celcius': DEFSET,#storedSettingFloat("print_temperature"),
208                         'Support_Layers_Temperature_Celcius': DEFSET,#storedSettingFloat("print_temperature"),
209                         'Supported_Layers_Temperature_Celcius': DEFSET,#storedSettingFloat("print_temperature"),
210                 },'raft': {
211                         'Activate_Raft': "True",
212                         'Add_Raft,_Elevate_Nozzle,_Orbit': DEFSET,
213                         'Base_Feed_Rate_Multiplier_ratio': DEFSET,
214                         'Base_Flow_Rate_Multiplier_ratio': storedPercentSetting('raft_base_material_amount'),
215                         'Base_Infill_Density_ratio': DEFSET,
216                         'Base_Layer_Thickness_over_Layer_Thickness': DEFSET,
217                         'Base_Layers_integer': raftLayerCount,
218                         'Base_Nozzle_Lift_over_Base_Layer_Thickness_ratio': DEFSET,
219                         'Initial_Circling': DEFSET,
220                         'Infill_Overhang_over_Extrusion_Width_ratio': DEFSET,
221                         'Interface_Feed_Rate_Multiplier_ratio': DEFSET,
222                         'Interface_Flow_Rate_Multiplier_ratio': storedPercentSetting('raft_interface_material_amount'),
223                         'Interface_Infill_Density_ratio': DEFSET,
224                         'Interface_Layer_Thickness_over_Layer_Thickness': DEFSET,
225                         'Interface_Layers_integer': raftLayerCount,
226                         'Interface_Nozzle_Lift_over_Interface_Layer_Thickness_ratio': DEFSET,
227                         'Name_of_Support_End_File': DEFSET,
228                         'Name_of_Support_Start_File': DEFSET,
229                         'Operating_Nozzle_Lift_over_Layer_Thickness_ratio': DEFSET,
230                         'Raft_Additional_Margin_over_Length_%': DEFSET,
231                         'Raft_Margin_mm': storedSettingFloat('raft_margin'),
232                         'Support_Cross_Hatch': 'False',
233                         'Support_Flow_Rate_over_Operating_Flow_Rate_ratio': storedPercentSetting('support_rate'),
234                         'Support_Gap_over_Perimeter_Extrusion_Width_ratio': calcSupportDistanceRatio,
235                         'Support_Material_Choice_': storedSetting('support'),
236                         'Support_Minimum_Angle_degrees': DEFSET,
237                 },'skirt': {
238                         'Skirt_line_count': storedSetting("skirt_line_count"),
239                         'Convex': "True",
240                         'Gap_Width_mm': storedSetting("skirt_gap"),
241                         'Layers_To_index': "1",
242                 },'joris': {
243                         'Activate_Joris': storedSetting("joris"),
244                         'Layers_From_index': calculateSolidLayerCount,
245                 },'chamber': {
246                         'Activate_Chamber': "False",
247                         'Bed_Temperature_Celcius': DEFSET,
248                         'Bed_Temperature_Begin_Change_Height_mm': DEFSET,
249                         'Bed_Temperature_End_Change_Height_mm': DEFSET,
250                         'Bed_Temperature_End_Celcius': DEFSET,
251                         'Chamber_Temperature_Celcius': DEFSET,
252                         'Holding_Force_bar': DEFSET,
253                 },'tower': {
254                         'Activate_Tower': "False",
255                         'Extruder_Possible_Collision_Cone_Angle_degrees': DEFSET,
256                         'Maximum_Tower_Height_layers': DEFSET,
257                         'Tower_Start_Layer_integer': DEFSET,
258                 },'jitter': {
259                         'Activate_Jitter': "False",
260                         'Jitter_Over_Perimeter_Width_ratio': DEFSET,
261                 },'clip': {
262                         'Activate_Clip': "False",
263                         'Clip_Over_Perimeter_Width_ratio': DEFSET,
264                         'Maximum_Connection_Distance_Over_Perimeter_Width_ratio': DEFSET,
265                 },'smooth': {
266                         'Activate_Smooth': "False",
267                         'Layers_From_index': DEFSET,
268                         'Maximum_Shortening_over_Width_float': DEFSET,
269                 },'stretch': {
270                         'Activate_Stretch': "False",
271                         'Cross_Limit_Distance_Over_Perimeter_Width_ratio': DEFSET,
272                         'Loop_Stretch_Over_Perimeter_Width_ratio': DEFSET,
273                         'Path_Stretch_Over_Perimeter_Width_ratio': DEFSET,
274                         'Perimeter_Inside_Stretch_Over_Perimeter_Width_ratio': DEFSET,
275                         'Perimeter_Outside_Stretch_Over_Perimeter_Width_ratio': DEFSET,
276                         'Stretch_From_Distance_Over_Perimeter_Width_ratio': DEFSET,
277                 },'skin': {
278                         'Activate_Skin': storedSetting("enable_skin"),
279                         'Horizontal_Infill_Divisions_integer': "1",
280                         'Horizontal_Perimeter_Divisions_integer': "1",
281                         'Vertical_Divisions_integer': "2",
282                         'Hop_When_Extruding_Infill': "False",
283                         'Layers_From_index': "1",
284                 },'comb': {
285                         'Activate_Comb': "True",
286                         'Running_Jump_Space_mm': DEFSET,
287                 },'cool': {
288                         'Activate_Cool': "True",
289                         'Bridge_Cool_Celcius': DEFSET,
290                         'Cool_Type': DEFSET,
291                         'Maximum_Cool_Celcius': DEFSET,
292                         'Minimum_Layer_Time_seconds': storedSettingFloat("cool_min_layer_time"),
293                         'Minimum_Orbital_Radius_millimeters': DEFSET,
294                         'Name_of_Cool_End_File': DEFSET,
295                         'Name_of_Cool_Start_File': DEFSET,
296                         'Orbital_Outset_millimeters': DEFSET,
297                         'Turn_Fan_On_at_Beginning': storedSetting("fan_enabled"),
298                         'Turn_Fan_Off_at_Ending': storedSetting("fan_enabled"),
299                         'Minimum_feed_rate_mm/s': storedSettingFloat("cool_min_feedrate"),
300                         'Fan_on_at_layer': storedSettingInt('fan_layer'),
301                         'Fan_speed_%': storedSettingInt('fan_speed'),
302                 },'hop': {
303                         'Activate_Hop': "False",
304                         'Hop_Over_Layer_Thickness_ratio': DEFSET,
305                         'Minimum_Hop_Angle_degrees': DEFSET,
306                 },'wipe': {
307                         'Activate_Wipe': "False",
308                         'Arrival_X_mm': DEFSET,
309                         'Arrival_Y_mm': DEFSET,
310                         'Arrival_Z_mm': DEFSET,
311                         'Departure_X_mm': DEFSET,
312                         'Departure_Y_mm': DEFSET,
313                         'Departure_Z_mm': DEFSET,
314                         'Wipe_X_mm': DEFSET,
315                         'Wipe_Y_mm': DEFSET,
316                         'Wipe_Z_mm': DEFSET,
317                         'Wipe_Period_layers': DEFSET,
318                 },'oozebane': {
319                         'Activate_Oozebane': "False",
320                         'After_Startup_Distance_millimeters': DEFSET,
321                         'Early_Shutdown_Distance_millimeters': DEFSET,
322                         'Early_Startup_Distance_Constant_millimeters': DEFSET,
323                         'Early_Startup_Maximum_Distance_millimeters': DEFSET,
324                         'First_Early_Startup_Distance_millimeters': DEFSET,
325                         'Minimum_Distance_for_Early_Startup_millimeters': DEFSET,
326                         'Minimum_Distance_for_Early_Shutdown_millimeters': DEFSET,
327                         'Slowdown_Startup_Steps_positive_integer': DEFSET,
328                 },'dwindle': {
329                         'Activate_Dwindle': "False",
330                         'End_Rate_Multiplier_ratio': DEFSET,
331                         'Pent_Up_Volume_cubic_millimeters': DEFSET,
332                         'Slowdown_Steps_positive_integer': DEFSET,
333                         'Slowdown_Volume_cubic_millimeters': DEFSET,
334                 },'splodge': {
335                         'Activate_Splodge': "False",
336                         'Initial_Lift_over_Extra_Thickness_ratio': DEFSET,
337                         'Initial_Splodge_Feed_Rate_mm/s': DEFSET,
338                         'Operating_Splodge_Feed_Rate_mm/s': DEFSET,
339                         'Operating_Splodge_Quantity_Length_millimeters': DEFSET,
340                         'Initial_Splodge_Quantity_Length_millimeters': DEFSET,
341                         'Operating_Lift_over_Extra_Thickness_ratio': DEFSET,
342                 },'home': {
343                         'Activate_Home': "False",
344                         'Name_of_Home_File': DEFSET,
345                 },'lash': {
346                         'Activate_Lash': "False",
347                         'X_Backlash_mm': DEFSET,
348                         'Y_Backlash_mm': DEFSET,
349                 },'fillet': {
350                         'Activate_Fillet': "False",
351                         'Arc_Point': DEFSET,
352                         'Arc_Radius': DEFSET,
353                         'Arc_Segment': DEFSET,
354                         'Bevel': DEFSET,
355                         'Corner_Feed_Rate_Multiplier_ratio': DEFSET,
356                         'Fillet_Radius_over_Perimeter_Width_ratio': DEFSET,
357                         'Reversal_Slowdown_Distance_over_Perimeter_Width_ratio': DEFSET,
358                         'Use_Intermediate_Feed_Rate_in_Corners': DEFSET,
359                 },'limit': {
360                         'Activate_Limit': "False",
361                         'Maximum_Initial_Feed_Rate_mm/s': DEFSET,
362                 },'unpause': {
363                         'Activate_Unpause': "False",
364                         'Delay_milliseconds': DEFSET,
365                         'Maximum_Speed_ratio': DEFSET,
366                 },'dimension': {
367                         'Activate_Dimension': "True",
368                         'Absolute_Extrusion_Distance': "True",
369                         'Relative_Extrusion_Distance': "False",
370                         'Extruder_Retraction_Speed_mm/s': storedSettingFloat('retraction_speed'),
371                         'Filament_Diameter_mm': storedSettingFloat("filament_diameter"),
372                         'Filament_Packing_Density_ratio': storedSettingFloat("filament_density"),
373                         'Maximum_E_Value_before_Reset_float': DEFSET,
374                         'Minimum_Travel_for_Retraction_millimeters': storedSettingFloat("retraction_min_travel"),
375                         'Retract_Within_Island': DEFSET,
376                         'Retraction_Distance_millimeters': storedSettingFloat('retraction_amount'),
377                         'Restart_Extra_Distance_millimeters': storedSettingFloat('retraction_extra'),
378                 },'alteration': {
379                         'Activate_Alteration': "True",
380                         'Name_of_End_File': "end.gcode",
381                         'Name_of_Start_File': "start.gcode",
382                         'Remove_Redundant_Mcode': "True",
383                         'Replace_Variable_with_Setting': DEFSET,
384                 },'export': {
385                         'Activate_Export': "True",
386                         'Add_Descriptive_Extension': DEFSET,
387                         'Add_Export_Suffix': DEFSET,
388                         'Add_Profile_Extension': DEFSET,
389                         'Add_Timestamp_Extension': DEFSET,
390                         'Also_Send_Output_To': DEFSET,
391                         'Analyze_Gcode': DEFSET,
392                         'Comment_Choice': DEFSET,
393                         'Do_Not_Change_Output': DEFSET,
394                         'binary_16_byte': DEFSET,
395                         'gcode_step': DEFSET,
396                         'gcode_time_segment': DEFSET,
397                         'gcode_small': DEFSET,
398                         'File_Extension': DEFSET,
399                         'Name_of_Replace_File': DEFSET,
400                         'Save_Penultimate_Gcode': "False",
401                 }
402         }
403
404 def safeConfigName(name):
405         return name.replace("=", "").replace(":", "").replace(" ", "_").replace("(", "").replace(")", "")
406
407 def getReadRepository(repository):
408         "Read the configuration for this 'repository'"
409         
410         info = getProfileInformation()
411         if not info.has_key(repository.name):
412                 print "Warning: Plugin: " + repository.name + " missing from Cura info"
413                 return repository
414         info = info[repository.name]
415         
416         #print('getReadRepository:', repository.name)
417         for p in repository.preferences:
418                 name = safeConfigName(p.name)
419                 if not info.has_key(name):
420                         print "Setting: " + repository.name + ":" + name + " missing from Cura info"
421                         continue
422                 if isinstance(info[name], types.FunctionType):
423                         p.setValueToString(str(info[name](p)))
424                 else:
425                         p.setValueToString(str(info[name]))
426
427         return repository
428
429 def printProgress(layerIndex, procedureName):
430         print ("Progress[" + procedureName + ":" + str(layerIndex+1) + "]")
431         sys.stdout.flush()
432
433 def printProgressByNumber(layerIndex, numberOfLayers, procedureName):
434         print ("Progress[" + procedureName + ":" + str(layerIndex+1) + ":" + str(numberOfLayers) + "]")
435         sys.stdout.flush()
436
437 def getAlterationFileLines(fileName):
438         'Get the alteration file line and the text lines from the fileName in the alterations directories.'
439         return getAlterationLines(fileName)
440
441 def getAlterationLines(fileName):
442         return archive.getTextLines(getAlterationFile(fileName))
443
444 def getAlterationFile(fileName):
445         return profile.getAlterationFileContents(fileName)
446
447 ####################################
448 ## Configuration settings classes ##
449 ####################################
450
451 class GeneralSetting:
452         "Just a basic setting subclass"
453         def getFromValue( self, name, repository, value ):
454                 #print('GeneralSetting:', name, repository, value )
455                 self.name = name
456                 self.value = value
457                 repository.preferences.append(self)
458                 return self
459
460 class StringSetting(GeneralSetting):
461         "A class to display, read & write a string."
462         def setValueToString(self, value):
463                 self.value = value
464
465 class BooleanSetting( GeneralSetting ):
466         "A class to display, read & write a boolean."
467         def setValueToString(self, value):
468                 self.value = str(value) == "True"
469
470 class LatentStringVar:
471         "This is actually used as 'group' object for Radio buttons. (Did I mention the code is a mess?)"
472         "This class doesn't have a name, and isn't really used for anything. It doesn't even know which repository it belongs to"
473
474 class Radio( BooleanSetting ):
475         "A class to display, read & write a boolean with associated radio button."
476         def getFromRadio( self, latentStringVar, name, repository, value ):
477                 "Initialize."
478                 #print('Radio->getFromRadio:', latentStringVar, name, repository, value )
479                 self.name = name
480                 self.value = value
481                 repository.preferences.append(self)
482                 return self
483
484 class RadioCapitalized( Radio ):
485         "A class to display, read & write a boolean with associated radio button."
486
487 class RadioCapitalizedButton( Radio ):
488         "A class to display, read & write a boolean with associated radio button. With an added configuration dialog button"
489         "Only used for the extra export options, which we are not using, so ignore the path for now"
490         def getFromPath( self, latentStringVar, name, path, repository, value ):
491                 "Initialize."
492                 #print('RadioCapitalizedButton->getFromPath:', latentStringVar, name, path, repository, value )
493                 self.name = name
494                 self.value = value
495                 repository.preferences.append(self)
496                 return self
497                 
498 class FileNameInput(StringSetting ):
499         "A class to display, read & write a fileName."
500         def getFromFileName( self, fileTypes, name, repository, value ):
501                 #print('FileNameInput:getFromFileName:', self, fileTypes, name, repository, value )
502                 self.name = name
503                 self.value = value
504                 return self
505
506 class HelpPage:
507     "A class to open a help page."
508     def getOpenFromAbsolute( self, hypertextAddress ):
509         return self
510
511 class MenuButtonDisplay:
512         "A class to add a combo box selection."
513         def getFromName( self, name, repository ):
514                 #print('MenuButtonDisplay->getFromName:', name, repository )
515                 self.name = name
516                 self.value = "ERROR"
517                 self.radioList = []
518                 repository.preferences.append(self)
519                 return self
520         
521         def addRadio(self, radio, default):
522                 if default:
523                         self.value = radio.name
524                 self.radioList.append(radio)
525         
526         def setValueToString(self, value):
527                 valueFound = False
528                 for radio in self.radioList:
529                         if radio.name == value:
530                                 valueFound = True;
531                 if valueFound:
532                         self.value = value
533                         for radio in self.radioList:
534                                 radio.value = (radio.name == value)
535
536 class MenuRadio( BooleanSetting ):
537         "A class to display, read & write a boolean with associated combo box selection."
538         def getFromMenuButtonDisplay( self, menuButtonDisplay, name, repository, value ):
539                 "Initialize."
540                 #print('MenuRadio->getFromMenuButtonDisplay:', menuButtonDisplay, name, repository, value )
541                 self.name = name
542                 self.value = value
543                 menuButtonDisplay.addRadio(self, value)
544                 return self
545
546 class LabelDisplay:
547         "A class to add a label."
548         def getFromName( self, name, repository ):
549                 "Initialize."
550                 return self
551
552 class FloatSetting(GeneralSetting):
553         "A class to display, read & write a float."
554         def setValueToString(self, value):
555                 self.value = float(value)
556
557 class FloatSpin( FloatSetting ):
558         "A class to display, read & write an float in a spin box."
559         def getFromValue(self, from_, name, repository, to, value):
560                 "Initialize."
561                 self.name = name
562                 self.value = value
563                 if repository != None:
564                         repository.preferences.append(self)
565                 return self
566
567 class LabelSeparator:
568         "A class to add a label and menu separator."
569         def getFromRepository( self, repository ):
570                 "Initialize."
571                 return self
572
573 class IntSpin(FloatSpin):
574         "A class to display, read & write an int in a spin box."
575         def getSingleIncrementFromValue( self, from_, name, repository, to, value ):
576                 "Initialize."
577                 self.name = name
578                 self.value = value
579                 repository.preferences.append(self)
580                 return self
581
582         def setValueToString(self, value):
583                 self.value = int(value)
584
585 ##########################
586 # Helper classes
587 ##########################
588
589 class LayerCount:
590         'A class to handle the layerIndex.'
591         def __init__(self):
592                 'Initialize.'
593                 self.layerIndex = -1
594
595         def __repr__(self):
596                 'Get the string representation of this LayerCount.'
597                 return str(self.layerIndex)
598
599         def printProgressIncrement(self, procedureName):
600                 'Print progress then increment layerIndex.'
601                 self.layerIndex += 1
602                 printProgress(self.layerIndex, procedureName)
603