ConfigurationMenu.qml 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. // Copyright (c) 2018 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 QtQuick.Layouts 1.3
  6. import UM 1.5 as UM
  7. import Cura 1.0 as Cura
  8. /**
  9. * Menu that allows you to select the configuration of the current printer, such
  10. * as the nozzle sizes and materials in each extruder.
  11. */
  12. Cura.ExpandablePopup
  13. {
  14. id: base
  15. property var extrudersModel: CuraApplication.getExtrudersModel()
  16. property var activeMachine: Cura.MachineManager.activeMachine
  17. UM.I18nCatalog
  18. {
  19. id: catalog
  20. name: "cura"
  21. }
  22. enum ConfigurationMethod
  23. {
  24. Auto,
  25. Custom
  26. }
  27. contentPadding: UM.Theme.getSize("default_lining").width
  28. enabled: activeMachine ? activeMachine.hasMaterials || activeMachine.hasVariants || activeMachine.hasVariantBuildplates : false; //Only let it drop down if there is any configuration that you could change.
  29. headerItem: Item
  30. {
  31. // Horizontal list that shows the extruders and their materials
  32. RowLayout
  33. {
  34. anchors.top: parent.top
  35. anchors.bottom: parent.bottom
  36. anchors.left: parent.left
  37. width: parent.width - UM.Theme.getSize("standard_arrow").width
  38. visible: activeMachine ? activeMachine.hasMaterials : false
  39. Repeater
  40. {
  41. model: extrudersModel
  42. delegate: Item
  43. {
  44. id: extruderItem
  45. Layout.preferredWidth: Math.round(parent.width / extrudersModel.count)
  46. Layout.maximumWidth: Math.round(parent.width / extrudersModel.count)
  47. Layout.fillHeight: true
  48. property var extruderStack: activeMachine ? activeMachine.extruders[model.index]: null
  49. property bool valueWarning: !Cura.ExtruderManager.getExtruderHasQualityForMaterial(extruderStack)
  50. property bool valueError: activeMachine ? Cura.ContainerManager.getContainerMetaDataEntry(extruderStack.material.id, "compatible", "") != "True" : false
  51. // Extruder icon. Shows extruder index and has the same color as the active material.
  52. Cura.ExtruderIcon
  53. {
  54. id: extruderIcon
  55. materialColor: model.color
  56. extruderEnabled: model.enabled
  57. anchors.verticalCenter: parent.verticalCenter
  58. }
  59. MouseArea // Connection status tooltip hover area
  60. {
  61. id: tooltipHoverArea
  62. anchors.fill: parent
  63. hoverEnabled: tooltip.text != ""
  64. acceptedButtons: Qt.NoButton // react to hover only, don't steal clicks
  65. onEntered:
  66. {
  67. base.mouseArea.entered() // we want both this and the outer area to be entered
  68. tooltip.show()
  69. }
  70. onExited: { tooltip.hide() }
  71. }
  72. Cura.ToolTip
  73. {
  74. id: tooltip
  75. x: 0
  76. y: parent.height + UM.Theme.getSize("default_margin").height
  77. width: UM.Theme.getSize("tooltip").width
  78. targetPoint: Qt.point(Math.round(extruderIcon.width / 2), 0)
  79. text:
  80. {
  81. if (!model.enabled)
  82. {
  83. return ""
  84. }
  85. if (extruderItem.valueError)
  86. {
  87. return catalog.i18nc("@tooltip", "The configuration of this extruder is not allowed, and prohibits slicing.")
  88. }
  89. if (extruderItem.valueWarning)
  90. {
  91. return catalog.i18nc("@tooltip", "There are no profiles matching the configuration of this extruder.")
  92. }
  93. return ""
  94. }
  95. }
  96. // Warning icon that indicates if no qualities are available for the variant/material combination for this extruder
  97. UM.RecolorImage
  98. {
  99. id: badge
  100. anchors
  101. {
  102. top: parent.top
  103. topMargin: - Math.round(height * 1 / 6)
  104. left: parent.left
  105. leftMargin: extruderIcon.width - Math.round(width * 5 / 6)
  106. }
  107. width: UM.Theme.getSize("icon_indicator").width
  108. height: UM.Theme.getSize("icon_indicator").height
  109. visible: model.enabled && (extruderItem.valueError || extruderItem.valueWarning)
  110. source:
  111. {
  112. if (extruderItem.valueError)
  113. {
  114. return UM.Theme.getIcon("ErrorBadge", "low")
  115. }
  116. if (extruderItem.valueWarning)
  117. {
  118. return UM.Theme.getIcon("WarningBadge", "low")
  119. }
  120. return ""
  121. }
  122. color:
  123. {
  124. if (extruderItem.valueError)
  125. {
  126. return UM.Theme.getColor("error")
  127. }
  128. if (extruderItem.valueWarning)
  129. {
  130. return UM.Theme.getColor("warning")
  131. }
  132. return "transparent"
  133. }
  134. // Make a themable circle in the background so we can change it in other themes
  135. Rectangle
  136. {
  137. id: iconBackground
  138. anchors.centerIn: parent
  139. width: parent.width - 1.5 //1.5 pixels smaller, (at least sqrt(2), regardless of screen pixel scale) so that the circle doesn't show up behind the icon due to anti-aliasing.
  140. height: parent.height - 1.5
  141. radius: width / 2
  142. z: parent.z - 1
  143. color:
  144. {
  145. if (extruderItem.valueError)
  146. {
  147. return UM.Theme.getColor("error_badge_background")
  148. }
  149. if (extruderItem.valueWarning)
  150. {
  151. return UM.Theme.getColor("warning_badge_background")
  152. }
  153. return "transparent"
  154. }
  155. }
  156. }
  157. Column
  158. {
  159. opacity: model.enabled ? 1 : UM.Theme.getColor("extruder_disabled").a
  160. spacing: 0
  161. visible: width > 0
  162. anchors
  163. {
  164. left: extruderIcon.right
  165. leftMargin: UM.Theme.getSize("default_margin").width
  166. verticalCenter: parent.verticalCenter
  167. right: parent.right
  168. rightMargin: UM.Theme.getSize("default_margin").width
  169. }
  170. // Label for the brand of the material
  171. UM.Label
  172. {
  173. id: materialBrandNameLabel
  174. text: model.material_brand + " " + model.material_name
  175. elide: Text.ElideRight
  176. width: parent.width
  177. visible: !truncated
  178. }
  179. UM.Label
  180. {
  181. id: materialNameLabel
  182. text: model.material_name
  183. elide: Text.ElideRight
  184. width: parent.width
  185. visible: !materialBrandNameLabel.visible && !truncated
  186. }
  187. UM.Label
  188. {
  189. id: materialTypeLabel
  190. text: model.material_type
  191. elide: Text.ElideRight
  192. width: parent.width
  193. visible: !materialBrandNameLabel.visible && !materialNameLabel.visible
  194. }
  195. // Label that shows the name of the variant
  196. UM.Label
  197. {
  198. id: variantLabel
  199. visible: activeMachine ? activeMachine.hasVariants : false
  200. text: model.variant
  201. elide: Text.ElideRight
  202. font: UM.Theme.getFont("default_bold")
  203. Layout.preferredWidth: parent.width
  204. }
  205. }
  206. }
  207. }
  208. }
  209. // Placeholder text if there is a configuration to select but no materials (so we can't show the materials per extruder).
  210. UM.Label
  211. {
  212. text: catalog.i18nc("@label", "Select configuration")
  213. elide: Text.ElideRight
  214. font: UM.Theme.getFont("medium")
  215. visible: activeMachine ? !activeMachine.hasMaterials && (activeMachine.hasVariants || activeMachine.hasVariantBuildplates) : false
  216. anchors
  217. {
  218. left: parent.left
  219. leftMargin: UM.Theme.getSize("default_margin").width
  220. verticalCenter: parent.verticalCenter
  221. }
  222. }
  223. }
  224. contentItem: Column
  225. {
  226. id: popupItem
  227. width: UM.Theme.getSize("configuration_selector").width
  228. height: implicitHeight // Required because ExpandableComponent will try to use this to determine the size of the background of the pop-up.
  229. padding: UM.Theme.getSize("default_margin").height
  230. spacing: UM.Theme.getSize("default_margin").height
  231. property bool is_connected: false // If current machine is connected to a printer. Only evaluated upon making popup visible.
  232. property int configuration_method: ConfigurationMenu.ConfigurationMethod.Custom // Type of configuration being used. Only evaluated upon making popup visible.
  233. property int manual_selected_method: -1 // It stores the configuration method selected by the user. By default the selected method is
  234. onVisibleChanged:
  235. {
  236. is_connected = activeMachine.hasRemoteConnection && Cura.MachineManager.printerConnected && Cura.MachineManager.printerOutputDevices[0].uniqueConfigurations.length > 0 //Re-evaluate.
  237. // If the printer is not connected or does not have configurations, we switch always to the custom mode. If is connected instead, the auto mode
  238. // or the previous state is selected
  239. configuration_method = is_connected ? (manual_selected_method == -1 ? ConfigurationMenu.ConfigurationMethod.Auto : manual_selected_method) : ConfigurationMenu.ConfigurationMethod.Custom
  240. }
  241. Item
  242. {
  243. width: parent.width - 2 * parent.padding
  244. height:
  245. {
  246. var height = 0
  247. if (autoConfiguration.visible)
  248. {
  249. height += autoConfiguration.height
  250. }
  251. if (customConfiguration.visible)
  252. {
  253. height += customConfiguration.height
  254. }
  255. return height
  256. }
  257. AutoConfiguration
  258. {
  259. id: autoConfiguration
  260. visible: popupItem.configuration_method == ConfigurationMenu.ConfigurationMethod.Auto
  261. }
  262. CustomConfiguration
  263. {
  264. id: customConfiguration
  265. visible: popupItem.configuration_method == ConfigurationMenu.ConfigurationMethod.Custom
  266. }
  267. }
  268. Rectangle
  269. {
  270. id: separator
  271. visible: buttonBar.visible
  272. x: -parent.padding
  273. width: parent.width
  274. height: UM.Theme.getSize("default_lining").height
  275. color: UM.Theme.getColor("lining")
  276. }
  277. //Allow switching between custom and auto.
  278. Item
  279. {
  280. id: buttonBar
  281. visible: popupItem.is_connected //Switching only makes sense if the "auto" part is possible.
  282. width: parent.width - 2 * parent.padding
  283. height: childrenRect.height
  284. Cura.SecondaryButton
  285. {
  286. id: goToCustom
  287. visible: popupItem.configuration_method == ConfigurationMenu.ConfigurationMethod.Auto
  288. text: catalog.i18nc("@label", "Custom")
  289. anchors.right: parent.right
  290. iconSource: UM.Theme.getIcon("ChevronSingleRight")
  291. isIconOnRightSide: true
  292. onClicked:
  293. {
  294. popupItem.configuration_method = ConfigurationMenu.ConfigurationMethod.Custom
  295. popupItem.manual_selected_method = popupItem.configuration_method
  296. }
  297. }
  298. Cura.SecondaryButton
  299. {
  300. id: goToAuto
  301. visible: popupItem.configuration_method == ConfigurationMenu.ConfigurationMethod.Custom
  302. text: catalog.i18nc("@label", "Configurations")
  303. iconSource: UM.Theme.getIcon("ChevronSingleLeft")
  304. onClicked:
  305. {
  306. popupItem.configuration_method = ConfigurationMenu.ConfigurationMethod.Auto
  307. popupItem.manual_selected_method = popupItem.configuration_method
  308. }
  309. }
  310. }
  311. }
  312. Connections
  313. {
  314. target: Cura.MachineManager
  315. function onGlobalContainerChanged() { popupItem.manual_selected_method = -1 } // When switching printers, reset the value of the manual selected method
  316. }
  317. }