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