ConfigurationMenu.qml 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  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.extruderList[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. UM.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.ColorImage
  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. wrapMode: Text.NoWrap
  177. width: parent.width
  178. visible: !truncated
  179. }
  180. UM.Label
  181. {
  182. id: materialNameLabel
  183. text: model.material_name
  184. elide: Text.ElideRight
  185. width: parent.width
  186. wrapMode: Text.NoWrap
  187. visible: !materialBrandNameLabel.visible && !truncated
  188. }
  189. UM.Label
  190. {
  191. id: materialTypeLabel
  192. text: model.material_type
  193. elide: Text.ElideRight
  194. width: parent.width
  195. wrapMode: Text.NoWrap
  196. visible: !materialBrandNameLabel.visible && !materialNameLabel.visible
  197. }
  198. // Label that shows the name of the variant
  199. UM.Label
  200. {
  201. id: variantLabel
  202. visible: activeMachine ? activeMachine.hasVariants : false
  203. text: model.variant
  204. elide: Text.ElideRight
  205. wrapMode: Text.NoWrap
  206. font: UM.Theme.getFont("default_bold")
  207. Layout.preferredWidth: parent.width
  208. }
  209. }
  210. }
  211. }
  212. }
  213. // Placeholder text if there is a configuration to select but no materials (so we can't show the materials per extruder).
  214. UM.Label
  215. {
  216. text: catalog.i18nc("@label", "Select configuration")
  217. elide: Text.ElideRight
  218. font: UM.Theme.getFont("medium")
  219. visible: activeMachine ? !activeMachine.hasMaterials && (activeMachine.hasVariants || activeMachine.hasVariantBuildplates) : false
  220. anchors
  221. {
  222. left: parent.left
  223. leftMargin: UM.Theme.getSize("default_margin").width
  224. verticalCenter: parent.verticalCenter
  225. }
  226. }
  227. }
  228. contentWidth: UM.Theme.getSize("configuration_selector").width
  229. contentItem: Column
  230. {
  231. id: popupItem
  232. padding: UM.Theme.getSize("default_margin").height
  233. spacing: UM.Theme.getSize("default_margin").height
  234. property bool is_connected: false // If current machine is connected to a printer. Only evaluated upon making popup visible.
  235. property int configuration_method: ConfigurationMenu.ConfigurationMethod.Custom // Type of configuration being used. Only evaluated upon making popup visible.
  236. property int manual_selected_method: -1 // It stores the configuration method selected by the user. By default the selected method is
  237. onVisibleChanged:
  238. {
  239. is_connected = activeMachine.hasRemoteConnection && Cura.MachineManager.printerConnected && Cura.MachineManager.printerOutputDevices[0].uniqueConfigurations.length > 0 //Re-evaluate.
  240. // 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
  241. // or the previous state is selected
  242. configuration_method = is_connected ? (manual_selected_method == -1 ? ConfigurationMenu.ConfigurationMethod.Auto : manual_selected_method) : ConfigurationMenu.ConfigurationMethod.Custom
  243. }
  244. Item
  245. {
  246. width: parent.width - 2 * parent.padding
  247. height:
  248. {
  249. var height = 0
  250. if (autoConfiguration.visible)
  251. {
  252. height += autoConfiguration.height
  253. }
  254. if (customConfiguration.visible)
  255. {
  256. height += customConfiguration.height
  257. }
  258. return height
  259. }
  260. AutoConfiguration
  261. {
  262. id: autoConfiguration
  263. visible: popupItem.configuration_method == ConfigurationMenu.ConfigurationMethod.Auto
  264. }
  265. CustomConfiguration
  266. {
  267. id: customConfiguration
  268. visible: popupItem.configuration_method == ConfigurationMenu.ConfigurationMethod.Custom
  269. }
  270. }
  271. Rectangle
  272. {
  273. id: separator
  274. visible: buttonBar.visible
  275. x: -parent.padding
  276. width: parent.width
  277. height: UM.Theme.getSize("default_lining").height
  278. color: UM.Theme.getColor("lining")
  279. }
  280. //Allow switching between custom and auto.
  281. Item
  282. {
  283. id: buttonBar
  284. visible: popupItem.is_connected //Switching only makes sense if the "auto" part is possible.
  285. width: parent.width - 2 * parent.padding
  286. height: childrenRect.height
  287. Cura.SecondaryButton
  288. {
  289. id: goToCustom
  290. visible: popupItem.configuration_method == ConfigurationMenu.ConfigurationMethod.Auto
  291. text: catalog.i18nc("@label", "Custom")
  292. anchors.right: parent.right
  293. iconSource: UM.Theme.getIcon("ChevronSingleRight")
  294. isIconOnRightSide: true
  295. onClicked:
  296. {
  297. popupItem.configuration_method = ConfigurationMenu.ConfigurationMethod.Custom
  298. popupItem.manual_selected_method = popupItem.configuration_method
  299. }
  300. }
  301. Cura.SecondaryButton
  302. {
  303. id: goToAuto
  304. visible: popupItem.configuration_method == ConfigurationMenu.ConfigurationMethod.Custom
  305. text: catalog.i18nc("@label", "Configurations")
  306. iconSource: UM.Theme.getIcon("ChevronSingleLeft")
  307. onClicked:
  308. {
  309. popupItem.configuration_method = ConfigurationMenu.ConfigurationMethod.Auto
  310. popupItem.manual_selected_method = popupItem.configuration_method
  311. }
  312. }
  313. }
  314. }
  315. Connections
  316. {
  317. target: Cura.MachineManager
  318. function onGlobalContainerChanged() { popupItem.manual_selected_method = -1 } // When switching printers, reset the value of the manual selected method
  319. }
  320. }