ComboBox.qml 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. // Copyright (c) 2022 Ultimaker B.V.
  2. // Cura is released under the terms of the LGPLv3 or higher.
  3. import QtQuick 2.10
  4. import QtQuick.Controls 2.3
  5. import UM 1.5 as UM
  6. import Cura 1.1 as Cura
  7. //
  8. // ComboBox with Cura styling.
  9. //
  10. ComboBox
  11. {
  12. id: control
  13. property var defaultTextOnEmptyModel: catalog.i18nc("@label", "No items to select from") // Text displayed in the combobox when the model is empty
  14. property var defaultTextOnEmptyIndex: "" // Text displayed in the combobox when the model has items but no item is selected
  15. property alias textFormat: contentLabel.textFormat
  16. property alias backgroundColor: background.color
  17. property bool forceHighlight: false
  18. property int contentLeftPadding: UM.Theme.getSize("setting_unit_margin").width
  19. property var textFont: UM.Theme.getFont("default")
  20. enabled: delegateModel.count > 0
  21. height: UM.Theme.getSize("combobox").height
  22. onVisibleChanged: { popup.close() }
  23. states: [
  24. State
  25. {
  26. name: "disabled"
  27. when: !control.enabled
  28. PropertyChanges { target: background; color: UM.Theme.getColor("setting_control_disabled")}
  29. PropertyChanges { target: contentLabel; color: UM.Theme.getColor("setting_control_disabled_text")}
  30. },
  31. State
  32. {
  33. name: "active"
  34. when: control.activeFocus
  35. PropertyChanges
  36. {
  37. target: background
  38. borderColor: UM.Theme.getColor("text_field_border_active")
  39. liningColor: UM.Theme.getColor("text_field_border_active")
  40. }
  41. },
  42. State
  43. {
  44. name: "highlighted"
  45. when: (control.hovered && !control.activeFocus) || forceHighlight
  46. PropertyChanges
  47. {
  48. target: background
  49. liningColor: UM.Theme.getColor("text_field_border_hovered")
  50. }
  51. }
  52. ]
  53. background: UM.UnderlineBackground
  54. {
  55. id: background
  56. // Rectangle for highlighting when this combobox needs to pulse.
  57. Rectangle
  58. {
  59. anchors.fill: parent
  60. opacity: 0
  61. color: "transparent"
  62. border.color: UM.Theme.getColor("text_field_border_active")
  63. border.width: UM.Theme.getSize("default_lining").width
  64. SequentialAnimation on opacity
  65. {
  66. id: pulseAnimation
  67. running: false
  68. loops: 2
  69. PropertyAnimation
  70. {
  71. to: 1
  72. duration: 150
  73. }
  74. PropertyAnimation
  75. {
  76. to: 0
  77. duration : 150
  78. }
  79. }
  80. }
  81. }
  82. indicator: UM.ColorImage
  83. {
  84. id: downArrow
  85. x: control.width - width - control.rightPadding
  86. y: control.topPadding + Math.round((control.availableHeight - height) / 2)
  87. source: UM.Theme.getIcon("ChevronSingleDown")
  88. width: UM.Theme.getSize("standard_arrow").width
  89. height: UM.Theme.getSize("standard_arrow").height
  90. color: UM.Theme.getColor("setting_control_button")
  91. }
  92. contentItem: UM.Label
  93. {
  94. id: contentLabel
  95. leftPadding: contentLeftPadding + UM.Theme.getSize("default_margin").width
  96. anchors.right: downArrow.left
  97. wrapMode: Text.NoWrap
  98. font: textFont
  99. text:
  100. {
  101. if (control.delegateModel.count == 0)
  102. {
  103. return control.defaultTextOnEmptyModel != "" ? control.defaultTextOnEmptyModel : control.defaultTextOnEmptyIndex
  104. }
  105. else
  106. {
  107. return control.currentIndex == -1 ? control.defaultTextOnEmptyIndex : control.currentText
  108. }
  109. }
  110. textFormat: Text.PlainText
  111. color: control.currentIndex == -1 ? UM.Theme.getColor("setting_control_disabled_text") : UM.Theme.getColor("setting_control_text")
  112. elide: Text.ElideRight
  113. }
  114. popup: Popup
  115. {
  116. y: control.height - UM.Theme.getSize("default_lining").height
  117. width: control.width
  118. implicitHeight: contentItem.implicitHeight + 2 * UM.Theme.getSize("default_lining").width
  119. bottomMargin: UM.Theme.getSize("default_margin").height
  120. padding: UM.Theme.getSize("default_lining").width
  121. contentItem: ListView
  122. {
  123. implicitHeight: contentHeight
  124. ScrollBar.vertical: UM.ScrollBar {}
  125. clip: true
  126. model: control.popup.visible ? control.delegateModel : null
  127. currentIndex: control.highlightedIndex
  128. }
  129. background: Rectangle
  130. {
  131. color: UM.Theme.getColor("setting_control")
  132. border.color: UM.Theme.getColor("setting_control_border")
  133. }
  134. }
  135. delegate: ItemDelegate
  136. {
  137. id: delegateItem
  138. width: control.width - 2 * UM.Theme.getSize("default_lining").width
  139. height: control.height
  140. highlighted: control.highlightedIndex == index
  141. text:
  142. // FIXME: Maybe there is a better way to do this. Check model and modelData doc page:
  143. // https://doc.qt.io/qt-5/qtquick-modelviewsdata-modelview.html
  144. {
  145. var _val = undefined
  146. if (typeof _val === 'undefined') // try to get textRole from "model".
  147. {
  148. _val = model[textRole]
  149. }
  150. if (typeof _val === 'undefined') // try to get textRole from "modelData" if it's still undefined.
  151. {
  152. _val = modelData[textRole]
  153. }
  154. return (typeof _val !== 'undefined') ? _val : ""
  155. }
  156. contentItem: UM.Label
  157. {
  158. id: delegateLabel
  159. // FIXME: Somehow the top/bottom anchoring is not correct on Linux and it results in invisible texts.
  160. anchors.fill: parent
  161. anchors.leftMargin: contentLeftPadding
  162. anchors.rightMargin: UM.Theme.getSize("setting_unit_margin").width
  163. text: delegateItem.text
  164. textFormat: control.textFormat
  165. font: textFont
  166. color: UM.Theme.getColor("setting_control_text")
  167. elide: Text.ElideRight
  168. wrapMode: Text.NoWrap
  169. }
  170. background: UM.TooltipArea
  171. {
  172. Rectangle
  173. {
  174. color: delegateItem.highlighted ? UM.Theme.getColor("setting_control_highlight") : "transparent"
  175. anchors.fill: parent
  176. }
  177. text: delegateLabel.truncated ? delegateItem.text : ""
  178. }
  179. }
  180. function pulse()
  181. {
  182. pulseAnimation.restart();
  183. }
  184. }