SettingTextField.qml 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. // Copyright (c) 2021 Ultimaker B.V.
  2. // Cura is released under the terms of the LGPLv3 or higher.
  3. import QtQuick 2.15
  4. import QtQuick.Controls 2.15
  5. import UM 1.7 as UM
  6. SettingItem
  7. {
  8. id: base
  9. property var focusItem: input
  10. property string textBeforeEdit
  11. property bool textHasChanged
  12. property bool focusGainedByClick: false
  13. readonly property UM.IntValidator intValidator: UM.IntValidator {}
  14. readonly property UM.FloatValidator floatValidator: UM.FloatValidator {}
  15. readonly property UM.IntListValidator intListValidator: UM.IntListValidator {}
  16. onFocusReceived:
  17. {
  18. textHasChanged = false;
  19. textBeforeEdit = focusItem.text;
  20. if(!focusGainedByClick)
  21. {
  22. // select all text when tabbing through fields (but not when selecting a field with the mouse)
  23. focusItem.selectAll();
  24. }
  25. }
  26. contents: UM.UnderlineBackground
  27. {
  28. id: control
  29. anchors.fill: parent
  30. borderColor: input.activeFocus ? UM.Theme.getColor("text_field_border_active") : "transparent"
  31. liningColor:
  32. {
  33. if(!enabled)
  34. {
  35. return UM.Theme.getColor("text_field_border_disabled");
  36. }
  37. switch(propertyProvider.properties.validationState)
  38. {
  39. case "ValidatorState.Invalid":
  40. case "ValidatorState.Exception":
  41. case "ValidatorState.MinimumError":
  42. case "ValidatorState.MaximumError":
  43. return UM.Theme.getColor("setting_validation_error");
  44. case "ValidatorState.MinimumWarning":
  45. case "ValidatorState.MaximumWarning":
  46. return UM.Theme.getColor("setting_validation_warning");
  47. }
  48. //Validation is OK.
  49. if(input.activeFocus)
  50. {
  51. return UM.Theme.getColor("text_field_border_active");
  52. }
  53. if(hovered)
  54. {
  55. return UM.Theme.getColor("text_field_border_hovered");
  56. }
  57. return UM.Theme.getColor("text_field_border");
  58. }
  59. color: {
  60. if(!enabled)
  61. {
  62. return UM.Theme.getColor("setting_control_disabled")
  63. }
  64. switch(propertyProvider.properties.validationState)
  65. {
  66. case "ValidatorState.Invalid":
  67. case "ValidatorState.Exception":
  68. case "ValidatorState.MinimumError":
  69. case "ValidatorState.MaximumError":
  70. return UM.Theme.getColor("setting_validation_error_background")
  71. case "ValidatorState.MinimumWarning":
  72. case "ValidatorState.MaximumWarning":
  73. return UM.Theme.getColor("setting_validation_warning_background")
  74. case "ValidatorState.Valid":
  75. return UM.Theme.getColor("setting_validation_ok")
  76. default:
  77. return UM.Theme.getColor("text_field")
  78. }
  79. }
  80. UM.Label
  81. {
  82. anchors
  83. {
  84. left: parent.left
  85. leftMargin: Math.round(UM.Theme.getSize("setting_unit_margin").width)
  86. right: parent.right
  87. rightMargin: Math.round(UM.Theme.getSize("setting_unit_margin").width)
  88. verticalCenter: parent.verticalCenter
  89. }
  90. text: definition.unit
  91. //However the setting value is aligned, align the unit opposite. That way it stays readable with right-to-left languages.
  92. horizontalAlignment: (input.effectiveHorizontalAlignment == Text.AlignLeft) ? Text.AlignRight : Text.AlignLeft
  93. textFormat: Text.PlainText
  94. color: UM.Theme.getColor("setting_unit")
  95. }
  96. TextInput
  97. {
  98. id: input
  99. anchors
  100. {
  101. left: parent.left
  102. leftMargin: Math.round(UM.Theme.getSize("setting_unit_margin").width)
  103. right: parent.right
  104. rightMargin: Math.round(UM.Theme.getSize("setting_unit_margin").width)
  105. verticalCenter: parent.verticalCenter
  106. }
  107. renderType: Text.NativeRendering
  108. Keys.onTabPressed:
  109. {
  110. base.setActiveFocusToNextSetting(true)
  111. }
  112. Keys.onBacktabPressed:
  113. {
  114. base.setActiveFocusToNextSetting(false)
  115. }
  116. Keys.onReleased:
  117. {
  118. if (text != textBeforeEdit)
  119. {
  120. textHasChanged = true;
  121. }
  122. if (textHasChanged)
  123. {
  124. propertyProvider.setPropertyValue("value", text)
  125. }
  126. }
  127. onActiveFocusChanged:
  128. {
  129. if(activeFocus)
  130. {
  131. base.focusReceived();
  132. }
  133. base.focusGainedByClick = false;
  134. }
  135. color: !enabled ? UM.Theme.getColor("setting_control_disabled_text") : UM.Theme.getColor("setting_control_text")
  136. selectedTextColor: UM.Theme.getColor("setting_control_text")
  137. font: UM.Theme.getFont("default")
  138. selectionColor: UM.Theme.getColor("text_selection")
  139. selectByMouse: true
  140. maximumLength: (definition.type == "str" || definition.type == "[int]") ? -1 : 12
  141. // Since [int] & str don't have a max length, they need to be clipped (since clipping is expensive, this
  142. // should be done as little as possible)
  143. clip: definition.type == "str" || definition.type == "[int]"
  144. validator: RegularExpressionValidator
  145. {
  146. regularExpression:
  147. {
  148. switch (definition.type)
  149. {
  150. case "[int]":
  151. return new RegExp(intListValidator.regexString)
  152. case "int":
  153. return new RegExp(intValidator.regexString)
  154. case "float":
  155. return new RegExp(floatValidator.regexString)
  156. default:
  157. return new RegExp("^.*$")
  158. }
  159. }
  160. }
  161. Binding
  162. {
  163. target: input
  164. property: "text"
  165. value:
  166. {
  167. if (input.activeFocus)
  168. {
  169. // In QT6 using "when: !activeFocus" causes the value to be null when activeFocus becomes True
  170. // Since we want the value to stay the same when giving focus to the TextInput this is being used
  171. // in place of "when: !activeFocus"
  172. return input.text
  173. }
  174. // Stacklevels
  175. // 0: user -> unsaved change
  176. // 1: quality changes -> saved change
  177. // 2: quality
  178. // 3: material -> user changed material in materialspage
  179. // 4: variant
  180. // 5: machine_changes
  181. // 6: machine
  182. if ((base.resolve != "None" && base.resolve) && (stackLevel != 0) && (stackLevel != 1))
  183. {
  184. // We have a resolve function. Indicates that the setting is not settable per extruder and that
  185. // we have to choose between the resolved value (default) and the global value
  186. // (if user has explicitly set this).
  187. return base.resolve
  188. }
  189. else {
  190. return propertyProvider.properties.value
  191. }
  192. }
  193. }
  194. MouseArea
  195. {
  196. id: mouseArea
  197. anchors.fill: parent
  198. cursorShape: Qt.IBeamCursor
  199. onPressed:(mouse)=> {
  200. if (!input.activeFocus)
  201. {
  202. base.focusGainedByClick = true
  203. input.forceActiveFocus()
  204. }
  205. mouse.accepted = false
  206. }
  207. }
  208. }
  209. }
  210. }