chiark / gitweb /
Add option to have the center of the printer at 0,0 for RoStock printers. #310 #266
[cura.git] / Cura / slice / 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
9 import sys
10 import types
11 import math
12
13 from Cura.util import profile
14 from Cura.slice.cura_sf.fabmetheus_utilities import archive
15
16 def DEFSET(setting):
17         return setting.value
18
19 def storedSetting(name):
20         return lambda setting: profile.getProfileSetting(name)
21 def storedSettingFloat(name):
22         return lambda setting: profile.getProfileSettingFloat(name)
23 def storedSettingInt(name):
24         return lambda setting: int(profile.getProfileSettingFloat(name))
25 def storedPreference(name):
26         return lambda setting: profile.getPreference(name)
27 def storedPreferenceFloat(name):
28         return lambda setting: profile.getPreferenceFloat(name)
29 def storedSettingInvertBoolean(name):
30         return lambda setting: profile.getProfileSetting(name) == "False"
31
32 def ifSettingAboveZero(name):
33         return lambda setting: profile.getProfileSettingFloat(name) > 0
34
35 def ifSettingIs(name, value):
36         return lambda setting: profile.getProfileSetting(name) == value
37
38 def raftLayerCount(setting):
39         if profile.getProfileSetting('enable_raft') == "True":
40                 return '1'
41         return '0'
42
43 def storedPercentSetting(name):
44         return lambda setting: profile.getProfileSettingFloat(name) / 100
45
46 def calculateEdgeWidth(setting):
47         return profile.calculateEdgeWidth()
48
49 def calculateShells(setting):
50         return profile.calculateLineCount() - 1
51
52 def calculateShellsBase(setting):
53         edgeWidth = profile.calculateEdgeWidth()
54         extraWall = profile.getProfileSettingFloat('extra_base_wall_thickness')
55         
56         return profile.calculateLineCount() - 1 + int(extraWall / edgeWidth + 0.0001)
57
58 def calculateSolidLayerCount(setting):
59         return profile.calculateSolidLayerCount()
60
61 def firstLayerSpeedRatio(setting):
62         bottomSpeed = profile.getProfileSettingFloat('bottom_layer_speed')
63         speed = profile.getProfileSettingFloat('print_speed')
64         return bottomSpeed/speed
65
66 def calcSupportDistanceRatio(setting):
67         edgeWidth = calculateEdgeWidth(setting)
68         distance = profile.getProfileSettingFloat('support_distance')
69         return distance / edgeWidth
70
71 def calculateMultiplyDistance(setting):
72         edgeWidth = calculateEdgeWidth(setting)
73         return 10.0 / edgeWidth
74
75 def calcBottomLayerFlowRateRatio(setting):
76         bottomThickness = profile.getProfileSettingFloat('bottom_thickness')
77         layerThickness = profile.getProfileSettingFloat('layer_height')
78         if bottomThickness < layerThickness:
79                 return 1.0
80         return bottomThickness / layerThickness
81
82 def calcExtraBottomThickness(setting):
83         bottomThickness = profile.getProfileSettingFloat('bottom_thickness')
84         layerThickness = profile.getProfileSettingFloat('layer_height')
85         if bottomThickness < layerThickness:
86                 return 0.0
87         return bottomThickness - layerThickness
88
89 def calcLayerSkip(setting):
90         bottomThickness = profile.getProfileSettingFloat('bottom_thickness')
91         layerThickness = profile.getProfileSettingFloat('layer_height')
92         if bottomThickness < layerThickness:
93                 return 0
94         return int(math.ceil((bottomThickness - layerThickness) / layerThickness + 0.0001) - 1)
95
96 def getProfileInformation():
97         return {
98                 'carve': {
99                         'Add_Layer_Template_to_SVG': 'False',
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                         'ObjectMatrix': storedSetting("object_matrix"),
110                         'CenterX': lambda setting: profile.getProfileSettingFloat('object_center_x'),
111                         'CenterY': lambda setting: profile.getProfileSettingFloat('object_center_y'),
112                         'AlternativeCenterFile': storedSetting("alternative_center"),
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': "False",
126                         'Set_Units_to_Millimeters': "False",
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': ifSettingAboveZero('fill_density'),
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': "False",
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': "False",
172                         'Center_X_mm': lambda setting: profile.getProfileSettingFloat('object_center_x') if profile.getProfileSettingFloat('object_center_x') > 0 else profile.getPreferenceFloat("machine_width") / 2,
173                         'Center_Y_mm': lambda setting: profile.getProfileSettingFloat('object_center_y') if profile.getProfileSettingFloat('object_center_y') > 0 else profile.getPreferenceFloat("machine_depth") / 2,
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_speed'),
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': lambda setting: 'True' if profile.getProfileSetting('support_dual_extrusion') == 'True' and int(profile.getPreference('extruder_amount')) > 1 else '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                         'Support_Margin_mm': '3.0',
238                         'Support_Offset_X_mm': lambda setting: -profile.getPreferenceFloat('extruder_offset_x1') if profile.getProfileSetting('support_dual_extrusion') == 'True' and int(profile.getPreference('extruder_amount')) > 1 else '0',
239                         'Support_Offset_Y_mm': lambda setting: -profile.getPreferenceFloat('extruder_offset_y1') if profile.getProfileSetting('support_dual_extrusion') == 'True' and int(profile.getPreference('extruder_amount')) > 1 else '0',
240                 },'skirt': {
241                         'Skirt_line_count': storedSetting("skirt_line_count"),
242                         'Convex': lambda setting: "True" if profile.getProfileSettingFloat('skirt_gap') > 0.0 else "False",
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_min_%': storedSettingInt('fan_speed'),
305                         'Fan_speed_max_%': storedSettingInt('fan_speed_max'),
306                 },'hop': {
307                         'Activate_Hop': storedSetting('hop_on_move'),
308                         'Hop_Over_Layer_Thickness_ratio': lambda setting: 0.2 / profile.getProfileSettingFloat('layer_height'),
309                         'Minimum_Hop_Angle_degrees': DEFSET,
310                 },'wipe': {
311                         'Activate_Wipe': "False",
312                         'Arrival_X_mm': DEFSET,
313                         'Arrival_Y_mm': DEFSET,
314                         'Arrival_Z_mm': DEFSET,
315                         'Departure_X_mm': DEFSET,
316                         'Departure_Y_mm': DEFSET,
317                         'Departure_Z_mm': DEFSET,
318                         'Wipe_X_mm': DEFSET,
319                         'Wipe_Y_mm': DEFSET,
320                         'Wipe_Z_mm': DEFSET,
321                         'Wipe_Period_layers': DEFSET,
322                 },'oozebane': {
323                         'Activate_Oozebane': "False",
324                         'After_Startup_Distance_millimeters': DEFSET,
325                         'Early_Shutdown_Distance_millimeters': DEFSET,
326                         'Early_Startup_Distance_Constant_millimeters': DEFSET,
327                         'Early_Startup_Maximum_Distance_millimeters': DEFSET,
328                         'First_Early_Startup_Distance_millimeters': DEFSET,
329                         'Minimum_Distance_for_Early_Startup_millimeters': DEFSET,
330                         'Minimum_Distance_for_Early_Shutdown_millimeters': DEFSET,
331                         'Slowdown_Startup_Steps_positive_integer': DEFSET,
332                 },'dwindle': {
333                         'Activate_Dwindle': "False",
334                         'End_Rate_Multiplier_ratio': '0.5',
335                         'Pent_Up_Volume_cubic_millimeters': "0.4",
336                         'Slowdown_Steps_positive_integer': '5',
337                         'Slowdown_Volume_cubic_millimeters': "5.0",
338                 },'splodge': {
339                         'Activate_Splodge': "False",
340                         'Initial_Lift_over_Extra_Thickness_ratio': DEFSET,
341                         'Initial_Splodge_Feed_Rate_mm/s': DEFSET,
342                         'Operating_Splodge_Feed_Rate_mm/s': DEFSET,
343                         'Operating_Splodge_Quantity_Length_millimeters': DEFSET,
344                         'Initial_Splodge_Quantity_Length_millimeters': DEFSET,
345                         'Operating_Lift_over_Extra_Thickness_ratio': DEFSET,
346                 },'home': {
347                         'Activate_Home': "False",
348                         'Name_of_Home_File': DEFSET,
349                 },'lash': {
350                         'Activate_Lash': "False",
351                         'X_Backlash_mm': DEFSET,
352                         'Y_Backlash_mm': DEFSET,
353                 },'fillet': {
354                         'Activate_Fillet': "False",
355                         'Arc_Point': DEFSET,
356                         'Arc_Radius': DEFSET,
357                         'Arc_Segment': DEFSET,
358                         'Bevel': DEFSET,
359                         'Corner_Feed_Rate_Multiplier_ratio': DEFSET,
360                         'Fillet_Radius_over_Perimeter_Width_ratio': DEFSET,
361                         'Reversal_Slowdown_Distance_over_Perimeter_Width_ratio': DEFSET,
362                         'Use_Intermediate_Feed_Rate_in_Corners': DEFSET,
363                 },'limit': {
364                         'Activate_Limit': "False",
365                         'Maximum_Initial_Feed_Rate_mm/s': DEFSET,
366                 },'unpause': {
367                         'Activate_Unpause': "False",
368                         'Delay_milliseconds': DEFSET,
369                         'Maximum_Speed_ratio': DEFSET,
370                 },'dimension': {
371                         'Activate_Dimension': "True",
372                         'Absolute_Extrusion_Distance': "True",
373                         'Relative_Extrusion_Distance': "False",
374                         'Extruder_Retraction_Speed_mm/s': storedSettingFloat('retraction_speed'),
375                         'Filament_Diameter_mm': storedSettingFloat("filament_diameter"),
376                         'Filament_Packing_Density_ratio': storedSettingFloat("filament_density"),
377                         'Maximum_E_Value_before_Reset_float': DEFSET,
378                         'Minimum_Travel_for_Retraction_millimeters': storedSettingFloat("retraction_min_travel"),
379                         'Retract_Within_Island': storedSettingInvertBoolean("retract_on_jumps_only"),
380                         'Retraction_Distance_millimeters': lambda setting: profile.getProfileSettingFloat('retraction_amount') if profile.getProfileSetting('retraction_enable') == 'True' else 0,
381                         'Restart_Extra_Distance_millimeters': storedSettingFloat('retraction_extra'),
382                 },'alteration': {
383                         'Activate_Alteration': "False",
384                         'Name_of_End_File': "end.gcode",
385                         'Name_of_Start_File': "start.gcode",
386                         'Remove_Redundant_Mcode': "True",
387                         'Replace_Variable_with_Setting': DEFSET,
388                 },'export': {
389                         'Activate_Export': "True",
390                         'Add_Descriptive_Extension': DEFSET,
391                         'Add_Export_Suffix': "False",
392                         'Add_Profile_Extension': DEFSET,
393                         'Add_Timestamp_Extension': DEFSET,
394                         'Also_Send_Output_To': DEFSET,
395                         'Analyze_Gcode': DEFSET,
396                         'Comment_Choice': DEFSET,
397                         'Do_Not_Change_Output': DEFSET,
398                         'binary_16_byte': DEFSET,
399                         'gcode_step': DEFSET,
400                         'gcode_time_segment': DEFSET,
401                         'gcode_small': DEFSET,
402                         'File_Extension': storedSetting('gcode_extension'),
403                         'Name_of_Replace_File': DEFSET,
404                         'Save_Penultimate_Gcode': "False",
405                 }
406         }
407
408 def safeConfigName(name):
409         return name.replace("=", "").replace(":", "").replace(" ", "_").replace("(", "").replace(")", "")
410
411 def getReadRepository(repository):
412         "Read the configuration for this 'repository'"
413         
414         info = getProfileInformation()
415         if not info.has_key(repository.name):
416                 print("Warning: Plugin: " + repository.name + " missing from Cura info")
417                 return repository
418         info = info[repository.name]
419         
420         #print('getReadRepository:', repository.name)
421         for p in repository.preferences:
422                 name = safeConfigName(p.name)
423                 if not info.has_key(name):
424                         print("Setting: " + repository.name + ":" + name + " missing from Cura info")
425                         continue
426                 if isinstance(info[name], types.FunctionType):
427                         p.setValueToString(str(info[name](p)))
428                 else:
429                         p.setValueToString(str(info[name]))
430
431         return repository
432
433 def printProgress(layerIndex, procedureName):
434         print("Progress[" + procedureName + ":" + str(layerIndex+1) + "]")
435         sys.stdout.flush()
436
437 def printProgressByNumber(layerIndex, numberOfLayers, procedureName):
438         print("Progress[" + procedureName + ":" + str(layerIndex+1) + ":" + str(numberOfLayers) + "]")
439         sys.stdout.flush()
440
441 def getAlterationFileLines(fileName):
442         'Get the alteration file line and the text lines from the fileName in the alterations directories.'
443         return getAlterationLines(fileName)
444
445 def getAlterationLines(fileName):
446         return archive.getTextLines(getAlterationFile(fileName))
447
448 def getAlterationFile(fileName):
449         return profile.getAlterationFileContents(fileName)
450
451 ####################################
452 ## Configuration settings classes ##
453 ####################################
454
455 class GeneralSetting(object):
456         "Just a basic setting subclass"
457         def getFromValue( self, name, repository, value ):
458                 #print('GeneralSetting:', name, repository, value )
459                 self.name = name
460                 self.value = value
461                 repository.preferences.append(self)
462                 return self
463
464 class StringSetting(GeneralSetting):
465         "A class to display, read & write a string."
466         def setValueToString(self, value):
467                 self.value = value
468
469 class BooleanSetting( GeneralSetting ):
470         "A class to display, read & write a boolean."
471         def setValueToString(self, value):
472                 self.value = str(value) == "True"
473
474 class LatentStringVar(object):
475         "This is actually used as 'group' object for Radio buttons. (Did I mention the code is a mess?)"
476         "This class doesn't have a name, and isn't really used for anything. It doesn't even know which repository it belongs to"
477
478 class Radio( BooleanSetting ):
479         "A class to display, read & write a boolean with associated radio button."
480         def getFromRadio( self, latentStringVar, name, repository, value ):
481                 "Initialize."
482                 #print('Radio->getFromRadio:', latentStringVar, name, repository, value )
483                 self.name = name
484                 self.value = value
485                 repository.preferences.append(self)
486                 return self
487
488 class RadioCapitalized( Radio ):
489         "A class to display, read & write a boolean with associated radio button."
490
491 class RadioCapitalizedButton( Radio ):
492         "A class to display, read & write a boolean with associated radio button. With an added configuration dialog button"
493         "Only used for the extra export options, which we are not using, so ignore the path for now"
494         def getFromPath( self, latentStringVar, name, path, repository, value ):
495                 "Initialize."
496                 #print('RadioCapitalizedButton->getFromPath:', latentStringVar, name, path, repository, value )
497                 self.name = name
498                 self.value = value
499                 repository.preferences.append(self)
500                 return self
501                 
502 class FileNameInput(StringSetting):
503         "A class to display, read & write a fileName."
504         def getFromFileName( self, fileTypes, name, repository, value ):
505                 #print('FileNameInput:getFromFileName:', self, fileTypes, name, repository, value )
506                 self.name = name
507                 self.value = value
508                 return self
509
510 class HelpPage(object):
511         "A class to open a help page."
512         def getOpenFromAbsolute( self, hypertextAddress ):
513                 return self
514
515 class MenuButtonDisplay(object):
516         "A class to add a combo box selection."
517         def getFromName( self, name, repository ):
518                 #print('MenuButtonDisplay->getFromName:', name, repository )
519                 self.name = name
520                 self.value = "ERROR"
521                 self.radioList = []
522                 repository.preferences.append(self)
523                 return self
524         
525         def addRadio(self, radio, default):
526                 if default:
527                         self.value = radio.name
528                 self.radioList.append(radio)
529         
530         def setValueToString(self, value):
531                 valueFound = False
532                 for radio in self.radioList:
533                         if radio.name == value:
534                                 valueFound = True
535                 if valueFound:
536                         self.value = value
537                         for radio in self.radioList:
538                                 radio.value = (radio.name == value)
539
540 class MenuRadio( BooleanSetting ):
541         "A class to display, read & write a boolean with associated combo box selection."
542         def getFromMenuButtonDisplay( self, menuButtonDisplay, name, repository, value ):
543                 "Initialize."
544                 #print('MenuRadio->getFromMenuButtonDisplay:', menuButtonDisplay, name, repository, value )
545                 self.name = name
546                 self.value = value
547                 menuButtonDisplay.addRadio(self, value)
548                 return self
549
550 class LabelDisplay(object):
551         "A class to add a label."
552         def getFromName( self, name, repository ):
553                 "Initialize."
554                 return self
555
556 class FloatSetting(GeneralSetting):
557         "A class to display, read & write a float."
558         def setValueToString(self, value):
559                 self.value = float(value)
560
561 class FloatSpin( FloatSetting ):
562         "A class to display, read & write an float in a spin box."
563         def getFromValue(self, from_, name, repository, to, value):
564                 "Initialize."
565                 self.name = name
566                 self.value = value
567                 if repository != None:
568                         repository.preferences.append(self)
569                 return self
570
571 class LabelSeparator(object):
572         "A class to add a label and menu separator."
573         def getFromRepository( self, repository ):
574                 "Initialize."
575                 return self
576
577 class IntSpin(FloatSpin):
578         "A class to display, read & write an int in a spin box."
579         def getSingleIncrementFromValue( self, from_, name, repository, to, value ):
580                 "Initialize."
581                 self.name = name
582                 self.value = value
583                 repository.preferences.append(self)
584                 return self
585
586         def setValueToString(self, value):
587                 self.value = int(value)
588
589 ##########################
590 # Helper classes
591 ##########################
592
593 class LayerCount(object):
594         'A class to handle the layerIndex.'
595         def __init__(self):
596                 'Initialize.'
597                 self.layerIndex = -1
598
599         def __repr__(self):
600                 'Get the string representation of this LayerCount.'
601                 return str(self.layerIndex)
602
603         def printProgressIncrement(self, procedureName):
604                 'Print progress then increment layerIndex.'
605                 self.layerIndex += 1
606                 printProgress(self.layerIndex, procedureName)
607