SettingView.qml 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  1. // Copyright (c) 2015 Ultimaker B.V.
  2. // Uranium is released under the terms of the AGPLv3 or higher.
  3. import QtQuick 2.2
  4. import QtQuick.Controls 1.1
  5. import QtQuick.Controls.Styles 1.1
  6. import QtQuick.Layouts 1.1
  7. import UM 1.2 as UM
  8. import Cura 1.0 as Cura
  9. Item
  10. {
  11. id: base;
  12. property Action configureSettings;
  13. property bool findingSettings;
  14. signal showTooltip(Item item, point location, string text);
  15. signal hideTooltip();
  16. function toggleFilterField()
  17. {
  18. filterContainer.visible = !filterContainer.visible
  19. if(filterContainer.visible)
  20. {
  21. filter.forceActiveFocus();
  22. }
  23. else
  24. {
  25. filter.text = "";
  26. }
  27. }
  28. Rectangle
  29. {
  30. id: filterContainer
  31. visible: false
  32. border.width: UM.Theme.getSize("default_lining").width
  33. border.color:
  34. {
  35. if(hoverMouseArea.containsMouse || clearFilterButton.containsMouse)
  36. {
  37. return UM.Theme.getColor("setting_control_border_highlight");
  38. }
  39. else
  40. {
  41. return UM.Theme.getColor("setting_control_border");
  42. }
  43. }
  44. color: UM.Theme.getColor("setting_control")
  45. anchors
  46. {
  47. top: parent.top
  48. left: parent.left
  49. leftMargin: UM.Theme.getSize("default_margin").width
  50. right: parent.right
  51. rightMargin: UM.Theme.getSize("default_margin").width
  52. }
  53. height: visible ? UM.Theme.getSize("setting_control").height : 0
  54. Behavior on height { NumberAnimation { duration: 100 } }
  55. TextField
  56. {
  57. id: filter;
  58. anchors.left: parent.left
  59. anchors.right: clearFilterButton.left
  60. anchors.rightMargin: UM.Theme.getSize("default_margin").width
  61. placeholderText: catalog.i18nc("@label:textbox", "Filter...")
  62. style: TextFieldStyle
  63. {
  64. textColor: UM.Theme.getColor("setting_control_text");
  65. font: UM.Theme.getFont("default");
  66. background: Item {}
  67. }
  68. property var expandedCategories
  69. property bool lastFindingSettings: false
  70. onTextChanged:
  71. {
  72. definitionsModel.filter = {"label": "*" + text};
  73. findingSettings = (text.length > 0);
  74. if(findingSettings != lastFindingSettings)
  75. {
  76. if(findingSettings)
  77. {
  78. expandedCategories = definitionsModel.expanded.slice();
  79. definitionsModel.expanded = ["*"];
  80. definitionsModel.showAncestors = true;
  81. definitionsModel.showAll = true;
  82. }
  83. else
  84. {
  85. definitionsModel.expanded = expandedCategories;
  86. definitionsModel.showAncestors = false;
  87. definitionsModel.showAll = false;
  88. }
  89. lastFindingSettings = findingSettings;
  90. }
  91. }
  92. Keys.onEscapePressed:
  93. {
  94. filter.text = "";
  95. }
  96. }
  97. MouseArea
  98. {
  99. id: hoverMouseArea
  100. anchors.fill: parent
  101. hoverEnabled: true
  102. acceptedButtons: Qt.NoButton
  103. cursorShape: Qt.IBeamCursor
  104. }
  105. UM.SimpleButton
  106. {
  107. id: clearFilterButton
  108. iconSource: UM.Theme.getIcon("cross1")
  109. visible: findingSettings
  110. height: parent.height * 0.4
  111. width: visible ? height : 0
  112. anchors.verticalCenter: parent.verticalCenter
  113. anchors.right: parent.right
  114. anchors.rightMargin: UM.Theme.getSize("default_margin").width
  115. color: UM.Theme.getColor("setting_control_button")
  116. hoverColor: UM.Theme.getColor("setting_control_button_hover")
  117. onClicked:
  118. {
  119. filter.text = "";
  120. filter.forceActiveFocus();
  121. }
  122. }
  123. }
  124. ScrollView
  125. {
  126. anchors.top: filterContainer.bottom;
  127. anchors.bottom: parent.bottom;
  128. anchors.right: parent.right;
  129. anchors.left: parent.left;
  130. anchors.topMargin: filterContainer.visible ? UM.Theme.getSize("default_margin").width : 0
  131. Behavior on anchors.topMargin { NumberAnimation { duration: 100 } }
  132. style: UM.Theme.styles.scrollview;
  133. flickableItem.flickableDirection: Flickable.VerticalFlick;
  134. ListView
  135. {
  136. id: contents
  137. spacing: UM.Theme.getSize("default_lining").height;
  138. cacheBuffer: 1000000; // Set a large cache to effectively just cache every list item.
  139. model: UM.SettingDefinitionsModel
  140. {
  141. id: definitionsModel;
  142. containerId: Cura.MachineManager.activeDefinitionId
  143. visibilityHandler: UM.SettingPreferenceVisibilityHandler { }
  144. exclude: ["machine_settings", "command_line_settings", "infill_mesh", "infill_mesh_order"] // TODO: infill_mesh settigns are excluded hardcoded, but should be based on the fact that settable_globally, settable_per_meshgroup and settable_per_extruder are false.
  145. expanded: Printer.expandedCategories
  146. onExpandedChanged:
  147. {
  148. if(!findingSettings)
  149. {
  150. // Do not change expandedCategories preference while filtering settings
  151. // because all categories are expanded while filtering
  152. Printer.setExpandedCategories(expanded)
  153. }
  154. }
  155. onVisibilityChanged: Cura.SettingInheritanceManager.forceUpdate()
  156. }
  157. delegate: Loader
  158. {
  159. id: delegate
  160. width: UM.Theme.getSize("sidebar").width;
  161. height: provider.properties.enabled == "True" ? UM.Theme.getSize("section").height : - contents.spacing
  162. Behavior on height { NumberAnimation { duration: 100 } }
  163. opacity: provider.properties.enabled == "True" ? 1 : 0
  164. Behavior on opacity { NumberAnimation { duration: 100 } }
  165. enabled:
  166. {
  167. if(!ExtruderManager.activeExtruderStackId && ExtruderManager.extruderCount > 0)
  168. {
  169. // disable all controls on the global tab, except categories
  170. return model.type == "category"
  171. }
  172. return provider.properties.enabled == "True"
  173. }
  174. property var definition: model
  175. property var settingDefinitionsModel: definitionsModel
  176. property var propertyProvider: provider
  177. property var globalPropertyProvider: inheritStackProvider
  178. //Qt5.4.2 and earlier has a bug where this causes a crash: https://bugreports.qt.io/browse/QTBUG-35989
  179. //In addition, while it works for 5.5 and higher, the ordering of the actual combo box drop down changes,
  180. //causing nasty issues when selecting different options. So disable asynchronous loading of enum type completely.
  181. asynchronous: model.type != "enum" && model.type != "extruder"
  182. active: model.type != undefined
  183. source:
  184. {
  185. switch(model.type)
  186. {
  187. case "int":
  188. return "SettingTextField.qml"
  189. case "float":
  190. return "SettingTextField.qml"
  191. case "enum":
  192. return "SettingComboBox.qml"
  193. case "extruder":
  194. return "SettingExtruder.qml"
  195. case "bool":
  196. return "SettingCheckBox.qml"
  197. case "str":
  198. return "SettingTextField.qml"
  199. case "category":
  200. return "SettingCategory.qml"
  201. default:
  202. return "SettingUnknown.qml"
  203. }
  204. }
  205. // Binding to ensure that the right containerstack ID is set for the provider.
  206. // This ensures that if a setting has a limit_to_extruder id (for instance; Support speed points to the
  207. // extruder that actually prints the support, as that is the setting we need to use to calculate the value)
  208. Binding
  209. {
  210. target: provider
  211. property: "containerStackId"
  212. when: model.settable_per_extruder || (inheritStackProvider.properties.limit_to_extruder != null && inheritStackProvider.properties.limit_to_extruder >= 0);
  213. value:
  214. {
  215. if(!model.settable_per_extruder || machineExtruderCount.properties.value == 1)
  216. {
  217. //Not settable per extruder or there only is global, so we must pick global.
  218. return Cura.MachineManager.activeMachineId;
  219. }
  220. if(inheritStackProvider.properties.limit_to_extruder != null && inheritStackProvider.properties.limit_to_extruder >= 0)
  221. {
  222. //We have limit_to_extruder, so pick that stack.
  223. return ExtruderManager.extruderIds[String(inheritStackProvider.properties.limit_to_extruder)];
  224. }
  225. if(ExtruderManager.activeExtruderStackId)
  226. {
  227. //We're on an extruder tab. Pick the current extruder.
  228. return ExtruderManager.activeExtruderStackId;
  229. }
  230. //No extruder tab is selected. Pick the global stack. Shouldn't happen any more since we removed the global tab.
  231. return Cura.MachineManager.activeMachineId;
  232. }
  233. }
  234. // Specialty provider that only watches global_inherits (we cant filter on what property changed we get events
  235. // so we bypass that to make a dedicated provider).
  236. UM.SettingPropertyProvider
  237. {
  238. id: inheritStackProvider
  239. containerStackId: Cura.MachineManager.activeMachineId
  240. key: model.key
  241. watchedProperties: [ "limit_to_extruder" ]
  242. }
  243. UM.SettingPropertyProvider
  244. {
  245. id: provider
  246. containerStackId: Cura.MachineManager.activeMachineId
  247. key: model.key ? model.key : ""
  248. watchedProperties: [ "value", "enabled", "state", "validationState", "settable_per_extruder", "resolve" ]
  249. storeIndex: 0
  250. // Due to the way setPropertyValue works, removeUnusedValue gives the correct output in case of resolve
  251. removeUnusedValue: model.resolve == undefined
  252. }
  253. Connections
  254. {
  255. target: item
  256. onContextMenuRequested:
  257. {
  258. contextMenu.key = model.key;
  259. contextMenu.settingVisible = model.visible;
  260. contextMenu.provider = provider
  261. contextMenu.popup();
  262. }
  263. onShowTooltip: base.showTooltip(delegate, { x: 0, y: delegate.height / 2 }, text)
  264. onHideTooltip: base.hideTooltip()
  265. onShowAllHiddenInheritedSettings:
  266. {
  267. var children_with_override = Cura.SettingInheritanceManager.getChildrenKeysWithOverride(category_id)
  268. for(var i = 0; i < children_with_override.length; i++)
  269. {
  270. definitionsModel.setVisible(children_with_override[i], true)
  271. }
  272. Cura.SettingInheritanceManager.manualRemoveOverride(category_id)
  273. }
  274. }
  275. }
  276. UM.I18nCatalog { id: catalog; name: "uranium"; }
  277. add: Transition {
  278. SequentialAnimation {
  279. NumberAnimation { properties: "height"; from: 0; duration: 100 }
  280. NumberAnimation { properties: "opacity"; from: 0; duration: 100 }
  281. }
  282. }
  283. remove: Transition {
  284. SequentialAnimation {
  285. NumberAnimation { properties: "opacity"; to: 0; duration: 100 }
  286. NumberAnimation { properties: "height"; to: 0; duration: 100 }
  287. }
  288. }
  289. addDisplaced: Transition {
  290. NumberAnimation { properties: "x,y"; duration: 100 }
  291. }
  292. removeDisplaced: Transition {
  293. SequentialAnimation {
  294. PauseAnimation { duration: 100; }
  295. NumberAnimation { properties: "x,y"; duration: 100 }
  296. }
  297. }
  298. Menu
  299. {
  300. id: contextMenu
  301. property string key
  302. property var provider
  303. property bool settingVisible
  304. MenuItem
  305. {
  306. //: Settings context menu action
  307. text: catalog.i18nc("@action:menu", "Copy value to all extruders")
  308. visible: machineExtruderCount.properties.value > 1
  309. enabled: contextMenu.provider != undefined && contextMenu.provider.properties.settable_per_extruder != "False"
  310. onTriggered: Cura.MachineManager.copyValueToExtruders(contextMenu.key)
  311. }
  312. MenuSeparator
  313. {
  314. visible: machineExtruderCount.properties.value > 1
  315. }
  316. MenuItem
  317. {
  318. //: Settings context menu action
  319. visible: !findingSettings;
  320. text: catalog.i18nc("@action:menu", "Hide this setting");
  321. onTriggered: definitionsModel.hide(contextMenu.key);
  322. }
  323. MenuItem
  324. {
  325. //: Settings context menu action
  326. text:
  327. {
  328. if (contextMenu.settingVisible)
  329. {
  330. return catalog.i18nc("@action:menu", "Don't show this setting");
  331. }
  332. else
  333. {
  334. return catalog.i18nc("@action:menu", "Keep this setting visible");
  335. }
  336. }
  337. visible: findingSettings;
  338. onTriggered:
  339. {
  340. if (contextMenu.settingVisible)
  341. {
  342. definitionsModel.hide(contextMenu.key);
  343. }
  344. else
  345. {
  346. definitionsModel.show(contextMenu.key);
  347. }
  348. }
  349. }
  350. MenuItem
  351. {
  352. //: Settings context menu action
  353. text: catalog.i18nc("@action:menu", "Configure setting visiblity...");
  354. onTriggered: Cura.Actions.configureSettingVisibility.trigger(contextMenu);
  355. }
  356. }
  357. UM.SettingPropertyProvider
  358. {
  359. id: machineExtruderCount
  360. containerStackId: Cura.MachineManager.activeMachineId
  361. key: "machine_extruder_count"
  362. watchedProperties: [ "value" ]
  363. storeIndex: 0
  364. }
  365. }
  366. }
  367. }