3 These are the validators for various profile settings, each validator can be attached to a setting.
4 The validators can be queried to see if the setting is valid.
5 There are 3 possible outcomes:
6 Valid - No problems found
7 Warning - The value is valid, but not recommended
8 Error - The value is not a proper number, out of range, or some other way wrong.
10 from __future__ import division
11 __copyright__ = "Copyright (C) 2013 David Braam - Released under terms of the AGPLv3 License"
20 class validFloat(object):
22 Checks if the given value in the setting is a valid float. An invalid float is an error condition.
23 And supports a minimum and/or maximum value. The min/max values are error conditions.
24 If the value == min or max then this is also an error.
26 def __init__(self, setting, minValue = None, maxValue = None):
27 self.setting = setting
28 self.setting._validators.append(self)
29 self.minValue = minValue
30 self.maxValue = maxValue
34 f = float(eval(self.setting.getValue().replace(',','.'), {}, {}))
35 if self.minValue is not None and f < self.minValue:
36 return ERROR, 'This setting should not be below ' + str(round(self.minValue, 3))
37 if self.maxValue is not None and f > self.maxValue:
38 return ERROR, 'This setting should not be above ' + str(self.maxValue)
40 except (ValueError, SyntaxError, TypeError, NameError):
41 return ERROR, '"' + str(self.setting.getValue()) + '" is not a valid number or expression'
43 class validInt(object):
45 Checks if the given value in the setting is a valid integer. An invalid integer is an error condition.
46 And supports a minimum and/or maximum value. The min/max values are error conditions.
47 If the value == min or max then this is also an error.
49 def __init__(self, setting, minValue = None, maxValue = None):
50 self.setting = setting
51 self.setting._validators.append(self)
52 self.minValue = minValue
53 self.maxValue = maxValue
57 f = int(eval(self.setting.getValue(), {}, {}))
58 if self.minValue is not None and f < self.minValue:
59 return ERROR, 'This setting should not be below ' + str(self.minValue)
60 if self.maxValue is not None and f > self.maxValue:
61 return ERROR, 'This setting should not be above ' + str(self.maxValue)
63 except (ValueError, SyntaxError, TypeError, NameError):
64 return ERROR, '"' + str(self.setting.getValue()) + '" is not a valid whole number or expression'
66 class warningAbove(object):
68 A validator to give off a warning if a value is equal or above a certain value.
70 def __init__(self, setting, minValueForWarning, warningMessage):
71 self.setting = setting
72 self.setting._validators.append(self)
73 self.minValueForWarning = minValueForWarning
74 self.warningMessage = warningMessage
78 f = float(eval(self.setting.getValue().replace(',','.'), {}, {}))
79 if isinstance(self.minValueForWarning, types.FunctionType):
80 if f >= self.minValueForWarning():
81 return WARNING, self.warningMessage % (self.minValueForWarning())
83 if f >= self.minValueForWarning:
84 return WARNING, self.warningMessage
86 except (ValueError, SyntaxError, TypeError):
87 #We already have an error by the int/float validator in this case.
90 class warningBelow(object):
92 A validator to give off a warning if a value is equal or below a certain value.
94 def __init__(self, setting, minValueForWarning, warningMessage):
95 self.setting = setting
96 self.setting._validators.append(self)
97 self.minValueForWarning = minValueForWarning
98 self.warningMessage = warningMessage
102 f = float(eval(self.setting.getValue().replace(',','.'), {}, {}))
103 if isinstance(self.minValueForWarning, types.FunctionType):
104 if f <= self.minValueForWarning():
105 return WARNING, self.warningMessage % (self.minValueForWarning())
107 if f <= self.minValueForWarning:
108 return WARNING, self.warningMessage
110 except (ValueError, SyntaxError, TypeError):
111 #We already have an error by the int/float validator in this case.
114 class wallThicknessValidator(object):
116 Special wall-thickness validator. The wall thickness is used to calculate the amount of shells and the thickness of the shells.
117 But, on certain conditions the resulting wall-thickness is not really suitable for printing. The range in which this can happen is small.
118 But better warn for it.
120 def __init__(self, setting):
121 self.setting = setting
122 self.setting._validators.append(self)
125 from Cura.util import profile
127 wallThickness = profile.getProfileSettingFloat('wall_thickness')
128 nozzleSize = profile.getProfileSettingFloat('nozzle_size')
129 if wallThickness < 0.01:
131 if wallThickness <= nozzleSize * 0.5:
132 return ERROR, 'Trying to print walls thinner then the half of your nozzle size, this will not produce anything usable'
133 if wallThickness <= nozzleSize * 0.85:
134 return WARNING, 'Trying to print walls thinner then the 0.8 * nozzle size. Small chance that this will produce usable results'
135 if wallThickness < nozzleSize:
138 return ERROR, 'Incorrect nozzle size'
140 lineCount = int(wallThickness / nozzleSize)
141 lineWidth = wallThickness / lineCount
142 lineWidthAlt = wallThickness / (lineCount + 1)
143 if lineWidth >= nozzleSize * 1.5 and lineWidthAlt <= nozzleSize * 0.85:
144 return WARNING, 'Current selected shell thickness results in a line thickness of ' + str(lineWidthAlt) + 'mm which is not recommended with your nozzle of ' + str(nozzleSize) + 'mm'
145 if abs((lineCount * nozzleSize) - wallThickness) > 0.01 and abs(((lineCount + 1) * nozzleSize) - wallThickness) > 0.01:
146 return WARNING, 'Currently selected shell thickness is not a multiple of the nozzle size. While this prints fine, it does not give optimal results.'
149 #We already have an error by the int/float validator in this case.
152 class printSpeedValidator(object):
154 Validate the printing speed by checking for a certain amount of volume per second.
155 This is based on the fact that you can push 10mm3 per second trough an UM-Origonal nozzle.
156 TODO: Update this code so it works better for different machine times with other feeders.
158 def __init__(self, setting):
159 self.setting = setting
160 self.setting._validators.append(self)
163 from Cura.util import profile
165 nozzleSize = profile.getProfileSettingFloat('nozzle_size')
166 layerHeight = profile.getProfileSettingFloat('layer_height')
167 raw_user_input = self.setting.getValue()
168 new_print_speed = raw_user_input.replace(',', '.')
170 evaluated = eval(new_print_speed, {}, {}) #Converts unicode into numeric
171 except SyntaxError: #Caused by unicode string being empty
173 printSpeed = float(evaluated)
174 if printSpeed == 0.0:
175 printSpeed = profile.getProfileSettingFloat('print_speed')
177 printVolumePerMM = layerHeight * nozzleSize
178 printVolumePerSecond = printVolumePerMM * printSpeed
179 #Using 8mm3 per second with a 0.4mm nozzle
180 maxPrintVolumePerSecond = 8 / (math.pi*(0.2*0.2)) * (math.pi*(nozzleSize/2*nozzleSize/2))
182 if printVolumePerSecond > maxPrintVolumePerSecond:
183 return WARNING, 'You are trying to print more then %.1fmm^3 of filament per second. This might cause filament slipping. (You are printing at %0.1fmm^3 per second)' % (maxPrintVolumePerSecond, printVolumePerSecond)
185 return SUCCESS, 'You are printing at %0.1fmm^3 per second' % (printVolumePerSecond)
187 #We already have an error by the int/float validator in this case.