ComboBox.qml 6.3 KB

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